mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-21 05:06:29 +00:00
Compare commits
24 Commits
aarch-wind
...
v7.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ddbefa88f | ||
|
|
d935115591 | ||
|
|
bd2ea42732 | ||
|
|
3bac38ee34 | ||
|
|
a7a4f6d8f2 | ||
|
|
80b6facbd3 | ||
|
|
7dee898400 | ||
|
|
4c4b2dbe17 | ||
|
|
73ed5ae697 | ||
|
|
833320de64 | ||
|
|
0d6ff8ef8a | ||
|
|
55a207a275 | ||
|
|
f33d1f1cc4 | ||
|
|
19ca2b12fc | ||
|
|
b7d3394464 | ||
|
|
8c33100d7a | ||
|
|
80c406f196 | ||
|
|
bc2c76e5e2 | ||
|
|
4a7bddbc09 | ||
|
|
e316fdbaef | ||
|
|
34106f470f | ||
|
|
d9ab0e7de8 | ||
|
|
5ca1573e2e | ||
|
|
c9ce996626 |
2
.dir-locals.el
Normal file
2
.dir-locals.el
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
((nil . ((eglot-luau-rojo-project-path . "plugin.project.json")
|
||||||
|
(eglot-luau-rojo-sourcemap-enabled . 't))))
|
||||||
6
.github/workflows/changelog.yml
vendored
6
.github/workflows/changelog.yml
vendored
@@ -11,12 +11,12 @@ jobs:
|
|||||||
name: Check Actions
|
name: Check Actions
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Changelog check
|
- name: Changelog check
|
||||||
uses: Zomzog/changelog-checker@v1.3.0
|
uses: Zomzog/changelog-checker@v1.3.0
|
||||||
with:
|
with:
|
||||||
fileName: CHANGELOG.md
|
fileName: CHANGELOG.md
|
||||||
noChangelogLabel: skip changelog
|
noChangelogLabel: skip changelog
|
||||||
checkNotification: Simple
|
checkNotification: Simple
|
||||||
env:
|
env:
|
||||||
|
|||||||
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -30,9 +30,9 @@ jobs:
|
|||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
- name: Setup Aftman
|
- name: Setup Aftman
|
||||||
uses: ok-nick/setup-aftman@v0.3.0
|
uses: ok-nick/setup-aftman@v0.4.2
|
||||||
with:
|
with:
|
||||||
version: 'v0.2.7'
|
version: 'v0.3.0'
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build --locked --verbose
|
run: cargo build --locked --verbose
|
||||||
@@ -56,9 +56,9 @@ jobs:
|
|||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
- name: Setup Aftman
|
- name: Setup Aftman
|
||||||
uses: ok-nick/setup-aftman@v0.3.0
|
uses: ok-nick/setup-aftman@v0.4.2
|
||||||
with:
|
with:
|
||||||
version: 'v0.2.7'
|
version: 'v0.3.0'
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build --locked --verbose
|
run: cargo build --locked --verbose
|
||||||
@@ -81,9 +81,9 @@ jobs:
|
|||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
- name: Setup Aftman
|
- name: Setup Aftman
|
||||||
uses: ok-nick/setup-aftman@v0.3.0
|
uses: ok-nick/setup-aftman@v0.4.2
|
||||||
with:
|
with:
|
||||||
version: 'v0.2.7'
|
version: 'v0.3.0'
|
||||||
|
|
||||||
- name: Stylua
|
- name: Stylua
|
||||||
run: stylua --check plugin/src
|
run: stylua --check plugin/src
|
||||||
|
|||||||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
@@ -26,14 +26,12 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup Aftman
|
- name: Setup Aftman
|
||||||
uses: ok-nick/setup-aftman@v0.1.0
|
uses: ok-nick/setup-aftman@v0.4.2
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
version: 'v0.3.0'
|
||||||
trust-check: false
|
|
||||||
version: 'v0.2.6'
|
|
||||||
|
|
||||||
- name: Build Plugin
|
- name: Build Plugin
|
||||||
run: rojo build plugin --output Rojo.rbxm
|
run: rojo build plugin.project.json --output Rojo.rbxm
|
||||||
|
|
||||||
- name: Upload Plugin to Release
|
- name: Upload Plugin to Release
|
||||||
env:
|
env:
|
||||||
@@ -55,7 +53,7 @@ jobs:
|
|||||||
# https://doc.rust-lang.org/rustc/platform-support.html
|
# https://doc.rust-lang.org/rustc/platform-support.html
|
||||||
include:
|
include:
|
||||||
- host: linux
|
- host: linux
|
||||||
os: ubuntu-20.04
|
os: ubuntu-latest
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
label: linux-x86_64
|
label: linux-x86_64
|
||||||
|
|
||||||
@@ -89,11 +87,9 @@ jobs:
|
|||||||
targets: ${{ matrix.target }}
|
targets: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Setup Aftman
|
- name: Setup Aftman
|
||||||
uses: ok-nick/setup-aftman@v0.1.0
|
uses: ok-nick/setup-aftman@v0.4.2
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
version: 'v0.3.0'
|
||||||
trust-check: false
|
|
||||||
version: 'v0.2.6'
|
|
||||||
|
|
||||||
- name: Build Release
|
- name: Build Release
|
||||||
run: cargo build --release --locked --verbose --target ${{ matrix.target }}
|
run: cargo build --release --locked --verbose --target ${{ matrix.target }}
|
||||||
|
|||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -10,8 +10,8 @@
|
|||||||
/*.rbxl
|
/*.rbxl
|
||||||
/*.rbxlx
|
/*.rbxlx
|
||||||
|
|
||||||
# Test places for the Roblox Studio Plugin
|
# Sourcemap for the Rojo plugin (for better intellisense)
|
||||||
/plugin/*.rbxlx
|
/sourcemap.json
|
||||||
|
|
||||||
# Roblox Studio holds 'lock' files on places
|
# Roblox Studio holds 'lock' files on places
|
||||||
*.rbxl.lock
|
*.rbxl.lock
|
||||||
@@ -19,3 +19,7 @@
|
|||||||
|
|
||||||
# Snapshot files from the 'insta' Rust crate
|
# Snapshot files from the 'insta' Rust crate
|
||||||
**/*.snap.new
|
**/*.snap.new
|
||||||
|
|
||||||
|
# Macos file system junk
|
||||||
|
._*
|
||||||
|
.DS_STORE
|
||||||
|
|||||||
8
.vscode/extensions.json
vendored
Normal file
8
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"JohnnyMorganz.luau-lsp",
|
||||||
|
"JohnnyMorganz.stylua",
|
||||||
|
"Kampfkarren.selene-vscode",
|
||||||
|
"rust-lang.rust-analyzer"
|
||||||
|
]
|
||||||
|
}
|
||||||
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"luau-lsp.sourcemap.rojoProjectFile": "plugin.project.json",
|
||||||
|
"luau-lsp.sourcemap.autogenerate": true
|
||||||
|
}
|
||||||
35
CHANGELOG.md
35
CHANGELOG.md
@@ -1,6 +1,14 @@
|
|||||||
# Rojo Changelog
|
# Rojo Changelog
|
||||||
|
|
||||||
## Unreleased Changes
|
## 7.5.0 - April 25th, 2025
|
||||||
|
* Fixed an edge case that caused model pivots to not be built correctly in some cases ([#1027])
|
||||||
|
* Add `blockedPlaceIds` project config field to allow blocking place ids from being live synced ([#1021])
|
||||||
|
* Adds support for `.plugin.lua(u)` files - this applies the `Plugin` RunContext. ([#1008])
|
||||||
|
* Added support for Roblox's `Content` type. This replaces the old `Content` type with `ContentId` to reflect Roblox's change.
|
||||||
|
If you were previously using the fully-qualified syntax for `Content` you will need to switch it to `ContentId`.
|
||||||
|
* Added support for `Enum` attributes
|
||||||
|
* Significantly improved performance of `.rbxm` parsing
|
||||||
|
* Support for a `$schema` field in all special JSON files (`.project.json`, `.model.json`, and `.meta.json`) ([#974])
|
||||||
* Projects may now manually link `Ref` properties together using `Attributes`. ([#843])
|
* Projects may now manually link `Ref` properties together using `Attributes`. ([#843])
|
||||||
This has two parts: using `id` or `$id` in JSON files or a `Rojo_Target` attribute, an Instance
|
This has two parts: using `id` or `$id` in JSON files or a `Rojo_Target` attribute, an Instance
|
||||||
is given an ID. Then, that ID may be used elsewhere in the project to point to an Instance
|
is given an ID. Then, that ID may be used elsewhere in the project to point to an Instance
|
||||||
@@ -28,6 +36,8 @@
|
|||||||
* Added experimental setting for Auto Connect in playtests ([#840])
|
* Added experimental setting for Auto Connect in playtests ([#840])
|
||||||
* Improved settings UI ([#886])
|
* Improved settings UI ([#886])
|
||||||
* `Open Scripts Externally` option can now be changed while syncing ([#911])
|
* `Open Scripts Externally` option can now be changed while syncing ([#911])
|
||||||
|
* The sync reminder notification will now tell you what was last synced and when ([#987])
|
||||||
|
* Fixed notification and tooltip text sometimes getting cut off ([#988])
|
||||||
* Projects may now specify rules for syncing files as if they had a different file extension. ([#813])
|
* Projects may now specify rules for syncing files as if they had a different file extension. ([#813])
|
||||||
This is specified via a new field on project files, `syncRules`:
|
This is specified via a new field on project files, `syncRules`:
|
||||||
|
|
||||||
@@ -56,7 +66,7 @@
|
|||||||
|
|
||||||
Additionally, the `exclude` field allows files to be excluded from the sync rule if they match a pattern specified by it. If it's not present, all files that match `pattern` will be modified using the sync rule.
|
Additionally, the `exclude` field allows files to be excluded from the sync rule if they match a pattern specified by it. If it's not present, all files that match `pattern` will be modified using the sync rule.
|
||||||
|
|
||||||
The `use` field corresponds to one of the potential file type that Rojo will currently include in a project. Files that match the provided pattern will be treated as if they had the file extension for that file type. A full list is below:
|
The `use` field corresponds to one of the potential file type that Rojo will currently include in a project. Files that match the provided pattern will be treated as if they had the file extension for that file type.
|
||||||
|
|
||||||
| `use` value | file extension |
|
| `use` value | file extension |
|
||||||
|:---------------|:----------------|
|
|:---------------|:----------------|
|
||||||
@@ -73,6 +83,16 @@
|
|||||||
| `project` | `.project.json` |
|
| `project` | `.project.json` |
|
||||||
| `ignore` | None! |
|
| `ignore` | None! |
|
||||||
|
|
||||||
|
Additionally, there are `use` values for specific script types ([#909]):
|
||||||
|
|
||||||
|
| `use` value | script type |
|
||||||
|
|:-------------------------|:---------------------------------------|
|
||||||
|
| `legacyServerScript` | `Script` with `Enum.RunContext.Legacy` |
|
||||||
|
| `legacyClientScript` | `LocalScript` |
|
||||||
|
| `runContextServerScript` | `Script` with `Enum.RunContext.Server` |
|
||||||
|
| `runContextClientScript` | `Script` with `Enum.RunContext.Client` |
|
||||||
|
| `pluginScript` | `Script` with `Enum.RunContext.Plugin` |
|
||||||
|
|
||||||
**All** sync rules are reset between project files, so they must be specified in each one when nesting them. This is to ensure that nothing can break other projects by changing how files are synced!
|
**All** sync rules are reset between project files, so they must be specified in each one when nesting them. This is to ensure that nothing can break other projects by changing how files are synced!
|
||||||
|
|
||||||
[#813]: https://github.com/rojo-rbx/rojo/pull/813
|
[#813]: https://github.com/rojo-rbx/rojo/pull/813
|
||||||
@@ -83,8 +103,19 @@
|
|||||||
[#843]: https://github.com/rojo-rbx/rojo/pull/843
|
[#843]: https://github.com/rojo-rbx/rojo/pull/843
|
||||||
[#883]: https://github.com/rojo-rbx/rojo/pull/883
|
[#883]: https://github.com/rojo-rbx/rojo/pull/883
|
||||||
[#886]: https://github.com/rojo-rbx/rojo/pull/886
|
[#886]: https://github.com/rojo-rbx/rojo/pull/886
|
||||||
|
[#909]: https://github.com/rojo-rbx/rojo/pull/909
|
||||||
[#911]: https://github.com/rojo-rbx/rojo/pull/911
|
[#911]: https://github.com/rojo-rbx/rojo/pull/911
|
||||||
[#915]: https://github.com/rojo-rbx/rojo/pull/915
|
[#915]: https://github.com/rojo-rbx/rojo/pull/915
|
||||||
|
[#974]: https://github.com/rojo-rbx/rojo/pull/974
|
||||||
|
[#987]: https://github.com/rojo-rbx/rojo/pull/987
|
||||||
|
[#988]: https://github.com/rojo-rbx/rojo/pull/988
|
||||||
|
[#1008]: https://github.com/rojo-rbx/rojo/pull/1008
|
||||||
|
[#1021]: https://github.com/rojo-rbx/rojo/pull/1021
|
||||||
|
[#1027]: https://github.com/rojo-rbx/rojo/pull/1027
|
||||||
|
|
||||||
|
## [7.4.4] - August 22nd, 2024
|
||||||
|
* Fixed issue with reading attributes from `Lighting` in new place files
|
||||||
|
* `Instance.Archivable` will now default to `true` when building a project into a binary (`rbxm`/`rbxl`) file rather than `false`.
|
||||||
|
|
||||||
## [7.4.3] - August 6th, 2024
|
## [7.4.3] - August 6th, 2024
|
||||||
* Fixed issue with building binary files introduced in 7.4.2
|
* Fixed issue with building binary files introduced in 7.4.2
|
||||||
|
|||||||
@@ -16,6 +16,23 @@ You'll want these tools to work on Rojo:
|
|||||||
* Latest stable Rust compiler
|
* Latest stable Rust compiler
|
||||||
* Latest stable [Rojo](https://github.com/rojo-rbx/rojo)
|
* Latest stable [Rojo](https://github.com/rojo-rbx/rojo)
|
||||||
* [Foreman](https://github.com/Roblox/foreman)
|
* [Foreman](https://github.com/Roblox/foreman)
|
||||||
|
* [Luau Language Server](https://github.com/JohnnyMorganz/luau-lsp) (Only needed if working on the Studio plugin.)
|
||||||
|
|
||||||
|
When working on the Studio plugin, we recommend using this command to automatically rebuild the plugin when you save a change:
|
||||||
|
|
||||||
|
*(Make sure you've enabled the Studio setting to reload plugins on file change!)*
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/watch-build-plugin.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also run the plugin's unit tests with the following:
|
||||||
|
|
||||||
|
*(Make sure you have `run-in-roblox` installed first!)*
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/unit-test-plugin.sh
|
||||||
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
Documentation impacts way more people than the individual lines of code we write.
|
Documentation impacts way more people than the individual lines of code we write.
|
||||||
|
|||||||
180
Cargo.lock
generated
180
Cargo.lock
generated
@@ -17,6 +17,19 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"getrandom",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
@@ -171,6 +184,10 @@ name = "cc"
|
|||||||
version = "1.0.89"
|
version = "1.0.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
|
checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
|
||||||
|
dependencies = [
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -492,7 +509,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.4.1",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -935,6 +952,15 @@ version = "1.0.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jod-thread"
|
name = "jod-thread"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@@ -962,9 +988,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazycell"
|
name = "lazycell"
|
||||||
@@ -986,7 +1012,7 @@ checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.4.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1001,6 +1027,16 @@ version = "0.4.13"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.21"
|
version = "0.4.21"
|
||||||
@@ -1241,6 +1277,29 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.5.10",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.52.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
@@ -1310,6 +1369,12 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plotters"
|
name = "plotters"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
@@ -1498,10 +1563,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_binary"
|
name = "rbx_binary"
|
||||||
version = "0.7.7"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b85057e8ff75a1ce99248200c4b3c7b481a3d52f921f1053ecd67921dcc7930"
|
checksum = "9573fee5e073d7b303f475c285197fdc8179468de66ca60ee115a58fbac99296"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"log",
|
"log",
|
||||||
"lz4",
|
"lz4",
|
||||||
"profiling",
|
"profiling",
|
||||||
@@ -1509,23 +1575,26 @@ dependencies = [
|
|||||||
"rbx_reflection",
|
"rbx_reflection",
|
||||||
"rbx_reflection_database",
|
"rbx_reflection_database",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_dom_weak"
|
name = "rbx_dom_weak"
|
||||||
version = "2.9.0"
|
version = "3.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fcd2a17d09e46af0805f8b311a926402172b97e8d9388745c9adf8f448901841"
|
checksum = "04425cf6e9376e5486f4fb35906c120d1b1b45618a490318cf563fab1fa230a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"rbx_types",
|
"rbx_types",
|
||||||
"serde",
|
"serde",
|
||||||
|
"ustr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_reflection"
|
name = "rbx_reflection"
|
||||||
version = "4.7.0"
|
version = "5.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8118ac6021d700e8debe324af6b40ecfd2cef270a00247849dbdfeebb0802677"
|
checksum = "1b6d0d62baa613556b058a5f94a53b01cf0ccde0ea327ce03056e335b982e77e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rbx_types",
|
"rbx_types",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -1534,9 +1603,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_reflection_database"
|
name = "rbx_reflection_database"
|
||||||
version = "0.2.12+roblox-638"
|
version = "1.0.2+roblox-670"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e29381d675420e841f8c02db5755cbb2545ed3e13f56c539546dc58702b512a"
|
checksum = "5349b19e5e94fbcaba7a52175263ab64011e0a13f17ff57729f2f560ccdec615"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"rbx_reflection",
|
"rbx_reflection",
|
||||||
@@ -1546,9 +1615,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_types"
|
name = "rbx_types"
|
||||||
version = "1.10.0"
|
version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e30f49b2a3bb667e4074ba73c2dfb8ca0873f610b448ccf318a240acfdec6c73"
|
checksum = "78e4fdde46493def107e5f923d82e813dec9b3eef52c2f75fbad3a716023eda2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
@@ -1561,10 +1630,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_xml"
|
name = "rbx_xml"
|
||||||
version = "0.13.5"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b14b3027bc9ccd82e2fc854c8bcd25ed58318e570c355bf2cf63df9cdbd5ba8"
|
checksum = "bb623833c31cc43bbdaeb32f5e91db8ecd63fc46e438d0d268baf9e61539cf1c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
"base64 0.13.1",
|
"base64 0.13.1",
|
||||||
"log",
|
"log",
|
||||||
"rbx_dom_weak",
|
"rbx_dom_weak",
|
||||||
@@ -1582,6 +1652,15 @@ dependencies = [
|
|||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@@ -1752,7 +1831,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rojo"
|
name = "rojo"
|
||||||
version = "7.4.0"
|
version = "7.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
@@ -1896,6 +1975,12 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sct"
|
name = "sct"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@@ -2393,6 +2478,19 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ustr"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18b19e258aa08450f93369cf56dd78063586adf19e92a75b338a800f799a0208"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
"byteorder",
|
||||||
|
"lazy_static",
|
||||||
|
"parking_lot",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.7.0"
|
version = "1.7.0"
|
||||||
@@ -2784,3 +2882,51 @@ name = "yansi"
|
|||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.7.35"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.78",
|
||||||
|
"quote 1.0.35",
|
||||||
|
"syn 2.0.52",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "7.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.15+zstd.1.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|||||||
13
Cargo.toml
13
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rojo"
|
name = "rojo"
|
||||||
version = "7.4.0"
|
version = "7.5.0"
|
||||||
rust-version = "1.70.0"
|
rust-version = "1.70.0"
|
||||||
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
|
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
|
||||||
description = "Enables professional-grade development tools for Roblox developers"
|
description = "Enables professional-grade development tools for Roblox developers"
|
||||||
@@ -51,11 +51,11 @@ memofs = { version = "0.3.0", path = "crates/memofs" }
|
|||||||
# rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" }
|
# rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" }
|
||||||
# rbx_xml = { path = "../rbx-dom/rbx_xml" }
|
# rbx_xml = { path = "../rbx-dom/rbx_xml" }
|
||||||
|
|
||||||
rbx_binary = "0.7.7"
|
rbx_binary = "1.0.0"
|
||||||
rbx_dom_weak = "2.9.0"
|
rbx_dom_weak = "3.0.0"
|
||||||
rbx_reflection = "4.7.0"
|
rbx_reflection = "5.0.0"
|
||||||
rbx_reflection_database = "0.2.12"
|
rbx_reflection_database = "1.0.2"
|
||||||
rbx_xml = "0.13.5"
|
rbx_xml = "1.0.0"
|
||||||
|
|
||||||
anyhow = "1.0.80"
|
anyhow = "1.0.80"
|
||||||
backtrace = "0.3.69"
|
backtrace = "0.3.69"
|
||||||
@@ -70,7 +70,6 @@ humantime = "2.1.0"
|
|||||||
hyper = { version = "0.14.28", features = ["server", "tcp", "http1"] }
|
hyper = { version = "0.14.28", features = ["server", "tcp", "http1"] }
|
||||||
jod-thread = "0.1.2"
|
jod-thread = "0.1.2"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
maplit = "1.0.2"
|
|
||||||
num_cpus = "1.16.0"
|
num_cpus = "1.16.0"
|
||||||
opener = "0.5.2"
|
opener = "0.5.2"
|
||||||
rayon = "1.9.0"
|
rayon = "1.9.0"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[tools]
|
[tools]
|
||||||
rojo = "rojo-rbx/rojo@7.3.0"
|
rojo = "rojo-rbx/rojo@7.4.1"
|
||||||
selene = "Kampfkarren/selene@0.26.1"
|
selene = "Kampfkarren/selene@0.27.1"
|
||||||
stylua = "JohnnyMorganz/stylua@0.18.2"
|
stylua = "JohnnyMorganz/stylua@0.20.0"
|
||||||
run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0"
|
run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0"
|
||||||
|
|||||||
28
build.rs
28
build.rs
@@ -20,6 +20,10 @@ fn snapshot_from_fs_path(path: &Path) -> io::Result<VfsSnapshot> {
|
|||||||
|
|
||||||
let file_name = entry.file_name().to_str().unwrap().to_owned();
|
let file_name = entry.file_name().to_str().unwrap().to_owned();
|
||||||
|
|
||||||
|
if file_name.starts_with(".git") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// We can skip any TestEZ test files since they aren't necessary for
|
// We can skip any TestEZ test files since they aren't necessary for
|
||||||
// the plugin to run.
|
// the plugin to run.
|
||||||
if file_name.ends_with(".spec.lua") || file_name.ends_with(".spec.luau") {
|
if file_name.ends_with(".spec.lua") || file_name.ends_with(".spec.luau") {
|
||||||
@@ -41,12 +45,12 @@ fn snapshot_from_fs_path(path: &Path) -> io::Result<VfsSnapshot> {
|
|||||||
fn main() -> Result<(), anyhow::Error> {
|
fn main() -> Result<(), anyhow::Error> {
|
||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
|
|
||||||
let root_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
|
let root_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||||
let plugin_root = PathBuf::from(root_dir).join("plugin");
|
let plugin_dir = root_dir.join("plugin");
|
||||||
|
|
||||||
let our_version = Version::parse(env::var_os("CARGO_PKG_VERSION").unwrap().to_str().unwrap())?;
|
let our_version = Version::parse(env::var_os("CARGO_PKG_VERSION").unwrap().to_str().unwrap())?;
|
||||||
let plugin_version =
|
let plugin_version =
|
||||||
Version::parse(fs::read_to_string(plugin_root.join("Version.txt"))?.trim())?;
|
Version::parse(fs::read_to_string(plugin_dir.join("Version.txt"))?.trim())?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
our_version, plugin_version,
|
our_version, plugin_version,
|
||||||
@@ -54,14 +58,16 @@ fn main() -> Result<(), anyhow::Error> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let snapshot = VfsSnapshot::dir(hashmap! {
|
let snapshot = VfsSnapshot::dir(hashmap! {
|
||||||
"default.project.json" => snapshot_from_fs_path(&plugin_root.join("default.project.json"))?,
|
"default.project.json" => snapshot_from_fs_path(&root_dir.join("plugin.project.json"))?,
|
||||||
"fmt" => snapshot_from_fs_path(&plugin_root.join("fmt"))?,
|
"plugin" => VfsSnapshot::dir(hashmap! {
|
||||||
"http" => snapshot_from_fs_path(&plugin_root.join("http"))?,
|
"fmt" => snapshot_from_fs_path(&plugin_dir.join("fmt"))?,
|
||||||
"log" => snapshot_from_fs_path(&plugin_root.join("log"))?,
|
"http" => snapshot_from_fs_path(&plugin_dir.join("http"))?,
|
||||||
"rbx_dom_lua" => snapshot_from_fs_path(&plugin_root.join("rbx_dom_lua"))?,
|
"log" => snapshot_from_fs_path(&plugin_dir.join("log"))?,
|
||||||
"src" => snapshot_from_fs_path(&plugin_root.join("src"))?,
|
"rbx_dom_lua" => snapshot_from_fs_path(&plugin_dir.join("rbx_dom_lua"))?,
|
||||||
"Packages" => snapshot_from_fs_path(&plugin_root.join("Packages"))?,
|
"src" => snapshot_from_fs_path(&plugin_dir.join("src"))?,
|
||||||
"Version.txt" => snapshot_from_fs_path(&plugin_root.join("Version.txt"))?,
|
"Packages" => snapshot_from_fs_path(&plugin_dir.join("Packages"))?,
|
||||||
|
"Version.txt" => snapshot_from_fs_path(&plugin_dir.join("Version.txt"))?,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
let out_path = Path::new(&out_dir).join("plugin.bincode");
|
let out_path = Path::new(&out_dir).join("plugin.bincode");
|
||||||
|
|||||||
@@ -5,19 +5,13 @@ use serde::Serialize;
|
|||||||
/// Enables redacting any value that serializes as a string.
|
/// Enables redacting any value that serializes as a string.
|
||||||
///
|
///
|
||||||
/// Used for transforming Rojo instance IDs into something deterministic.
|
/// Used for transforming Rojo instance IDs into something deterministic.
|
||||||
|
#[derive(Default)]
|
||||||
pub struct RedactionMap {
|
pub struct RedactionMap {
|
||||||
ids: HashMap<String, usize>,
|
ids: HashMap<String, usize>,
|
||||||
last_id: usize,
|
last_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RedactionMap {
|
impl RedactionMap {
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
ids: HashMap::new(),
|
|
||||||
last_id: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_redacted_value(&self, id: impl ToString) -> Option<String> {
|
pub fn get_redacted_value(&self, id: impl ToString) -> Option<String> {
|
||||||
let id = id.to_string();
|
let id = id.to_string();
|
||||||
|
|
||||||
|
|||||||
@@ -3,25 +3,25 @@
|
|||||||
"tree": {
|
"tree": {
|
||||||
"$className": "Folder",
|
"$className": "Folder",
|
||||||
"Plugin": {
|
"Plugin": {
|
||||||
"$path": "src"
|
"$path": "plugin/src"
|
||||||
},
|
},
|
||||||
"Packages": {
|
"Packages": {
|
||||||
"$path": "Packages",
|
"$path": "plugin/Packages",
|
||||||
"Log": {
|
"Log": {
|
||||||
"$path": "log"
|
"$path": "plugin/log"
|
||||||
},
|
},
|
||||||
"Http": {
|
"Http": {
|
||||||
"$path": "http"
|
"$path": "plugin/http"
|
||||||
},
|
},
|
||||||
"Fmt": {
|
"Fmt": {
|
||||||
"$path": "fmt"
|
"$path": "plugin/fmt"
|
||||||
},
|
},
|
||||||
"RbxDom": {
|
"RbxDom": {
|
||||||
"$path": "rbx_dom_lua"
|
"$path": "plugin/rbx_dom_lua"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Version": {
|
"Version": {
|
||||||
"$path": "Version.txt"
|
"$path": "plugin/Version.txt"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
7.4.0
|
7.5.0
|
||||||
@@ -70,7 +70,7 @@ local function debugImpl(buffer, value, extendedForm)
|
|||||||
elseif valueType == "table" then
|
elseif valueType == "table" then
|
||||||
local valueMeta = getmetatable(value)
|
local valueMeta = getmetatable(value)
|
||||||
|
|
||||||
if valueMeta ~= nil and valueMeta.__fmtDebug ~= nil then
|
if valueMeta ~= nil and valueMeta.__fmtDebug ~= nil then
|
||||||
-- This type implement's the metamethod we made up to line up with
|
-- This type implement's the metamethod we made up to line up with
|
||||||
-- Rust's 'Debug' trait.
|
-- Rust's 'Debug' trait.
|
||||||
|
|
||||||
@@ -242,4 +242,4 @@ return {
|
|||||||
debugOutputBuffer = debugOutputBuffer,
|
debugOutputBuffer = debugOutputBuffer,
|
||||||
fmt = fmt,
|
fmt = fmt,
|
||||||
debugify = debugify,
|
debugify = debugify,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,4 +31,4 @@ function Response:json()
|
|||||||
return HttpService:JSONDecode(self.body)
|
return HttpService:JSONDecode(self.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
return Response
|
return Response
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ return function()
|
|||||||
it("should load", function()
|
it("should load", function()
|
||||||
require(script.Parent)
|
require(script.Parent)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -57,4 +57,4 @@ function Log.error(template, ...)
|
|||||||
error(Fmt.fmt(template, ...))
|
error(Fmt.fmt(template, ...))
|
||||||
end
|
end
|
||||||
|
|
||||||
return Log
|
return Log
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ return function()
|
|||||||
it("should load", function()
|
it("should load", function()
|
||||||
require(script.Parent)
|
require(script.Parent)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -188,6 +188,38 @@ types = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
Content = {
|
Content = {
|
||||||
|
fromPod = function(pod): Content
|
||||||
|
if type(pod) == "string" then
|
||||||
|
if pod == "None" then
|
||||||
|
return Content.none
|
||||||
|
else
|
||||||
|
error(`unexpected Content value '{pod}'`)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local ty, value = next(pod)
|
||||||
|
if ty == "Uri" then
|
||||||
|
return Content.fromUri(value)
|
||||||
|
elseif ty == "Object" then
|
||||||
|
error("Object deserializing is not currently implemented")
|
||||||
|
else
|
||||||
|
error(`Unknown Content type '{ty}' (could not deserialize)`)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
toPod = function(roblox: Content)
|
||||||
|
if roblox.SourceType == Enum.ContentSourceType.None then
|
||||||
|
return "None"
|
||||||
|
elseif roblox.SourceType == Enum.ContentSourceType.Uri then
|
||||||
|
return { Uri = roblox.Uri }
|
||||||
|
elseif roblox.SourceType == Enum.ContentSourceType.Object then
|
||||||
|
error("Object serializing is not currently implemented")
|
||||||
|
else
|
||||||
|
error(`Unknown Content type '{roblox.SourceType} (could not serialize)`)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
ContentId = {
|
||||||
fromPod = identity,
|
fromPod = identity,
|
||||||
toPod = identity,
|
toPod = identity,
|
||||||
},
|
},
|
||||||
@@ -205,6 +237,19 @@ types = {
|
|||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
EnumItem = {
|
||||||
|
fromPod = function(pod)
|
||||||
|
return Enum[pod.type]:FromValue(pod.value)
|
||||||
|
end,
|
||||||
|
|
||||||
|
toPod = function(roblox)
|
||||||
|
return {
|
||||||
|
type = tostring(roblox.EnumType),
|
||||||
|
value = roblox.Value,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
Faces = {
|
Faces = {
|
||||||
fromPod = function(pod)
|
fromPod = function(pod)
|
||||||
local faces = {}
|
local faces = {}
|
||||||
@@ -300,7 +345,12 @@ types = {
|
|||||||
local keypoints = {}
|
local keypoints = {}
|
||||||
|
|
||||||
for index, keypoint in ipairs(pod.keypoints) do
|
for index, keypoint in ipairs(pod.keypoints) do
|
||||||
keypoints[index] = NumberSequenceKeypoint.new(keypoint.time, keypoint.value, keypoint.envelope)
|
-- TODO: Add a test for NaN or Infinity values and envelopes
|
||||||
|
-- Right now it isn't possible because it'd fail the roundtrip.
|
||||||
|
-- It's more important that it works right now, though.
|
||||||
|
local value = keypoint.value or 0
|
||||||
|
local envelope = keypoint.envelope or 0
|
||||||
|
keypoints[index] = NumberSequenceKeypoint.new(keypoint.time, value, envelope)
|
||||||
end
|
end
|
||||||
|
|
||||||
return NumberSequence.new(keypoints)
|
return NumberSequence.new(keypoints)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Error.Kind = {
|
|||||||
UnknownProperty = "UnknownProperty",
|
UnknownProperty = "UnknownProperty",
|
||||||
PropertyNotReadable = "PropertyNotReadable",
|
PropertyNotReadable = "PropertyNotReadable",
|
||||||
PropertyNotWritable = "PropertyNotWritable",
|
PropertyNotWritable = "PropertyNotWritable",
|
||||||
|
CannotParseBinaryString = "CannotParseBinaryString",
|
||||||
Roblox = "Roblox",
|
Roblox = "Roblox",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,12 @@
|
|||||||
0.0
|
0.0
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"TestEnumItem": {
|
||||||
|
"EnumItem": {
|
||||||
|
"type": "Material",
|
||||||
|
"value": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
"TestNumber": {
|
"TestNumber": {
|
||||||
"Float64": 1337.0
|
"Float64": 1337.0
|
||||||
},
|
},
|
||||||
@@ -170,9 +176,23 @@
|
|||||||
},
|
},
|
||||||
"ty": "ColorSequence"
|
"ty": "ColorSequence"
|
||||||
},
|
},
|
||||||
"Content": {
|
"ContentId": {
|
||||||
"value": {
|
"value": {
|
||||||
"Content": "rbxassetid://12345"
|
"ContentId": "rbxassetid://12345"
|
||||||
|
},
|
||||||
|
"ty": "ContentId"
|
||||||
|
},
|
||||||
|
"Content_None": {
|
||||||
|
"value": {
|
||||||
|
"Content": "None"
|
||||||
|
},
|
||||||
|
"ty": "Content"
|
||||||
|
},
|
||||||
|
"Content_Uri": {
|
||||||
|
"value": {
|
||||||
|
"Content": {
|
||||||
|
"Uri": "rbxasset://abc/123.rojo"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ty": "Content"
|
"ty": "Content"
|
||||||
},
|
},
|
||||||
@@ -182,6 +202,15 @@
|
|||||||
},
|
},
|
||||||
"ty": "Enum"
|
"ty": "Enum"
|
||||||
},
|
},
|
||||||
|
"EnumItem": {
|
||||||
|
"value": {
|
||||||
|
"EnumItem": {
|
||||||
|
"type": "Material",
|
||||||
|
"value": 256
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ty": "EnumItem"
|
||||||
|
},
|
||||||
"Faces": {
|
"Faces": {
|
||||||
"value": {
|
"value": {
|
||||||
"Faces": [
|
"Faces": [
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
local CollectionService = game:GetService("CollectionService")
|
local CollectionService = game:GetService("CollectionService")
|
||||||
local ScriptEditorService = game:GetService("ScriptEditorService")
|
local ScriptEditorService = game:GetService("ScriptEditorService")
|
||||||
|
|
||||||
|
local Error = require(script.Parent.Error)
|
||||||
|
|
||||||
--- A list of `Enum.Material` values that are used for Terrain.MaterialColors
|
--- A list of `Enum.Material` values that are used for Terrain.MaterialColors
|
||||||
local TERRAIN_MATERIAL_COLORS = {
|
local TERRAIN_MATERIAL_COLORS = {
|
||||||
Enum.Material.Grass,
|
Enum.Material.Grass,
|
||||||
@@ -51,6 +53,10 @@ return {
|
|||||||
return true, instance:GetAttributes()
|
return true, instance:GetAttributes()
|
||||||
end,
|
end,
|
||||||
write = function(instance, _, value)
|
write = function(instance, _, value)
|
||||||
|
if typeof(value) ~= "table" then
|
||||||
|
return false, Error.new(Error.Kind.CannotParseBinaryString)
|
||||||
|
end
|
||||||
|
|
||||||
local existing = instance:GetAttributes()
|
local existing = instance:GetAttributes()
|
||||||
local didAllWritesSucceed = true
|
local didAllWritesSucceed = true
|
||||||
|
|
||||||
@@ -160,9 +166,14 @@ return {
|
|||||||
return true, colors
|
return true, colors
|
||||||
end,
|
end,
|
||||||
write = function(instance: Terrain, _, value: { [Enum.Material]: Color3 })
|
write = function(instance: Terrain, _, value: { [Enum.Material]: Color3 })
|
||||||
|
if typeof(value) ~= "table" then
|
||||||
|
return false, Error.new(Error.Kind.CannotParseBinaryString)
|
||||||
|
end
|
||||||
|
|
||||||
for material, color in value do
|
for material, color in value do
|
||||||
instance:SetMaterialColor(material, color)
|
instance:SetMaterialColor(material, color)
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end,
|
end,
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||||
|
|
||||||
local TestEZ = require(ReplicatedStorage.Packages.TestEZ)
|
local TestEZ = require(ReplicatedStorage.Packages:WaitForChild("TestEZ", 10))
|
||||||
|
|
||||||
local Rojo = ReplicatedStorage.Rojo
|
local Rojo = ReplicatedStorage.Rojo
|
||||||
|
|
||||||
|
|||||||
@@ -45,14 +45,7 @@ end
|
|||||||
|
|
||||||
local function rejectWrongPlaceId(infoResponseBody)
|
local function rejectWrongPlaceId(infoResponseBody)
|
||||||
if infoResponseBody.expectedPlaceIds ~= nil then
|
if infoResponseBody.expectedPlaceIds ~= nil then
|
||||||
local foundId = false
|
local foundId = table.find(infoResponseBody.expectedPlaceIds, game.PlaceId)
|
||||||
|
|
||||||
for _, id in ipairs(infoResponseBody.expectedPlaceIds) do
|
|
||||||
if id == game.PlaceId then
|
|
||||||
foundId = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not foundId then
|
if not foundId then
|
||||||
local idList = {}
|
local idList = {}
|
||||||
@@ -62,10 +55,30 @@ local function rejectWrongPlaceId(infoResponseBody)
|
|||||||
|
|
||||||
local message = (
|
local message = (
|
||||||
"Found a Rojo server, but its project is set to only be used with a specific list of places."
|
"Found a Rojo server, but its project is set to only be used with a specific list of places."
|
||||||
.. "\nYour place ID is %s, but needs to be one of these:"
|
.. "\nYour place ID is %u, but needs to be one of these:"
|
||||||
.. "\n%s"
|
.. "\n%s"
|
||||||
.. "\n\nTo change this list, edit 'servePlaceIds' in your .project.json file."
|
.. "\n\nTo change this list, edit 'servePlaceIds' in your .project.json file."
|
||||||
):format(tostring(game.PlaceId), table.concat(idList, "\n"))
|
):format(game.PlaceId, table.concat(idList, "\n"))
|
||||||
|
|
||||||
|
return Promise.reject(message)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if infoResponseBody.unexpectedPlaceIds ~= nil then
|
||||||
|
local foundId = table.find(infoResponseBody.unexpectedPlaceIds, game.PlaceId)
|
||||||
|
|
||||||
|
if foundId then
|
||||||
|
local idList = {}
|
||||||
|
for _, id in ipairs(infoResponseBody.unexpectedPlaceIds) do
|
||||||
|
table.insert(idList, "- " .. tostring(id))
|
||||||
|
end
|
||||||
|
|
||||||
|
local message = (
|
||||||
|
"Found a Rojo server, but its project is set to not be used with a specific list of places."
|
||||||
|
.. "\nYour place ID is %u, but needs to not be one of these:"
|
||||||
|
.. "\n%s"
|
||||||
|
.. "\n\nTo change this list, edit 'blockedPlaceIds' in your .project.json file."
|
||||||
|
):format(game.PlaceId, table.concat(idList, "\n"))
|
||||||
|
|
||||||
return Promise.reject(message)
|
return Promise.reject(message)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ end
|
|||||||
|
|
||||||
function Checkbox:render()
|
function Checkbox:render()
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
theme = theme.Checkbox
|
local checkboxTheme = theme.Checkbox
|
||||||
|
|
||||||
local activeTransparency = Roact.joinBindings({
|
local activeTransparency = Roact.joinBindings({
|
||||||
self.binding:map(function(value)
|
self.binding:map(function(value)
|
||||||
@@ -57,20 +57,21 @@ function Checkbox:render()
|
|||||||
end,
|
end,
|
||||||
}, {
|
}, {
|
||||||
StateTip = e(Tooltip.Trigger, {
|
StateTip = e(Tooltip.Trigger, {
|
||||||
text = (if self.props.locked then "[LOCKED] " else "")
|
text = (if self.props.locked
|
||||||
.. (if self.props.active then "Enabled" else "Disabled"),
|
then (self.props.lockedTooltip or "(Cannot be changed right now)") .. "\n"
|
||||||
|
else "") .. (if self.props.active then "Enabled" else "Disabled"),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Active = e(SlicedImage, {
|
Active = e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBackground,
|
slice = Assets.Slices.RoundedBackground,
|
||||||
color = theme.Active.BackgroundColor,
|
color = checkboxTheme.Active.BackgroundColor,
|
||||||
transparency = activeTransparency,
|
transparency = activeTransparency,
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
zIndex = 2,
|
zIndex = 2,
|
||||||
}, {
|
}, {
|
||||||
Icon = e("ImageLabel", {
|
Icon = e("ImageLabel", {
|
||||||
Image = if self.props.locked then Assets.Images.Checkbox.Locked else Assets.Images.Checkbox.Active,
|
Image = if self.props.locked then Assets.Images.Checkbox.Locked else Assets.Images.Checkbox.Active,
|
||||||
ImageColor3 = theme.Active.IconColor,
|
ImageColor3 = checkboxTheme.Active.IconColor,
|
||||||
ImageTransparency = activeTransparency,
|
ImageTransparency = activeTransparency,
|
||||||
|
|
||||||
Size = UDim2.new(0, 16, 0, 16),
|
Size = UDim2.new(0, 16, 0, 16),
|
||||||
@@ -83,7 +84,7 @@ function Checkbox:render()
|
|||||||
|
|
||||||
Inactive = e(SlicedImage, {
|
Inactive = e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBorder,
|
slice = Assets.Slices.RoundedBorder,
|
||||||
color = theme.Inactive.BorderColor,
|
color = checkboxTheme.Inactive.BorderColor,
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
}, {
|
}, {
|
||||||
@@ -91,7 +92,7 @@ function Checkbox:render()
|
|||||||
Image = if self.props.locked
|
Image = if self.props.locked
|
||||||
then Assets.Images.Checkbox.Locked
|
then Assets.Images.Checkbox.Locked
|
||||||
else Assets.Images.Checkbox.Inactive,
|
else Assets.Images.Checkbox.Inactive,
|
||||||
ImageColor3 = theme.Inactive.IconColor,
|
ImageColor3 = checkboxTheme.Inactive.IconColor,
|
||||||
ImageTransparency = self.props.transparency,
|
ImageTransparency = self.props.transparency,
|
||||||
|
|
||||||
Size = UDim2.new(0, 16, 0, 16),
|
Size = UDim2.new(0, 16, 0, 16),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
|
local Plugin = Rojo.Plugin
|
||||||
local Packages = Rojo.Packages
|
local Packages = Rojo.Packages
|
||||||
|
|
||||||
local Roact = require(Packages.Roact)
|
local Roact = require(Packages.Roact)
|
||||||
@@ -7,6 +8,8 @@ Highlighter.matchStudioSettings()
|
|||||||
|
|
||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
|
|
||||||
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
|
||||||
local CodeLabel = Roact.PureComponent:extend("CodeLabel")
|
local CodeLabel = Roact.PureComponent:extend("CodeLabel")
|
||||||
|
|
||||||
function CodeLabel:init()
|
function CodeLabel:init()
|
||||||
@@ -40,22 +43,24 @@ function CodeLabel:updateHighlights()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function CodeLabel:render()
|
function CodeLabel:render()
|
||||||
return e("TextLabel", {
|
return Theme.with(function(theme)
|
||||||
Size = self.props.size,
|
return e("TextLabel", {
|
||||||
Position = self.props.position,
|
Size = self.props.size,
|
||||||
Text = self.props.text,
|
Position = self.props.position,
|
||||||
BackgroundTransparency = 1,
|
Text = self.props.text,
|
||||||
Font = Enum.Font.RobotoMono,
|
BackgroundTransparency = 1,
|
||||||
TextSize = 16,
|
FontFace = theme.Font.Code,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextSize = theme.TextSize.Code,
|
||||||
TextYAlignment = Enum.TextYAlignment.Top,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextColor3 = Color3.fromRGB(255, 255, 255),
|
TextYAlignment = Enum.TextYAlignment.Top,
|
||||||
[Roact.Ref] = self.labelRef,
|
TextColor3 = Color3.fromRGB(255, 255, 255),
|
||||||
}, {
|
[Roact.Ref] = self.labelRef,
|
||||||
SyntaxHighlights = e("Folder", {
|
}, {
|
||||||
[Roact.Ref] = self.highlightsRef,
|
SyntaxHighlights = e("Folder", {
|
||||||
}),
|
[Roact.Ref] = self.highlightsRef,
|
||||||
})
|
}),
|
||||||
|
})
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
return CodeLabel
|
return CodeLabel
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
local TextService = game:GetService("TextService")
|
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
local Plugin = Rojo.Plugin
|
local Plugin = Rojo.Plugin
|
||||||
local Packages = Rojo.Packages
|
local Packages = Rojo.Packages
|
||||||
@@ -10,9 +8,11 @@ local Flipper = require(Packages.Flipper)
|
|||||||
local Assets = require(Plugin.Assets)
|
local Assets = require(Plugin.Assets)
|
||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
local bindingUtil = require(Plugin.App.bindingUtil)
|
local bindingUtil = require(Plugin.App.bindingUtil)
|
||||||
|
local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
|
||||||
|
|
||||||
local SlicedImage = require(script.Parent.SlicedImage)
|
local SlicedImage = require(script.Parent.SlicedImage)
|
||||||
local ScrollingFrame = require(script.Parent.ScrollingFrame)
|
local ScrollingFrame = require(script.Parent.ScrollingFrame)
|
||||||
|
local Tooltip = require(script.Parent.Tooltip)
|
||||||
|
|
||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
|
|
||||||
@@ -44,29 +44,29 @@ end
|
|||||||
|
|
||||||
function Dropdown:render()
|
function Dropdown:render()
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
theme = theme.Dropdown
|
local dropdownTheme = theme.Dropdown
|
||||||
|
|
||||||
local optionButtons = {}
|
local optionButtons = {}
|
||||||
local width = -1
|
local width = -1
|
||||||
for i, option in self.props.options do
|
for i, option in self.props.options do
|
||||||
local text = tostring(option or "")
|
local text = tostring(option or "")
|
||||||
local textSize = TextService:GetTextSize(text, 15, Enum.Font.GothamMedium, Vector2.new(math.huge, 20))
|
local textBounds = getTextBoundsAsync(text, theme.Font.Main, theme.TextSize.Body, math.huge)
|
||||||
if textSize.X > width then
|
if textBounds.X > width then
|
||||||
width = textSize.X
|
width = textBounds.X
|
||||||
end
|
end
|
||||||
|
|
||||||
optionButtons[text] = e("TextButton", {
|
optionButtons[text] = e("TextButton", {
|
||||||
Text = text,
|
Text = text,
|
||||||
LayoutOrder = i,
|
LayoutOrder = i,
|
||||||
Size = UDim2.new(1, 0, 0, 24),
|
Size = UDim2.new(1, 0, 0, 24),
|
||||||
BackgroundColor3 = theme.BackgroundColor,
|
BackgroundColor3 = dropdownTheme.BackgroundColor,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
BackgroundTransparency = self.props.transparency,
|
BackgroundTransparency = self.props.transparency,
|
||||||
BorderSizePixel = 0,
|
BorderSizePixel = 0,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = dropdownTheme.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Body,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
|
|
||||||
[Roact.Event.Activated] = function()
|
[Roact.Event.Activated] = function()
|
||||||
if self.props.locked then
|
if self.props.locked then
|
||||||
@@ -103,13 +103,13 @@ function Dropdown:render()
|
|||||||
}, {
|
}, {
|
||||||
Border = e(SlicedImage, {
|
Border = e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBorder,
|
slice = Assets.Slices.RoundedBorder,
|
||||||
color = theme.BorderColor,
|
color = dropdownTheme.BorderColor,
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
}, {
|
}, {
|
||||||
DropArrow = e("ImageLabel", {
|
DropArrow = e("ImageLabel", {
|
||||||
Image = if self.props.locked then Assets.Images.Dropdown.Locked else Assets.Images.Dropdown.Arrow,
|
Image = if self.props.locked then Assets.Images.Dropdown.Locked else Assets.Images.Dropdown.Arrow,
|
||||||
ImageColor3 = theme.IconColor,
|
ImageColor3 = dropdownTheme.IconColor,
|
||||||
ImageTransparency = self.props.transparency,
|
ImageTransparency = self.props.transparency,
|
||||||
|
|
||||||
Size = UDim2.new(0, 18, 0, 18),
|
Size = UDim2.new(0, 18, 0, 18),
|
||||||
@@ -120,15 +120,21 @@ function Dropdown:render()
|
|||||||
end),
|
end),
|
||||||
|
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
|
}, {
|
||||||
|
StateTip = if self.props.locked
|
||||||
|
then e(Tooltip.Trigger, {
|
||||||
|
text = self.props.lockedTooltip or "(Cannot be changed right now)",
|
||||||
|
})
|
||||||
|
else nil,
|
||||||
}),
|
}),
|
||||||
Active = e("TextLabel", {
|
Active = e("TextLabel", {
|
||||||
Size = UDim2.new(1, -30, 1, 0),
|
Size = UDim2.new(1, -30, 1, 0),
|
||||||
Position = UDim2.new(0, 6, 0, 0),
|
Position = UDim2.new(0, 6, 0, 0),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = self.props.active,
|
Text = self.props.active,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = dropdownTheme.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
}),
|
}),
|
||||||
@@ -136,7 +142,7 @@ function Dropdown:render()
|
|||||||
Options = if self.state.open
|
Options = if self.state.open
|
||||||
then e(SlicedImage, {
|
then e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBackground,
|
slice = Assets.Slices.RoundedBackground,
|
||||||
color = theme.BackgroundColor,
|
color = dropdownTheme.BackgroundColor,
|
||||||
position = UDim2.new(1, 0, 1, 3),
|
position = UDim2.new(1, 0, 1, 3),
|
||||||
size = self.openBinding:map(function(a)
|
size = self.openBinding:map(function(a)
|
||||||
return UDim2.new(1, 0, a * math.min(3, #self.props.options), 0)
|
return UDim2.new(1, 0, a * math.min(3, #self.props.options), 0)
|
||||||
@@ -145,7 +151,7 @@ function Dropdown:render()
|
|||||||
}, {
|
}, {
|
||||||
Border = e(SlicedImage, {
|
Border = e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBorder,
|
slice = Assets.Slices.RoundedBorder,
|
||||||
color = theme.BorderColor,
|
color = dropdownTheme.BorderColor,
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ local function Header(props)
|
|||||||
|
|
||||||
Version = e("TextLabel", {
|
Version = e("TextLabel", {
|
||||||
Text = Version.display(Config.version),
|
Text = Version.display(Config.version),
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Header.VersionColor,
|
TextColor3 = theme.Header.VersionColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
|
|
||||||
Size = UDim2.new(1, 0, 0, 14),
|
Size = UDim2.new(1, 0, 0, theme.TextSize.Body),
|
||||||
|
|
||||||
LayoutOrder = 2,
|
LayoutOrder = 2,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ local function ViewDiffButton(props)
|
|||||||
Label = e("TextLabel", {
|
Label = e("TextLabel", {
|
||||||
Text = "View Diff",
|
Text = "View Diff",
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -170,8 +170,8 @@ function ChangeList:render()
|
|||||||
ColumnA = e("TextLabel", {
|
ColumnA = e("TextLabel", {
|
||||||
Text = tostring(headerRow[1]),
|
Text = tostring(headerRow[1]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = theme.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -182,8 +182,8 @@ function ChangeList:render()
|
|||||||
ColumnB = e("TextLabel", {
|
ColumnB = e("TextLabel", {
|
||||||
Text = tostring(headerRow[2]),
|
Text = tostring(headerRow[2]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = theme.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -194,8 +194,8 @@ function ChangeList:render()
|
|||||||
ColumnC = e("TextLabel", {
|
ColumnC = e("TextLabel", {
|
||||||
Text = tostring(headerRow[3]),
|
Text = tostring(headerRow[3]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = theme.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -230,8 +230,8 @@ function ChangeList:render()
|
|||||||
ColumnA = e("TextLabel", {
|
ColumnA = e("TextLabel", {
|
||||||
Text = (if isWarning then "⚠ " else "") .. tostring(values[1]),
|
Text = (if isWarning then "⚠ " else "") .. tostring(values[1]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = if isWarning then theme.Diff.Warning else theme.TextColor,
|
TextColor3 = if isWarning then theme.Diff.Warning else theme.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ local function DisplayValue(props)
|
|||||||
Label = e("TextLabel", {
|
Label = e("TextLabel", {
|
||||||
Text = string.format("%d, %d, %d", props.value.R * 255, props.value.G * 255, props.value.B * 255),
|
Text = string.format("%d, %d, %d", props.value.R * 255, props.value.G * 255, props.value.B * 255),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = props.textColor,
|
TextColor3 = props.textColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -90,8 +90,8 @@ local function DisplayValue(props)
|
|||||||
return e("TextLabel", {
|
return e("TextLabel", {
|
||||||
Text = textRepresentation,
|
Text = textRepresentation,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = props.textColor,
|
TextColor3 = props.textColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -112,8 +112,8 @@ local function DisplayValue(props)
|
|||||||
return e("TextLabel", {
|
return e("TextLabel", {
|
||||||
Text = textRepresentation,
|
Text = textRepresentation,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = props.textColor,
|
TextColor3 = props.textColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
|
|||||||
@@ -225,8 +225,8 @@ function DomLabel:render()
|
|||||||
Text = (if props.isWarning then "⚠ " else "") .. props.name,
|
Text = (if props.isWarning then "⚠ " else "") .. props.name,
|
||||||
RichText = true,
|
RichText = true,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = if props.patchType then Enum.Font.GothamBold else Enum.Font.GothamMedium,
|
FontFace = if props.patchType then theme.Font.Bold else theme.Font.Main,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = color,
|
TextColor3 = color,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -251,11 +251,11 @@ function DomLabel:render()
|
|||||||
then e("TextLabel", {
|
then e("TextLabel", {
|
||||||
Text = props.changeInfo.edits .. if props.changeInfo.failed then "," else "",
|
Text = props.changeInfo.edits .. if props.changeInfo.failed then "," else "",
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.SubTextColor,
|
TextColor3 = theme.SubTextColor,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
Size = UDim2.new(0, 0, 0, 16),
|
Size = UDim2.new(0, 0, 0, theme.TextSize.Body),
|
||||||
AutomaticSize = Enum.AutomaticSize.X,
|
AutomaticSize = Enum.AutomaticSize.X,
|
||||||
LayoutOrder = 2,
|
LayoutOrder = 2,
|
||||||
})
|
})
|
||||||
@@ -264,11 +264,11 @@ function DomLabel:render()
|
|||||||
then e("TextLabel", {
|
then e("TextLabel", {
|
||||||
Text = props.changeInfo.failed,
|
Text = props.changeInfo.failed,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Diff.Warning,
|
TextColor3 = theme.Diff.Warning,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
Size = UDim2.new(0, 0, 0, 16),
|
Size = UDim2.new(0, 0, 0, theme.TextSize.Body),
|
||||||
AutomaticSize = Enum.AutomaticSize.X,
|
AutomaticSize = Enum.AutomaticSize.X,
|
||||||
LayoutOrder = 6,
|
LayoutOrder = 6,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -124,8 +124,8 @@ function PatchVisualizer:render()
|
|||||||
CleanMerge = e("TextLabel", {
|
CleanMerge = e("TextLabel", {
|
||||||
Visible = #scrollElements == 0,
|
Visible = #scrollElements == 0,
|
||||||
Text = "No changes to sync, project is up to date.",
|
Text = "No changes to sync, project is up to date.",
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Medium,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = theme.TextColor,
|
||||||
TextWrapped = true,
|
TextWrapped = true,
|
||||||
Size = UDim2.new(1, 0, 1, 0),
|
Size = UDim2.new(1, 0, 1, 0),
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
local TextService = game:GetService("TextService")
|
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
local Plugin = Rojo.Plugin
|
local Plugin = Rojo.Plugin
|
||||||
local Packages = Rojo.Packages
|
local Packages = Rojo.Packages
|
||||||
@@ -11,6 +9,7 @@ local StringDiff = require(script:FindFirstChild("StringDiff"))
|
|||||||
|
|
||||||
local Timer = require(Plugin.Timer)
|
local Timer = require(Plugin.Timer)
|
||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
|
||||||
|
|
||||||
local CodeLabel = require(Plugin.App.Components.CodeLabel)
|
local CodeLabel = require(Plugin.App.Components.CodeLabel)
|
||||||
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
||||||
@@ -32,7 +31,6 @@ function StringDiffVisualizer:init()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
self:calculateContentSize()
|
|
||||||
self:updateScriptBackground()
|
self:updateScriptBackground()
|
||||||
|
|
||||||
self:setState({
|
self:setState({
|
||||||
@@ -54,7 +52,6 @@ end
|
|||||||
|
|
||||||
function StringDiffVisualizer:didUpdate(previousProps)
|
function StringDiffVisualizer:didUpdate(previousProps)
|
||||||
if previousProps.oldString ~= self.props.oldString or previousProps.newString ~= self.props.newString then
|
if previousProps.oldString ~= self.props.oldString or previousProps.newString ~= self.props.newString then
|
||||||
self:calculateContentSize()
|
|
||||||
local add, remove = self:calculateDiffLines()
|
local add, remove = self:calculateDiffLines()
|
||||||
self:setState({
|
self:setState({
|
||||||
add = add,
|
add = add,
|
||||||
@@ -63,11 +60,11 @@ function StringDiffVisualizer:didUpdate(previousProps)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function StringDiffVisualizer:calculateContentSize()
|
function StringDiffVisualizer:calculateContentSize(theme)
|
||||||
local oldString, newString = self.props.oldString, self.props.newString
|
local oldString, newString = self.props.oldString, self.props.newString
|
||||||
|
|
||||||
local oldStringBounds = TextService:GetTextSize(oldString, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999))
|
local oldStringBounds = getTextBoundsAsync(oldString, theme.Font.Code, theme.TextSize.Code, math.huge)
|
||||||
local newStringBounds = TextService:GetTextSize(newString, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999))
|
local newStringBounds = getTextBoundsAsync(newString, theme.Font.Code, theme.TextSize.Code, math.huge)
|
||||||
|
|
||||||
self.setContentSize(
|
self.setContentSize(
|
||||||
Vector2.new(math.max(oldStringBounds.X, newStringBounds.X), math.max(oldStringBounds.Y, newStringBounds.Y))
|
Vector2.new(math.max(oldStringBounds.X, newStringBounds.X), math.max(oldStringBounds.Y, newStringBounds.Y))
|
||||||
@@ -143,6 +140,8 @@ function StringDiffVisualizer:render()
|
|||||||
local oldString, newString = self.props.oldString, self.props.newString
|
local oldString, newString = self.props.oldString, self.props.newString
|
||||||
|
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
|
self:calculateContentSize(theme)
|
||||||
|
|
||||||
return e(BorderedContainer, {
|
return e(BorderedContainer, {
|
||||||
size = self.props.size,
|
size = self.props.size,
|
||||||
position = self.props.position,
|
position = self.props.position,
|
||||||
|
|||||||
@@ -152,8 +152,8 @@ function Array:render()
|
|||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = "Old",
|
Text = "Old",
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
}),
|
}),
|
||||||
@@ -163,8 +163,8 @@ function Array:render()
|
|||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = "New",
|
Text = "New",
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -112,8 +112,8 @@ function Dictionary:render()
|
|||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = key,
|
Text = key,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
}),
|
}),
|
||||||
@@ -157,8 +157,8 @@ function Dictionary:render()
|
|||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = "Key",
|
Text = "Key",
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
}),
|
}),
|
||||||
@@ -168,8 +168,8 @@ function Dictionary:render()
|
|||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = "Old",
|
Text = "Old",
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
}),
|
}),
|
||||||
@@ -179,8 +179,8 @@ function Dictionary:render()
|
|||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = "New",
|
Text = "New",
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ local Packages = Rojo.Packages
|
|||||||
|
|
||||||
local Roact = require(Packages.Roact)
|
local Roact = require(Packages.Roact)
|
||||||
|
|
||||||
|
local Theme = require(Plugin.App.Theme)
|
||||||
local Assets = require(Plugin.Assets)
|
local Assets = require(Plugin.Assets)
|
||||||
|
|
||||||
local SlicedImage = require(Plugin.App.Components.SlicedImage)
|
local SlicedImage = require(Plugin.App.Components.SlicedImage)
|
||||||
@@ -11,46 +12,48 @@ local SlicedImage = require(Plugin.App.Components.SlicedImage)
|
|||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
|
|
||||||
return function(props)
|
return function(props)
|
||||||
return e(SlicedImage, {
|
return Theme.with(function(theme)
|
||||||
slice = Assets.Slices.RoundedBackground,
|
return e(SlicedImage, {
|
||||||
color = props.color,
|
slice = Assets.Slices.RoundedBackground,
|
||||||
transparency = props.transparency:map(function(transparency)
|
color = props.color,
|
||||||
return 0.9 + (0.1 * transparency)
|
transparency = props.transparency:map(function(transparency)
|
||||||
end),
|
return 0.9 + (0.1 * transparency)
|
||||||
layoutOrder = props.layoutOrder,
|
end),
|
||||||
position = props.position,
|
layoutOrder = props.layoutOrder,
|
||||||
anchorPoint = props.anchorPoint,
|
position = props.position,
|
||||||
size = UDim2.new(0, 0, 0, 16),
|
anchorPoint = props.anchorPoint,
|
||||||
automaticSize = Enum.AutomaticSize.X,
|
size = UDim2.new(0, 0, 0, theme.TextSize.Medium),
|
||||||
}, {
|
automaticSize = Enum.AutomaticSize.X,
|
||||||
Padding = e("UIPadding", {
|
}, {
|
||||||
PaddingLeft = UDim.new(0, 4),
|
Padding = e("UIPadding", {
|
||||||
PaddingRight = UDim.new(0, 4),
|
PaddingLeft = UDim.new(0, 4),
|
||||||
PaddingTop = UDim.new(0, 2),
|
PaddingRight = UDim.new(0, 4),
|
||||||
PaddingBottom = UDim.new(0, 2),
|
PaddingTop = UDim.new(0, 2),
|
||||||
}),
|
PaddingBottom = UDim.new(0, 2),
|
||||||
Icon = if props.icon
|
}),
|
||||||
then e("ImageLabel", {
|
Icon = if props.icon
|
||||||
Size = UDim2.new(0, 12, 0, 12),
|
then e("ImageLabel", {
|
||||||
Position = UDim2.new(0, 0, 0.5, 0),
|
Size = UDim2.new(0, 12, 0, 12),
|
||||||
AnchorPoint = Vector2.new(0, 0.5),
|
Position = UDim2.new(0, 0, 0.5, 0),
|
||||||
Image = props.icon,
|
AnchorPoint = Vector2.new(0, 0.5),
|
||||||
|
Image = props.icon,
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
ImageColor3 = props.color,
|
||||||
|
ImageTransparency = props.transparency,
|
||||||
|
})
|
||||||
|
else nil,
|
||||||
|
Text = e("TextLabel", {
|
||||||
|
Text = props.text,
|
||||||
|
FontFace = theme.Font.Main,
|
||||||
|
TextSize = theme.TextSize.Small,
|
||||||
|
TextColor3 = props.color,
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Center,
|
||||||
|
TextTransparency = props.transparency,
|
||||||
|
Size = UDim2.new(0, 0, 1, 0),
|
||||||
|
Position = UDim2.new(0, if props.icon then 15 else 0, 0, 0),
|
||||||
|
AutomaticSize = Enum.AutomaticSize.X,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
ImageColor3 = props.color,
|
}),
|
||||||
ImageTransparency = props.transparency,
|
})
|
||||||
})
|
end)
|
||||||
else nil,
|
|
||||||
Text = e("TextLabel", {
|
|
||||||
Text = props.text,
|
|
||||||
Font = Enum.Font.GothamMedium,
|
|
||||||
TextSize = 12,
|
|
||||||
TextColor3 = props.color,
|
|
||||||
TextXAlignment = Enum.TextXAlignment.Center,
|
|
||||||
TextTransparency = props.transparency,
|
|
||||||
Size = UDim2.new(0, 0, 1, 0),
|
|
||||||
Position = UDim2.new(0, if props.icon then 15 else 0, 0, 0),
|
|
||||||
AutomaticSize = Enum.AutomaticSize.X,
|
|
||||||
BackgroundTransparency = 1,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
local TextService = game:GetService("TextService")
|
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
local Plugin = Rojo.Plugin
|
local Plugin = Rojo.Plugin
|
||||||
local Packages = Rojo.Packages
|
local Packages = Rojo.Packages
|
||||||
@@ -10,6 +8,7 @@ local Flipper = require(Packages.Flipper)
|
|||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
local Assets = require(Plugin.Assets)
|
local Assets = require(Plugin.Assets)
|
||||||
local bindingUtil = require(Plugin.App.bindingUtil)
|
local bindingUtil = require(Plugin.App.bindingUtil)
|
||||||
|
local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
|
||||||
|
|
||||||
local SlicedImage = require(script.Parent.SlicedImage)
|
local SlicedImage = require(script.Parent.SlicedImage)
|
||||||
local TouchRipple = require(script.Parent.TouchRipple)
|
local TouchRipple = require(script.Parent.TouchRipple)
|
||||||
@@ -41,18 +40,17 @@ end
|
|||||||
|
|
||||||
function TextButton:render()
|
function TextButton:render()
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
local textSize =
|
local textBounds = getTextBoundsAsync(self.props.text, theme.Font.Main, theme.TextSize.Large, math.huge)
|
||||||
TextService:GetTextSize(self.props.text, 18, Enum.Font.GothamMedium, Vector2.new(math.huge, math.huge))
|
|
||||||
|
|
||||||
local style = self.props.style
|
local style = self.props.style
|
||||||
|
|
||||||
theme = theme.Button[style]
|
local buttonTheme = theme.Button[style]
|
||||||
|
|
||||||
local bindingHover = bindingUtil.deriveProperty(self.binding, "hover")
|
local bindingHover = bindingUtil.deriveProperty(self.binding, "hover")
|
||||||
local bindingEnabled = bindingUtil.deriveProperty(self.binding, "enabled")
|
local bindingEnabled = bindingUtil.deriveProperty(self.binding, "enabled")
|
||||||
|
|
||||||
return e("ImageButton", {
|
return e("ImageButton", {
|
||||||
Size = UDim2.new(0, 15 + textSize.X + 15, 0, 34),
|
Size = UDim2.new(0, (theme.TextSize.Body * 2) + textBounds.X, 0, 34),
|
||||||
Position = self.props.position,
|
Position = self.props.position,
|
||||||
AnchorPoint = self.props.anchorPoint,
|
AnchorPoint = self.props.anchorPoint,
|
||||||
|
|
||||||
@@ -74,18 +72,22 @@ function TextButton:render()
|
|||||||
end,
|
end,
|
||||||
}, {
|
}, {
|
||||||
TouchRipple = e(TouchRipple, {
|
TouchRipple = e(TouchRipple, {
|
||||||
color = theme.ActionFillColor,
|
color = buttonTheme.ActionFillColor,
|
||||||
transparency = self.props.transparency:map(function(value)
|
transparency = self.props.transparency:map(function(value)
|
||||||
return bindingUtil.blendAlpha({ theme.ActionFillTransparency, value })
|
return bindingUtil.blendAlpha({ buttonTheme.ActionFillTransparency, value })
|
||||||
end),
|
end),
|
||||||
zIndex = 2,
|
zIndex = 2,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Text = e("TextLabel", {
|
Text = e("TextLabel", {
|
||||||
Text = self.props.text,
|
Text = self.props.text,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 18,
|
TextSize = theme.TextSize.Large,
|
||||||
TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.TextColor, theme.Disabled.TextColor),
|
TextColor3 = bindingUtil.mapLerp(
|
||||||
|
bindingEnabled,
|
||||||
|
buttonTheme.Enabled.TextColor,
|
||||||
|
buttonTheme.Disabled.TextColor
|
||||||
|
),
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
|
|
||||||
Size = UDim2.new(1, 0, 1, 0),
|
Size = UDim2.new(1, 0, 1, 0),
|
||||||
@@ -95,7 +97,11 @@ function TextButton:render()
|
|||||||
|
|
||||||
Border = style == "Bordered" and e(SlicedImage, {
|
Border = style == "Bordered" and e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBorder,
|
slice = Assets.Slices.RoundedBorder,
|
||||||
color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BorderColor, theme.Disabled.BorderColor),
|
color = bindingUtil.mapLerp(
|
||||||
|
bindingEnabled,
|
||||||
|
buttonTheme.Enabled.BorderColor,
|
||||||
|
buttonTheme.Disabled.BorderColor
|
||||||
|
),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
@@ -105,14 +111,18 @@ function TextButton:render()
|
|||||||
|
|
||||||
HoverOverlay = e(SlicedImage, {
|
HoverOverlay = e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBackground,
|
slice = Assets.Slices.RoundedBackground,
|
||||||
color = theme.ActionFillColor,
|
color = buttonTheme.ActionFillColor,
|
||||||
transparency = Roact.joinBindings({
|
transparency = Roact.joinBindings({
|
||||||
hover = bindingHover:map(function(value)
|
hover = bindingHover:map(function(value)
|
||||||
return 1 - value
|
return 1 - value
|
||||||
end),
|
end),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
}):map(function(values)
|
}):map(function(values)
|
||||||
return bindingUtil.blendAlpha({ theme.ActionFillTransparency, values.hover, values.transparency })
|
return bindingUtil.blendAlpha({
|
||||||
|
buttonTheme.ActionFillTransparency,
|
||||||
|
values.hover,
|
||||||
|
values.transparency,
|
||||||
|
})
|
||||||
end),
|
end),
|
||||||
|
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
@@ -124,8 +134,8 @@ function TextButton:render()
|
|||||||
slice = Assets.Slices.RoundedBackground,
|
slice = Assets.Slices.RoundedBackground,
|
||||||
color = bindingUtil.mapLerp(
|
color = bindingUtil.mapLerp(
|
||||||
bindingEnabled,
|
bindingEnabled,
|
||||||
theme.Enabled.BackgroundColor,
|
buttonTheme.Enabled.BackgroundColor,
|
||||||
theme.Disabled.BackgroundColor
|
buttonTheme.Disabled.BackgroundColor
|
||||||
),
|
),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
|
|||||||
@@ -38,14 +38,18 @@ end
|
|||||||
|
|
||||||
function TextInput:render()
|
function TextInput:render()
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
theme = theme.TextInput
|
local textInputTheme = theme.TextInput
|
||||||
|
|
||||||
local bindingHover = bindingUtil.deriveProperty(self.binding, "hover")
|
local bindingHover = bindingUtil.deriveProperty(self.binding, "hover")
|
||||||
local bindingEnabled = bindingUtil.deriveProperty(self.binding, "enabled")
|
local bindingEnabled = bindingUtil.deriveProperty(self.binding, "enabled")
|
||||||
|
|
||||||
return e(SlicedImage, {
|
return e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBorder,
|
slice = Assets.Slices.RoundedBorder,
|
||||||
color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BorderColor, theme.Disabled.BorderColor),
|
color = bindingUtil.mapLerp(
|
||||||
|
bindingEnabled,
|
||||||
|
textInputTheme.Enabled.BorderColor,
|
||||||
|
textInputTheme.Disabled.BorderColor
|
||||||
|
),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
size = self.props.size or UDim2.new(1, 0, 1, 0),
|
size = self.props.size or UDim2.new(1, 0, 1, 0),
|
||||||
@@ -55,14 +59,18 @@ function TextInput:render()
|
|||||||
}, {
|
}, {
|
||||||
HoverOverlay = e(SlicedImage, {
|
HoverOverlay = e(SlicedImage, {
|
||||||
slice = Assets.Slices.RoundedBackground,
|
slice = Assets.Slices.RoundedBackground,
|
||||||
color = theme.ActionFillColor,
|
color = textInputTheme.ActionFillColor,
|
||||||
transparency = Roact.joinBindings({
|
transparency = Roact.joinBindings({
|
||||||
hover = bindingHover:map(function(value)
|
hover = bindingHover:map(function(value)
|
||||||
return 1 - value
|
return 1 - value
|
||||||
end),
|
end),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
}):map(function(values)
|
}):map(function(values)
|
||||||
return bindingUtil.blendAlpha({ theme.ActionFillTransparency, values.hover, values.transparency })
|
return bindingUtil.blendAlpha({
|
||||||
|
textInputTheme.ActionFillTransparency,
|
||||||
|
values.hover,
|
||||||
|
values.transparency,
|
||||||
|
})
|
||||||
end),
|
end),
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
zIndex = -1,
|
zIndex = -1,
|
||||||
@@ -72,14 +80,18 @@ function TextInput:render()
|
|||||||
Size = UDim2.fromScale(1, 1),
|
Size = UDim2.fromScale(1, 1),
|
||||||
Text = self.props.text,
|
Text = self.props.text,
|
||||||
PlaceholderText = self.props.placeholder,
|
PlaceholderText = self.props.placeholder,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Disabled.TextColor, theme.Enabled.TextColor),
|
TextColor3 = bindingUtil.mapLerp(
|
||||||
|
bindingEnabled,
|
||||||
|
textInputTheme.Disabled.TextColor,
|
||||||
|
textInputTheme.Enabled.TextColor
|
||||||
|
),
|
||||||
PlaceholderColor3 = bindingUtil.mapLerp(
|
PlaceholderColor3 = bindingUtil.mapLerp(
|
||||||
bindingEnabled,
|
bindingEnabled,
|
||||||
theme.Disabled.PlaceholderColor,
|
textInputTheme.Disabled.PlaceholderColor,
|
||||||
theme.Enabled.PlaceholderColor
|
textInputTheme.Enabled.PlaceholderColor
|
||||||
),
|
),
|
||||||
TextSize = 18,
|
TextSize = theme.TextSize.Large,
|
||||||
TextEditable = self.props.enabled,
|
TextEditable = self.props.enabled,
|
||||||
ClearTextOnFocus = self.props.clearTextOnFocus,
|
ClearTextOnFocus = self.props.clearTextOnFocus,
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
local TextService = game:GetService("TextService")
|
|
||||||
local HttpService = game:GetService("HttpService")
|
local HttpService = game:GetService("HttpService")
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
@@ -8,6 +7,8 @@ local Packages = Rojo.Packages
|
|||||||
local Roact = require(Packages.Roact)
|
local Roact = require(Packages.Roact)
|
||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
|
||||||
|
local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
|
||||||
|
|
||||||
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
||||||
|
|
||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
@@ -21,50 +22,48 @@ local Y_OVERLAP = 10 -- Let the triangle tail piece overlap the target a bit to
|
|||||||
local TooltipContext = Roact.createContext({})
|
local TooltipContext = Roact.createContext({})
|
||||||
|
|
||||||
local function Popup(props)
|
local function Popup(props)
|
||||||
local textSize = TextService:GetTextSize(
|
|
||||||
props.Text,
|
|
||||||
16,
|
|
||||||
Enum.Font.GothamMedium,
|
|
||||||
Vector2.new(math.min(props.parentSize.X, 160), math.huge)
|
|
||||||
) + TEXT_PADDING + (Vector2.one * 2)
|
|
||||||
|
|
||||||
local trigger = props.Trigger:getValue()
|
|
||||||
|
|
||||||
local spaceBelow = props.parentSize.Y
|
|
||||||
- (trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y - Y_OVERLAP + TAIL_SIZE)
|
|
||||||
local spaceAbove = trigger.AbsolutePosition.Y + Y_OVERLAP - TAIL_SIZE
|
|
||||||
|
|
||||||
-- If there's not enough space below, and there's more space above, then show the tooltip above the trigger
|
|
||||||
local displayAbove = spaceBelow < textSize.Y and spaceAbove > spaceBelow
|
|
||||||
|
|
||||||
local X = math.clamp(props.Position.X - X_OFFSET, 0, props.parentSize.X - textSize.X)
|
|
||||||
local Y = 0
|
|
||||||
|
|
||||||
if displayAbove then
|
|
||||||
Y = math.max(trigger.AbsolutePosition.Y - TAIL_SIZE - textSize.Y + Y_OVERLAP, 0)
|
|
||||||
else
|
|
||||||
Y = math.min(
|
|
||||||
trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y + TAIL_SIZE - Y_OVERLAP,
|
|
||||||
props.parentSize.Y - textSize.Y
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
|
local textXSpace = math.min(props.parentSize.X, 250) - TEXT_PADDING.X
|
||||||
|
local textBounds = getTextBoundsAsync(props.Text, theme.Font.Main, theme.TextSize.Medium, textXSpace)
|
||||||
|
local contentSize = textBounds + TEXT_PADDING + (Vector2.one * 2)
|
||||||
|
|
||||||
|
local trigger = props.Trigger:getValue()
|
||||||
|
|
||||||
|
local spaceBelow = props.parentSize.Y
|
||||||
|
- (trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y - Y_OVERLAP + TAIL_SIZE)
|
||||||
|
local spaceAbove = trigger.AbsolutePosition.Y + Y_OVERLAP - TAIL_SIZE
|
||||||
|
|
||||||
|
-- If there's not enough space below, and there's more space above, then show the tooltip above the trigger
|
||||||
|
local displayAbove = spaceBelow < contentSize.Y and spaceAbove > spaceBelow
|
||||||
|
|
||||||
|
local X = math.clamp(props.Position.X - X_OFFSET, 0, math.max(props.parentSize.X - contentSize.X, 1))
|
||||||
|
local Y = 0
|
||||||
|
|
||||||
|
if displayAbove then
|
||||||
|
Y = math.max(trigger.AbsolutePosition.Y - TAIL_SIZE - contentSize.Y + Y_OVERLAP, 0)
|
||||||
|
else
|
||||||
|
Y = math.min(
|
||||||
|
trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y + TAIL_SIZE - Y_OVERLAP,
|
||||||
|
props.parentSize.Y - contentSize.Y
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
return e(BorderedContainer, {
|
return e(BorderedContainer, {
|
||||||
position = UDim2.fromOffset(X, Y),
|
position = UDim2.fromOffset(X, Y),
|
||||||
size = UDim2.fromOffset(textSize.X, textSize.Y),
|
size = UDim2.fromOffset(contentSize.X, contentSize.Y),
|
||||||
transparency = props.transparency,
|
transparency = props.transparency,
|
||||||
}, {
|
}, {
|
||||||
Label = e("TextLabel", {
|
Label = e("TextLabel", {
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Position = UDim2.fromScale(0.5, 0.5),
|
Position = UDim2.fromScale(0.5, 0.5),
|
||||||
Size = UDim2.new(1, -TEXT_PADDING.X, 1, -TEXT_PADDING.Y),
|
|
||||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||||
|
Size = UDim2.fromOffset(textBounds.X, textBounds.Y),
|
||||||
Text = props.Text,
|
Text = props.Text,
|
||||||
TextSize = 16,
|
TextSize = theme.TextSize.Medium,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextWrapped = true,
|
TextWrapped = true,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
TextYAlignment = Enum.TextYAlignment.Center,
|
||||||
TextColor3 = theme.Button.Bordered.Enabled.TextColor,
|
TextColor3 = theme.Button.Bordered.Enabled.TextColor,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
}),
|
}),
|
||||||
@@ -72,8 +71,8 @@ local function Popup(props)
|
|||||||
Tail = e("ImageLabel", {
|
Tail = e("ImageLabel", {
|
||||||
ZIndex = 100,
|
ZIndex = 100,
|
||||||
Position = if displayAbove
|
Position = if displayAbove
|
||||||
then UDim2.new(0, math.clamp(props.Position.X - X, 6, textSize.X - 6), 1, -1)
|
then UDim2.new(0, math.clamp(props.Position.X - X, 6, contentSize.X - 6), 1, -1)
|
||||||
else UDim2.new(0, math.clamp(props.Position.X - X, 6, textSize.X - 6), 0, -TAIL_SIZE + 1),
|
else UDim2.new(0, math.clamp(props.Position.X - X, 6, contentSize.X - 6), 0, -TAIL_SIZE + 1),
|
||||||
Size = UDim2.fromOffset(TAIL_SIZE, TAIL_SIZE),
|
Size = UDim2.fromOffset(TAIL_SIZE, TAIL_SIZE),
|
||||||
AnchorPoint = Vector2.new(0.5, 0),
|
AnchorPoint = Vector2.new(0.5, 0),
|
||||||
Rotation = if displayAbove then 180 else 0,
|
Rotation = if displayAbove then 180 else 0,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
local TextService = game:GetService("TextService")
|
|
||||||
local StudioService = game:GetService("StudioService")
|
local StudioService = game:GetService("StudioService")
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
@@ -9,10 +8,10 @@ local Roact = require(Packages.Roact)
|
|||||||
local Flipper = require(Packages.Flipper)
|
local Flipper = require(Packages.Flipper)
|
||||||
local Log = require(Packages.Log)
|
local Log = require(Packages.Log)
|
||||||
|
|
||||||
local bindingUtil = require(script.Parent.bindingUtil)
|
|
||||||
|
|
||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
local Assets = require(Plugin.Assets)
|
local Assets = require(Plugin.Assets)
|
||||||
|
local bindingUtil = require(Plugin.App.bindingUtil)
|
||||||
|
local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
|
||||||
|
|
||||||
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
||||||
local TextButton = require(Plugin.App.Components.TextButton)
|
local TextButton = require(Plugin.App.Components.TextButton)
|
||||||
@@ -86,51 +85,46 @@ function Notification:render()
|
|||||||
return 1 - value
|
return 1 - value
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local textBounds = TextService:GetTextSize(self.props.text, 15, Enum.Font.GothamMedium, Vector2.new(350, 700))
|
return Theme.with(function(theme)
|
||||||
|
local actionButtons = {}
|
||||||
|
local buttonsX = 0
|
||||||
|
if self.props.actions then
|
||||||
|
local count = 0
|
||||||
|
for key, action in self.props.actions do
|
||||||
|
actionButtons[key] = e(TextButton, {
|
||||||
|
text = action.text,
|
||||||
|
style = action.style,
|
||||||
|
onClick = function()
|
||||||
|
local success, err = pcall(action.onClick, self)
|
||||||
|
if not success then
|
||||||
|
Log.warn("Error in notification action: " .. tostring(err))
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
layoutOrder = -action.layoutOrder,
|
||||||
|
transparency = transparency,
|
||||||
|
})
|
||||||
|
|
||||||
local actionButtons = {}
|
buttonsX += getTextBoundsAsync(action.text, theme.Font.Main, theme.TextSize.Large, math.huge).X + (theme.TextSize.Body * 2)
|
||||||
local buttonsX = 0
|
|
||||||
if self.props.actions then
|
|
||||||
local count = 0
|
|
||||||
for key, action in self.props.actions do
|
|
||||||
actionButtons[key] = e(TextButton, {
|
|
||||||
text = action.text,
|
|
||||||
style = action.style,
|
|
||||||
onClick = function()
|
|
||||||
local success, err = pcall(action.onClick, self)
|
|
||||||
if not success then
|
|
||||||
Log.warn("Error in notification action: " .. tostring(err))
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
layoutOrder = -action.layoutOrder,
|
|
||||||
transparency = transparency,
|
|
||||||
})
|
|
||||||
|
|
||||||
buttonsX += TextService:GetTextSize(
|
count += 1
|
||||||
action.text,
|
end
|
||||||
18,
|
|
||||||
Enum.Font.GothamMedium,
|
|
||||||
Vector2.new(math.huge, math.huge)
|
|
||||||
).X + 30
|
|
||||||
|
|
||||||
count += 1
|
buttonsX += (count - 1) * 5
|
||||||
end
|
end
|
||||||
|
|
||||||
buttonsX += (count - 1) * 5
|
local paddingY, logoSize = 20, 32
|
||||||
end
|
local actionsY = if self.props.actions then 37 else 0
|
||||||
|
local textXSpace = math.max(250, buttonsX) + 35
|
||||||
|
local textBounds = getTextBoundsAsync(self.props.text, theme.Font.Main, theme.TextSize.Body, textXSpace)
|
||||||
|
local contentX = math.max(textBounds.X, buttonsX)
|
||||||
|
|
||||||
local paddingY, logoSize = 20, 32
|
local size = self.binding:map(function(value)
|
||||||
local actionsY = if self.props.actions then 35 else 0
|
return UDim2.fromOffset(
|
||||||
local contentX = math.max(textBounds.X, buttonsX)
|
(35 + 40 + contentX) * value,
|
||||||
|
5 + actionsY + paddingY + math.max(logoSize, textBounds.Y)
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
local size = self.binding:map(function(value)
|
|
||||||
return UDim2.fromOffset(
|
|
||||||
(35 + 40 + contentX) * value,
|
|
||||||
5 + actionsY + paddingY + math.max(logoSize, textBounds.Y)
|
|
||||||
)
|
|
||||||
end)
|
|
||||||
|
|
||||||
return Theme.with(function(theme)
|
|
||||||
return e("TextButton", {
|
return e("TextButton", {
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Size = size,
|
Size = size,
|
||||||
@@ -147,8 +141,7 @@ function Notification:render()
|
|||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
}, {
|
}, {
|
||||||
Contents = e("Frame", {
|
Contents = e("Frame", {
|
||||||
Size = UDim2.new(0, 35 + contentX, 1, -paddingY),
|
Size = UDim2.new(1, 0, 1, 0),
|
||||||
Position = UDim2.new(0, 0, 0, paddingY / 2),
|
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
}, {
|
}, {
|
||||||
Logo = e("ImageLabel", {
|
Logo = e("ImageLabel", {
|
||||||
@@ -161,14 +154,15 @@ function Notification:render()
|
|||||||
}),
|
}),
|
||||||
Info = e("TextLabel", {
|
Info = e("TextLabel", {
|
||||||
Text = self.props.text,
|
Text = self.props.text,
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Notification.InfoColor,
|
TextColor3 = theme.Notification.InfoColor,
|
||||||
TextTransparency = transparency,
|
TextTransparency = transparency,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
TextYAlignment = Enum.TextYAlignment.Center,
|
||||||
TextWrapped = true,
|
TextWrapped = true,
|
||||||
|
|
||||||
Size = UDim2.new(0, textBounds.X, 0, textBounds.Y),
|
Size = UDim2.new(0, textBounds.X, 1, -actionsY),
|
||||||
Position = UDim2.fromOffset(35, 0),
|
Position = UDim2.fromOffset(35, 0),
|
||||||
|
|
||||||
LayoutOrder = 1,
|
LayoutOrder = 1,
|
||||||
@@ -176,7 +170,7 @@ function Notification:render()
|
|||||||
}),
|
}),
|
||||||
Actions = if self.props.actions
|
Actions = if self.props.actions
|
||||||
then e("Frame", {
|
then e("Frame", {
|
||||||
Size = UDim2.new(1, -40, 0, 35),
|
Size = UDim2.new(1, -40, 0, actionsY),
|
||||||
Position = UDim2.new(1, 0, 1, 0),
|
Position = UDim2.new(1, 0, 1, 0),
|
||||||
AnchorPoint = Vector2.new(1, 1),
|
AnchorPoint = Vector2.new(1, 1),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
@@ -196,6 +190,8 @@ function Notification:render()
|
|||||||
Padding = e("UIPadding", {
|
Padding = e("UIPadding", {
|
||||||
PaddingLeft = UDim.new(0, 17),
|
PaddingLeft = UDim.new(0, 17),
|
||||||
PaddingRight = UDim.new(0, 15),
|
PaddingRight = UDim.new(0, 15),
|
||||||
|
PaddingTop = UDim.new(0, paddingY / 2),
|
||||||
|
PaddingBottom = UDim.new(0, paddingY / 2),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ function ConfirmingPage:render()
|
|||||||
"Sync changes for project '%s':",
|
"Sync changes for project '%s':",
|
||||||
self.props.confirmData.serverInfo.projectName or "UNKNOWN"
|
self.props.confirmData.serverInfo.projectName or "UNKNOWN"
|
||||||
),
|
),
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
LineHeight = 1.2,
|
LineHeight = 1.2,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = theme.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
Size = UDim2.new(1, 0, 0, 20),
|
Size = UDim2.new(1, 0, 0, theme.TextSize.Large + 2),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -61,12 +61,12 @@ function ChangesViewer:render()
|
|||||||
|
|
||||||
Title = e("TextLabel", {
|
Title = e("TextLabel", {
|
||||||
Text = "Sync",
|
Text = "Sync",
|
||||||
Font = Enum.Font.GothamMedium,
|
FontFace = theme.Font.Main,
|
||||||
TextSize = 17,
|
TextSize = theme.TextSize.Large,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = theme.TextColor,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
Size = UDim2.new(1, -40, 0, 20),
|
Size = UDim2.new(1, -40, 0, theme.TextSize.Large + 2),
|
||||||
Position = UDim2.new(0, 40, 0, 0),
|
Position = UDim2.new(0, 40, 0, 0),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
}),
|
}),
|
||||||
@@ -74,13 +74,13 @@ function ChangesViewer:render()
|
|||||||
Subtitle = e("TextLabel", {
|
Subtitle = e("TextLabel", {
|
||||||
Text = DateTime.fromUnixTimestamp(self.props.patchData.timestamp):FormatLocalTime("LTS", "en-us"),
|
Text = DateTime.fromUnixTimestamp(self.props.patchData.timestamp):FormatLocalTime("LTS", "en-us"),
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Medium,
|
||||||
TextColor3 = theme.SubTextColor,
|
TextColor3 = theme.SubTextColor,
|
||||||
TextTruncate = Enum.TextTruncate.AtEnd,
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
Size = UDim2.new(1, -40, 0, 16),
|
Size = UDim2.new(1, -40, 0, theme.TextSize.Medium),
|
||||||
Position = UDim2.new(0, 40, 0, 20),
|
Position = UDim2.new(0, 40, 0, theme.TextSize.Large + 2),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -131,8 +131,8 @@ function ChangesViewer:render()
|
|||||||
}),
|
}),
|
||||||
AppliedText = e("TextLabel", {
|
AppliedText = e("TextLabel", {
|
||||||
Text = applied,
|
Text = applied,
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = theme.TextColor,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
Size = UDim2.new(0, 0, 1, 0),
|
Size = UDim2.new(0, 0, 1, 0),
|
||||||
@@ -156,8 +156,8 @@ function ChangesViewer:render()
|
|||||||
}),
|
}),
|
||||||
UnappliedText = e("TextLabel", {
|
UnappliedText = e("TextLabel", {
|
||||||
Text = unapplied,
|
Text = unapplied,
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = theme.Diff.Warning,
|
TextColor3 = theme.Diff.Warning,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
Size = UDim2.new(0, 0, 1, 0),
|
Size = UDim2.new(0, 0, 1, 0),
|
||||||
@@ -217,13 +217,13 @@ local function ConnectionDetails(props)
|
|||||||
}, {
|
}, {
|
||||||
ProjectName = e("TextLabel", {
|
ProjectName = e("TextLabel", {
|
||||||
Text = props.projectName,
|
Text = props.projectName,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 20,
|
TextSize = theme.TextSize.Large,
|
||||||
TextColor3 = theme.ConnectionDetails.ProjectNameColor,
|
TextColor3 = theme.ConnectionDetails.ProjectNameColor,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
|
||||||
Size = UDim2.new(1, 0, 0, 20),
|
Size = UDim2.new(1, 0, 0, theme.TextSize.Large),
|
||||||
|
|
||||||
LayoutOrder = 1,
|
LayoutOrder = 1,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
@@ -231,13 +231,13 @@ local function ConnectionDetails(props)
|
|||||||
|
|
||||||
Address = e("TextLabel", {
|
Address = e("TextLabel", {
|
||||||
Text = props.address,
|
Text = props.address,
|
||||||
Font = Enum.Font.Code,
|
FontFace = theme.Font.Code,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Medium,
|
||||||
TextColor3 = theme.ConnectionDetails.AddressColor,
|
TextColor3 = theme.ConnectionDetails.AddressColor,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
|
||||||
Size = UDim2.new(1, 0, 0, 15),
|
Size = UDim2.new(1, 0, 0, theme.TextSize.Medium),
|
||||||
|
|
||||||
LayoutOrder = 2,
|
LayoutOrder = 2,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
@@ -410,8 +410,8 @@ function ConnectedPage:render()
|
|||||||
Text = e("TextLabel", {
|
Text = e("TextLabel", {
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Text = self.changeInfoText,
|
Text = self.changeInfoText,
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 15,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = if syncWarning then theme.Diff.Warning else theme.Header.VersionColor,
|
TextColor3 = if syncWarning then theme.Diff.Warning else theme.Header.VersionColor,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
TextXAlignment = Enum.TextXAlignment.Right,
|
TextXAlignment = Enum.TextXAlignment.Right,
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
local TextService = game:GetService("TextService")
|
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
local Plugin = Rojo.Plugin
|
local Plugin = Rojo.Plugin
|
||||||
local Packages = Rojo.Packages
|
local Packages = Rojo.Packages
|
||||||
@@ -7,6 +5,7 @@ local Packages = Rojo.Packages
|
|||||||
local Roact = require(Packages.Roact)
|
local Roact = require(Packages.Roact)
|
||||||
|
|
||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
|
||||||
|
|
||||||
local TextButton = require(Plugin.App.Components.TextButton)
|
local TextButton = require(Plugin.App.Components.TextButton)
|
||||||
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
||||||
@@ -24,43 +23,43 @@ function Error:init()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Error:render()
|
function Error:render()
|
||||||
return e(BorderedContainer, {
|
return Theme.with(function(theme)
|
||||||
size = Roact.joinBindings({
|
return e(BorderedContainer, {
|
||||||
containerSize = self.props.containerSize,
|
size = Roact.joinBindings({
|
||||||
contentSize = self.contentSize,
|
containerSize = self.props.containerSize,
|
||||||
}):map(function(values)
|
contentSize = self.contentSize,
|
||||||
local maximumSize = values.containerSize
|
}):map(function(values)
|
||||||
maximumSize -= Vector2.new(14, 14) * 2 -- Page padding
|
local maximumSize = values.containerSize
|
||||||
maximumSize -= Vector2.new(0, 34 + 10) -- Buttons and spacing
|
maximumSize -= Vector2.new(14, 14) * 2 -- Page padding
|
||||||
|
maximumSize -= Vector2.new(0, 34 + 10) -- Buttons and spacing
|
||||||
|
|
||||||
local outerSize = values.contentSize + ERROR_PADDING * 2
|
local outerSize = values.contentSize + ERROR_PADDING * 2
|
||||||
|
|
||||||
return UDim2.new(1, 0, 0, math.min(outerSize.Y, maximumSize.Y))
|
return UDim2.new(1, 0, 0, math.min(outerSize.Y, maximumSize.Y))
|
||||||
end),
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
}, {
|
|
||||||
ScrollingFrame = e(ScrollingFrame, {
|
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
|
||||||
contentSize = self.contentSize:map(function(value)
|
|
||||||
return value + ERROR_PADDING * 2
|
|
||||||
end),
|
end),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
[Roact.Change.AbsoluteSize] = function(object)
|
|
||||||
local containerSize = object.AbsoluteSize - ERROR_PADDING * 2
|
|
||||||
|
|
||||||
local textBounds = TextService:GetTextSize(
|
|
||||||
self.props.errorMessage,
|
|
||||||
16,
|
|
||||||
Enum.Font.Code,
|
|
||||||
Vector2.new(containerSize.X, math.huge)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.setContentSize(Vector2.new(containerSize.X, textBounds.Y))
|
|
||||||
end,
|
|
||||||
}, {
|
}, {
|
||||||
ErrorMessage = Theme.with(function(theme)
|
ScrollingFrame = e(ScrollingFrame, {
|
||||||
return e("TextBox", {
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
|
contentSize = self.contentSize:map(function(value)
|
||||||
|
return value + ERROR_PADDING * 2
|
||||||
|
end),
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
|
[Roact.Change.AbsoluteSize] = function(object)
|
||||||
|
local containerSize = object.AbsoluteSize - ERROR_PADDING * 2
|
||||||
|
|
||||||
|
local textBounds = getTextBoundsAsync(
|
||||||
|
self.props.errorMessage,
|
||||||
|
theme.Font.Code,
|
||||||
|
theme.TextSize.Code,
|
||||||
|
containerSize.X
|
||||||
|
)
|
||||||
|
|
||||||
|
self.setContentSize(Vector2.new(containerSize.X, textBounds.Y))
|
||||||
|
end,
|
||||||
|
}, {
|
||||||
|
ErrorMessage = e("TextBox", {
|
||||||
[Roact.Event.InputBegan] = function(rbx, input)
|
[Roact.Event.InputBegan] = function(rbx, input)
|
||||||
if input.UserInputType ~= Enum.UserInputType.MouseButton1 then
|
if input.UserInputType ~= Enum.UserInputType.MouseButton1 then
|
||||||
return
|
return
|
||||||
@@ -71,8 +70,8 @@ function Error:render()
|
|||||||
|
|
||||||
Text = self.props.errorMessage,
|
Text = self.props.errorMessage,
|
||||||
TextEditable = false,
|
TextEditable = false,
|
||||||
Font = Enum.Font.Code,
|
FontFace = theme.Font.Code,
|
||||||
TextSize = 16,
|
TextSize = theme.TextSize.Code,
|
||||||
TextColor3 = theme.ErrorColor,
|
TextColor3 = theme.ErrorColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextYAlignment = Enum.TextYAlignment.Top,
|
TextYAlignment = Enum.TextYAlignment.Top,
|
||||||
@@ -81,17 +80,17 @@ function Error:render()
|
|||||||
ClearTextOnFocus = false,
|
ClearTextOnFocus = false,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Size = UDim2.new(1, 0, 1, 0),
|
Size = UDim2.new(1, 0, 1, 0),
|
||||||
})
|
}),
|
||||||
end),
|
|
||||||
|
|
||||||
Padding = e("UIPadding", {
|
Padding = e("UIPadding", {
|
||||||
PaddingLeft = UDim.new(0, ERROR_PADDING.X),
|
PaddingLeft = UDim.new(0, ERROR_PADDING.X),
|
||||||
PaddingRight = UDim.new(0, ERROR_PADDING.X),
|
PaddingRight = UDim.new(0, ERROR_PADDING.X),
|
||||||
PaddingTop = UDim.new(0, ERROR_PADDING.Y),
|
PaddingTop = UDim.new(0, ERROR_PADDING.Y),
|
||||||
PaddingBottom = UDim.new(0, ERROR_PADDING.Y),
|
PaddingBottom = UDim.new(0, ERROR_PADDING.Y),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
})
|
||||||
})
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local ErrorPage = Roact.Component:extend("ErrorPage")
|
local ErrorPage = Roact.Component:extend("ErrorPage")
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ local function AddressEntry(props)
|
|||||||
}, {
|
}, {
|
||||||
Host = e("TextBox", {
|
Host = e("TextBox", {
|
||||||
Text = props.host or "",
|
Text = props.host or "",
|
||||||
Font = Enum.Font.Code,
|
FontFace = theme.Font.Code,
|
||||||
TextSize = 18,
|
TextSize = theme.TextSize.Large,
|
||||||
TextColor3 = theme.AddressEntry.TextColor,
|
TextColor3 = theme.AddressEntry.TextColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
@@ -51,8 +51,8 @@ local function AddressEntry(props)
|
|||||||
|
|
||||||
Port = e("TextBox", {
|
Port = e("TextBox", {
|
||||||
Text = props.port or "",
|
Text = props.port or "",
|
||||||
Font = Enum.Font.Code,
|
FontFace = theme.Font.Code,
|
||||||
TextSize = 18,
|
TextSize = theme.TextSize.Large,
|
||||||
TextColor3 = theme.AddressEntry.TextColor,
|
TextColor3 = theme.AddressEntry.TextColor,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
PlaceholderText = Config.defaultPort,
|
PlaceholderText = Config.defaultPort,
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
local TextService = game:GetService("TextService")
|
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
local Plugin = Rojo.Plugin
|
local Plugin = Rojo.Plugin
|
||||||
local Packages = Rojo.Packages
|
local Packages = Rojo.Packages
|
||||||
@@ -9,6 +7,7 @@ local Roact = require(Packages.Roact)
|
|||||||
local Settings = require(Plugin.Settings)
|
local Settings = require(Plugin.Settings)
|
||||||
local Assets = require(Plugin.Assets)
|
local Assets = require(Plugin.Assets)
|
||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
local getTextBoundsAsync = require(Plugin.App.getTextBoundsAsync)
|
||||||
|
|
||||||
local Checkbox = require(Plugin.App.Components.Checkbox)
|
local Checkbox = require(Plugin.App.Components.Checkbox)
|
||||||
local Dropdown = require(Plugin.App.Components.Dropdown)
|
local Dropdown = require(Plugin.App.Components.Dropdown)
|
||||||
@@ -31,10 +30,16 @@ local TAG_TYPES = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local function getTextBounds(text, textSize, font, lineHeight, bounds)
|
local function getTextBoundsWithLineHeight(
|
||||||
local textBounds = TextService:GetTextSize(text, textSize, font, bounds)
|
text: string,
|
||||||
|
font: Font,
|
||||||
|
textSize: number,
|
||||||
|
width: number,
|
||||||
|
lineHeight: number
|
||||||
|
)
|
||||||
|
local textBounds = getTextBoundsAsync(text, font, textSize, width)
|
||||||
|
|
||||||
local lineCount = textBounds.Y / textSize
|
local lineCount = math.ceil(textBounds.Y / textSize)
|
||||||
local lineHeightAbsolute = textSize * lineHeight
|
local lineHeightAbsolute = textSize * lineHeight
|
||||||
|
|
||||||
return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize))
|
return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize))
|
||||||
@@ -109,6 +114,7 @@ function Setting:render()
|
|||||||
then self.props.input
|
then self.props.input
|
||||||
elseif self.props.options ~= nil then e(Dropdown, {
|
elseif self.props.options ~= nil then e(Dropdown, {
|
||||||
locked = self.props.locked,
|
locked = self.props.locked,
|
||||||
|
lockedTooltip = self.props.lockedTooltip,
|
||||||
options = self.props.options,
|
options = self.props.options,
|
||||||
active = self.state.setting,
|
active = self.state.setting,
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
@@ -118,6 +124,7 @@ function Setting:render()
|
|||||||
})
|
})
|
||||||
else e(Checkbox, {
|
else e(Checkbox, {
|
||||||
locked = self.props.locked,
|
locked = self.props.locked,
|
||||||
|
lockedTooltip = self.props.lockedTooltip,
|
||||||
active = self.state.setting,
|
active = self.state.setting,
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
onClick = function()
|
onClick = function()
|
||||||
@@ -145,7 +152,7 @@ function Setting:render()
|
|||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
}, {
|
}, {
|
||||||
Heading = e("Frame", {
|
Heading = e("Frame", {
|
||||||
Size = UDim2.new(1, 0, 0, 16),
|
Size = UDim2.new(1, 0, 0, theme.TextSize.Medium),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
}, {
|
}, {
|
||||||
Layout = e("UIListLayout", {
|
Layout = e("UIListLayout", {
|
||||||
@@ -165,8 +172,8 @@ function Setting:render()
|
|||||||
else nil,
|
else nil,
|
||||||
Name = e("TextLabel", {
|
Name = e("TextLabel", {
|
||||||
Text = self.props.name,
|
Text = self.props.name,
|
||||||
Font = Enum.Font.GothamBold,
|
FontFace = theme.Font.Bold,
|
||||||
TextSize = 16,
|
TextSize = theme.TextSize.Medium,
|
||||||
TextColor3 = if self.props.tag and TAG_TYPES[self.props.tag]
|
TextColor3 = if self.props.tag and TAG_TYPES[self.props.tag]
|
||||||
then getThemeColorFromPath(theme, TAG_TYPES[self.props.tag].color)
|
then getThemeColorFromPath(theme, TAG_TYPES[self.props.tag].color)
|
||||||
else settingsTheme.Setting.NameColor,
|
else settingsTheme.Setting.NameColor,
|
||||||
@@ -174,7 +181,7 @@ function Setting:render()
|
|||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
RichText = true,
|
RichText = true,
|
||||||
|
|
||||||
Size = UDim2.new(1, 0, 0, 16),
|
Size = UDim2.new(1, 0, 0, theme.TextSize.Medium),
|
||||||
|
|
||||||
LayoutOrder = 2,
|
LayoutOrder = 2,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
@@ -183,9 +190,9 @@ function Setting:render()
|
|||||||
|
|
||||||
Description = e("TextLabel", {
|
Description = e("TextLabel", {
|
||||||
Text = self.props.description,
|
Text = self.props.description,
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Main,
|
||||||
LineHeight = 1.2,
|
LineHeight = 1.2,
|
||||||
TextSize = 14,
|
TextSize = theme.TextSize.Body,
|
||||||
TextColor3 = settingsTheme.Setting.DescriptionColor,
|
TextColor3 = settingsTheme.Setting.DescriptionColor,
|
||||||
TextXAlignment = Enum.TextXAlignment.Left,
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
TextTransparency = self.props.transparency,
|
TextTransparency = self.props.transparency,
|
||||||
@@ -197,12 +204,12 @@ function Setting:render()
|
|||||||
inputSize = self.inputSize,
|
inputSize = self.inputSize,
|
||||||
}):map(function(values)
|
}):map(function(values)
|
||||||
local offset = values.inputSize.X + 5
|
local offset = values.inputSize.X + 5
|
||||||
local textBounds = getTextBounds(
|
local textBounds = getTextBoundsWithLineHeight(
|
||||||
self.props.description,
|
self.props.description,
|
||||||
14,
|
theme.Font.Main,
|
||||||
Enum.Font.Gotham,
|
theme.TextSize.Body,
|
||||||
1.2,
|
values.containerSize.X - offset,
|
||||||
Vector2.new(values.containerSize.X - offset, math.huge)
|
1.2
|
||||||
)
|
)
|
||||||
return UDim2.new(1, -offset, 0, textBounds.Y)
|
return UDim2.new(1, -offset, 0, textBounds.Y)
|
||||||
end),
|
end),
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ local confirmationBehaviors = { "Initial", "Always", "Large Changes", "Unlisted
|
|||||||
|
|
||||||
local function Navbar(props)
|
local function Navbar(props)
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
theme = theme.Settings.Navbar
|
local navbarTheme = theme.Settings.Navbar
|
||||||
|
|
||||||
return e("Frame", {
|
return e("Frame", {
|
||||||
Size = UDim2.new(1, 0, 0, 46),
|
Size = UDim2.new(1, 0, 0, 46),
|
||||||
@@ -40,7 +40,7 @@ local function Navbar(props)
|
|||||||
Back = e(IconButton, {
|
Back = e(IconButton, {
|
||||||
icon = Assets.Images.Icons.Back,
|
icon = Assets.Images.Icons.Back,
|
||||||
iconSize = 24,
|
iconSize = 24,
|
||||||
color = theme.BackButtonColor,
|
color = navbarTheme.BackButtonColor,
|
||||||
transparency = props.transparency,
|
transparency = props.transparency,
|
||||||
|
|
||||||
position = UDim2.new(0, 0, 0.5, 0),
|
position = UDim2.new(0, 0, 0.5, 0),
|
||||||
@@ -55,9 +55,9 @@ local function Navbar(props)
|
|||||||
|
|
||||||
Text = e("TextLabel", {
|
Text = e("TextLabel", {
|
||||||
Text = "Settings",
|
Text = "Settings",
|
||||||
Font = Enum.Font.Gotham,
|
FontFace = theme.Font.Thin,
|
||||||
TextSize = 18,
|
TextSize = theme.TextSize.Large,
|
||||||
TextColor3 = theme.TextColor,
|
TextColor3 = navbarTheme.TextColor,
|
||||||
TextTransparency = props.transparency,
|
TextTransparency = props.transparency,
|
||||||
|
|
||||||
Size = UDim2.new(1, 0, 1, 0),
|
Size = UDim2.new(1, 0, 1, 0),
|
||||||
@@ -81,185 +81,182 @@ function SettingsPage:render()
|
|||||||
return layoutOrder
|
return layoutOrder
|
||||||
end
|
end
|
||||||
|
|
||||||
return Theme.with(function(theme)
|
return Roact.createFragment({
|
||||||
theme = theme.Settings
|
Navbar = e(Navbar, {
|
||||||
|
onBack = self.props.onBack,
|
||||||
return Roact.createFragment({
|
transparency = self.props.transparency,
|
||||||
Navbar = e(Navbar, {
|
layoutOrder = layoutIncrement(),
|
||||||
onBack = self.props.onBack,
|
}),
|
||||||
|
Content = e(ScrollingFrame, {
|
||||||
|
size = UDim2.new(1, 0, 1, -47),
|
||||||
|
position = UDim2.new(0, 0, 0, 47),
|
||||||
|
contentSize = self.contentSize,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
}, {
|
||||||
|
ShowNotifications = e(Setting, {
|
||||||
|
id = "showNotifications",
|
||||||
|
name = "Show Notifications",
|
||||||
|
description = "Popup notifications in viewport",
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
layoutOrder = layoutIncrement(),
|
layoutOrder = layoutIncrement(),
|
||||||
}),
|
}),
|
||||||
Content = e(ScrollingFrame, {
|
|
||||||
size = UDim2.new(1, 0, 1, -47),
|
SyncReminder = e(Setting, {
|
||||||
position = UDim2.new(0, 0, 0, 47),
|
id = "syncReminder",
|
||||||
contentSize = self.contentSize,
|
name = "Sync Reminder",
|
||||||
|
description = "Notify to sync when opening a place that has previously been synced",
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
}, {
|
visible = Settings:getBinding("showNotifications"),
|
||||||
ShowNotifications = e(Setting, {
|
layoutOrder = layoutIncrement(),
|
||||||
id = "showNotifications",
|
}),
|
||||||
name = "Show Notifications",
|
|
||||||
description = "Popup notifications in viewport",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
SyncReminder = e(Setting, {
|
ConfirmationBehavior = e(Setting, {
|
||||||
id = "syncReminder",
|
id = "confirmationBehavior",
|
||||||
name = "Sync Reminder",
|
name = "Confirmation Behavior",
|
||||||
description = "Notify to sync when opening a place that has previously been synced",
|
description = "When to prompt for confirmation before syncing",
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
visible = Settings:getBinding("showNotifications"),
|
layoutOrder = layoutIncrement(),
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
ConfirmationBehavior = e(Setting, {
|
options = confirmationBehaviors,
|
||||||
id = "confirmationBehavior",
|
}),
|
||||||
name = "Confirmation Behavior",
|
|
||||||
description = "When to prompt for confirmation before syncing",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
|
|
||||||
options = confirmationBehaviors,
|
LargeChangesConfirmationThreshold = e(Setting, {
|
||||||
}),
|
id = "largeChangesConfirmationThreshold",
|
||||||
|
name = "Confirmation Threshold",
|
||||||
LargeChangesConfirmationThreshold = e(Setting, {
|
description = "How many modified instances to be considered a large change",
|
||||||
id = "largeChangesConfirmationThreshold",
|
transparency = self.props.transparency,
|
||||||
name = "Confirmation Threshold",
|
layoutOrder = layoutIncrement(),
|
||||||
description = "How many modified instances to be considered a large change",
|
visible = Settings:getBinding("confirmationBehavior"):map(function(value)
|
||||||
transparency = self.props.transparency,
|
return value == "Large Changes"
|
||||||
layoutOrder = layoutIncrement(),
|
end),
|
||||||
visible = Settings:getBinding("confirmationBehavior"):map(function(value)
|
input = e(TextInput, {
|
||||||
return value == "Large Changes"
|
size = UDim2.new(0, 40, 0, 28),
|
||||||
|
text = Settings:getBinding("largeChangesConfirmationThreshold"):map(function(value)
|
||||||
|
return tostring(value)
|
||||||
end),
|
end),
|
||||||
input = e(TextInput, {
|
|
||||||
size = UDim2.new(0, 40, 0, 28),
|
|
||||||
text = Settings:getBinding("largeChangesConfirmationThreshold"):map(function(value)
|
|
||||||
return tostring(value)
|
|
||||||
end),
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
enabled = true,
|
|
||||||
onEntered = function(text)
|
|
||||||
local number = tonumber(string.match(text, "%d+"))
|
|
||||||
if number then
|
|
||||||
Settings:set("largeChangesConfirmationThreshold", math.clamp(number, 1, 999))
|
|
||||||
else
|
|
||||||
-- Force text back to last valid value
|
|
||||||
Settings:set(
|
|
||||||
"largeChangesConfirmationThreshold",
|
|
||||||
Settings:get("largeChangesConfirmationThreshold")
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
|
|
||||||
PlaySounds = e(Setting, {
|
|
||||||
id = "playSounds",
|
|
||||||
name = "Play Sounds",
|
|
||||||
description = "Toggle sound effects",
|
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
layoutOrder = layoutIncrement(),
|
enabled = true,
|
||||||
}),
|
onEntered = function(text)
|
||||||
|
local number = tonumber(string.match(text, "%d+"))
|
||||||
CheckForUpdates = e(Setting, {
|
if number then
|
||||||
id = "checkForUpdates",
|
Settings:set("largeChangesConfirmationThreshold", math.clamp(number, 1, 999))
|
||||||
name = "Check For Updates",
|
else
|
||||||
description = "Notify about newer compatible Rojo releases",
|
-- Force text back to last valid value
|
||||||
transparency = self.props.transparency,
|
Settings:set(
|
||||||
layoutOrder = layoutIncrement(),
|
"largeChangesConfirmationThreshold",
|
||||||
}),
|
Settings:get("largeChangesConfirmationThreshold")
|
||||||
|
)
|
||||||
CheckForPreleases = e(Setting, {
|
end
|
||||||
id = "checkForPrereleases",
|
|
||||||
name = "Include Prerelease Updates",
|
|
||||||
description = "Include prereleases when checking for updates",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
visible = if string.find(debug.traceback(), "\n[^\n]-user_.-$") == nil
|
|
||||||
then false -- Must be a local install to allow prerelease checks
|
|
||||||
else Settings:getBinding("checkForUpdates"),
|
|
||||||
}),
|
|
||||||
|
|
||||||
AutoConnectPlaytestServer = e(Setting, {
|
|
||||||
id = "autoConnectPlaytestServer",
|
|
||||||
name = "Auto Connect Playtest Server",
|
|
||||||
description = "Automatically connect game server to Rojo when playtesting while connected in Edit",
|
|
||||||
tag = "unstable",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
OpenScriptsExternally = e(Setting, {
|
|
||||||
id = "openScriptsExternally",
|
|
||||||
name = "Open Scripts Externally",
|
|
||||||
description = "Attempt to open scripts in an external editor",
|
|
||||||
tag = "unstable",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
TwoWaySync = e(Setting, {
|
|
||||||
id = "twoWaySync",
|
|
||||||
name = "Two-Way Sync",
|
|
||||||
description = "Editing files in Studio will sync them into the filesystem",
|
|
||||||
locked = self.props.syncActive,
|
|
||||||
tag = "unstable",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
LogLevel = e(Setting, {
|
|
||||||
id = "logLevel",
|
|
||||||
name = "Log Level",
|
|
||||||
description = "Plugin output verbosity level",
|
|
||||||
tag = "debug",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
|
|
||||||
options = invertedLevels,
|
|
||||||
showReset = Settings:getBinding("logLevel"):map(function(value)
|
|
||||||
return value ~= "Info"
|
|
||||||
end),
|
|
||||||
onReset = function()
|
|
||||||
Settings:set("logLevel", "Info")
|
|
||||||
end,
|
end,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
TypecheckingEnabled = e(Setting, {
|
|
||||||
id = "typecheckingEnabled",
|
|
||||||
name = "Typechecking",
|
|
||||||
description = "Toggle typechecking on the API surface",
|
|
||||||
tag = "debug",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
TimingLogsEnabled = e(Setting, {
|
|
||||||
id = "timingLogsEnabled",
|
|
||||||
name = "Timing Logs",
|
|
||||||
description = "Toggle logging timing of internal actions for benchmarking Rojo performance",
|
|
||||||
tag = "debug",
|
|
||||||
transparency = self.props.transparency,
|
|
||||||
layoutOrder = layoutIncrement(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
Layout = e("UIListLayout", {
|
|
||||||
FillDirection = Enum.FillDirection.Vertical,
|
|
||||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
|
||||||
|
|
||||||
[Roact.Change.AbsoluteContentSize] = function(object)
|
|
||||||
self.setContentSize(object.AbsoluteContentSize)
|
|
||||||
end,
|
|
||||||
}),
|
|
||||||
|
|
||||||
Padding = e("UIPadding", {
|
|
||||||
PaddingLeft = UDim.new(0, 20),
|
|
||||||
PaddingRight = UDim.new(0, 20),
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
})
|
|
||||||
end)
|
PlaySounds = e(Setting, {
|
||||||
|
id = "playSounds",
|
||||||
|
name = "Play Sounds",
|
||||||
|
description = "Toggle sound effects",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
CheckForUpdates = e(Setting, {
|
||||||
|
id = "checkForUpdates",
|
||||||
|
name = "Check For Updates",
|
||||||
|
description = "Notify about newer compatible Rojo releases",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
CheckForPreleases = e(Setting, {
|
||||||
|
id = "checkForPrereleases",
|
||||||
|
name = "Include Prerelease Updates",
|
||||||
|
description = "Include prereleases when checking for updates",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
visible = if string.find(debug.traceback(), "\n[^\n]-user_.-$") == nil
|
||||||
|
then false -- Must be a local install to allow prerelease checks
|
||||||
|
else Settings:getBinding("checkForUpdates"),
|
||||||
|
}),
|
||||||
|
|
||||||
|
AutoConnectPlaytestServer = e(Setting, {
|
||||||
|
id = "autoConnectPlaytestServer",
|
||||||
|
name = "Auto Connect Playtest Server",
|
||||||
|
description = "Automatically connect game server to Rojo when playtesting while connected in Edit",
|
||||||
|
tag = "unstable",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
OpenScriptsExternally = e(Setting, {
|
||||||
|
id = "openScriptsExternally",
|
||||||
|
name = "Open Scripts Externally",
|
||||||
|
description = "Attempt to open scripts in an external editor",
|
||||||
|
tag = "unstable",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
TwoWaySync = e(Setting, {
|
||||||
|
id = "twoWaySync",
|
||||||
|
name = "Two-Way Sync",
|
||||||
|
description = "Editing files in Studio will sync them into the filesystem",
|
||||||
|
locked = self.props.syncActive,
|
||||||
|
lockedTooltip = "(Cannot change while currently syncing. Disconnect first.)",
|
||||||
|
tag = "unstable",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
LogLevel = e(Setting, {
|
||||||
|
id = "logLevel",
|
||||||
|
name = "Log Level",
|
||||||
|
description = "Plugin output verbosity level",
|
||||||
|
tag = "debug",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
|
||||||
|
options = invertedLevels,
|
||||||
|
showReset = Settings:getBinding("logLevel"):map(function(value)
|
||||||
|
return value ~= "Info"
|
||||||
|
end),
|
||||||
|
onReset = function()
|
||||||
|
Settings:set("logLevel", "Info")
|
||||||
|
end,
|
||||||
|
}),
|
||||||
|
|
||||||
|
TypecheckingEnabled = e(Setting, {
|
||||||
|
id = "typecheckingEnabled",
|
||||||
|
name = "Typechecking",
|
||||||
|
description = "Toggle typechecking on the API surface",
|
||||||
|
tag = "debug",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
TimingLogsEnabled = e(Setting, {
|
||||||
|
id = "timingLogsEnabled",
|
||||||
|
name = "Timing Logs",
|
||||||
|
description = "Toggle logging timing of internal actions for benchmarking Rojo performance",
|
||||||
|
tag = "debug",
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
layoutOrder = layoutIncrement(),
|
||||||
|
}),
|
||||||
|
|
||||||
|
Layout = e("UIListLayout", {
|
||||||
|
FillDirection = Enum.FillDirection.Vertical,
|
||||||
|
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||||
|
|
||||||
|
[Roact.Change.AbsoluteContentSize] = function(object)
|
||||||
|
self.setContentSize(object.AbsoluteContentSize)
|
||||||
|
end,
|
||||||
|
}),
|
||||||
|
|
||||||
|
Padding = e("UIPadding", {
|
||||||
|
PaddingLeft = UDim.new(0, 20),
|
||||||
|
PaddingRight = UDim.new(0, 20),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
return SettingsPage
|
return SettingsPage
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
--[[
|
--[[
|
||||||
Theming system taking advantage of Roact's new context API.
|
Theming system provided through Roact's context.
|
||||||
Doesn't use colors provided by Studio and instead just branches on theme
|
Uses Studio colors when possible.
|
||||||
name. This isn't exactly best practice.
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
-- Studio does not exist outside Roblox Studio, so we'll lazily initialize it
|
-- Studio does not exist outside Roblox Studio, so we'll lazily initialize it
|
||||||
@@ -15,6 +14,8 @@ local function getStudio()
|
|||||||
return _Studio
|
return _Studio
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local ContentProvider = game:GetService("ContentProvider")
|
||||||
|
|
||||||
local Rojo = script:FindFirstAncestor("Rojo")
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
local Packages = Rojo.Packages
|
local Packages = Rojo.Packages
|
||||||
|
|
||||||
@@ -35,6 +36,27 @@ function StudioProvider:updateTheme()
|
|||||||
local isDark = studioTheme.Name == "Dark"
|
local isDark = studioTheme.Name == "Dark"
|
||||||
|
|
||||||
local theme = strict(studioTheme.Name .. "Theme", {
|
local theme = strict(studioTheme.Name .. "Theme", {
|
||||||
|
Font = {
|
||||||
|
Main = Font.new("rbxasset://fonts/families/Montserrat.json", Enum.FontWeight.Medium, Enum.FontStyle.Normal),
|
||||||
|
Bold = Font.new("rbxasset://fonts/families/Montserrat.json", Enum.FontWeight.Bold, Enum.FontStyle.Normal),
|
||||||
|
Thin = Font.new(
|
||||||
|
"rbxasset://fonts/families/Montserrat.json",
|
||||||
|
Enum.FontWeight.Regular,
|
||||||
|
Enum.FontStyle.Normal
|
||||||
|
),
|
||||||
|
Code = Font.new(
|
||||||
|
"rbxasset://fonts/families/Inconsolata.json",
|
||||||
|
Enum.FontWeight.Regular,
|
||||||
|
Enum.FontStyle.Normal
|
||||||
|
),
|
||||||
|
},
|
||||||
|
TextSize = {
|
||||||
|
Body = 15,
|
||||||
|
Small = 13,
|
||||||
|
Medium = 16,
|
||||||
|
Large = 18,
|
||||||
|
Code = 16,
|
||||||
|
},
|
||||||
BrandColor = BRAND_COLOR,
|
BrandColor = BRAND_COLOR,
|
||||||
BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainBackground),
|
BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainBackground),
|
||||||
TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText),
|
TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText),
|
||||||
@@ -190,6 +212,13 @@ end
|
|||||||
|
|
||||||
function StudioProvider:init()
|
function StudioProvider:init()
|
||||||
self:updateTheme()
|
self:updateTheme()
|
||||||
|
|
||||||
|
-- Preload the Fonts so that getTextBoundsAsync won't yield
|
||||||
|
local fontAssetIds = {}
|
||||||
|
for _, font in self.state.theme.Font do
|
||||||
|
table.insert(fontAssetIds, font.Family)
|
||||||
|
end
|
||||||
|
pcall(ContentProvider.PreloadAsync, ContentProvider, fontAssetIds)
|
||||||
end
|
end
|
||||||
|
|
||||||
function StudioProvider:render()
|
function StudioProvider:render()
|
||||||
|
|||||||
41
plugin/src/App/getTextBoundsAsync.lua
Normal file
41
plugin/src/App/getTextBoundsAsync.lua
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
local TextService = game:GetService("TextService")
|
||||||
|
|
||||||
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
|
local Packages = Rojo.Packages
|
||||||
|
|
||||||
|
local Log = require(Packages.Log)
|
||||||
|
|
||||||
|
local params = Instance.new("GetTextBoundsParams")
|
||||||
|
|
||||||
|
local function getTextBoundsAsync(
|
||||||
|
text: string,
|
||||||
|
font: Font,
|
||||||
|
textSize: number,
|
||||||
|
width: number,
|
||||||
|
richText: boolean?
|
||||||
|
): Vector2
|
||||||
|
if type(text) ~= "string" then
|
||||||
|
Log.warn(`Invalid text. Expected string, received {type(text)} instead`)
|
||||||
|
return Vector2.zero
|
||||||
|
end
|
||||||
|
if #text >= 200_000 then
|
||||||
|
Log.warn(`Invalid text. Exceeds the 199,999 character limit`)
|
||||||
|
return Vector2.zero
|
||||||
|
end
|
||||||
|
|
||||||
|
params.Text = text
|
||||||
|
params.Font = font
|
||||||
|
params.Size = textSize
|
||||||
|
params.Width = width
|
||||||
|
params.RichText = not not richText
|
||||||
|
|
||||||
|
local success, bounds = pcall(TextService.GetTextBoundsAsync, TextService, params)
|
||||||
|
if not success then
|
||||||
|
Log.warn(`Failed to get text bounds: {bounds}`)
|
||||||
|
return Vector2.zero
|
||||||
|
end
|
||||||
|
|
||||||
|
return bounds
|
||||||
|
end
|
||||||
|
|
||||||
|
return getTextBoundsAsync
|
||||||
@@ -52,9 +52,9 @@ local App = Roact.Component:extend("App")
|
|||||||
function App:init()
|
function App:init()
|
||||||
preloadAssets()
|
preloadAssets()
|
||||||
|
|
||||||
local priorHost, priorPort = self:getPriorEndpoint()
|
local priorSyncInfo = self:getPriorSyncInfo()
|
||||||
self.host, self.setHost = Roact.createBinding(priorHost or "")
|
self.host, self.setHost = Roact.createBinding(priorSyncInfo.host or "")
|
||||||
self.port, self.setPort = Roact.createBinding(priorPort or "")
|
self.port, self.setPort = Roact.createBinding(priorSyncInfo.port or "")
|
||||||
|
|
||||||
self.confirmationBindable = Instance.new("BindableEvent")
|
self.confirmationBindable = Instance.new("BindableEvent")
|
||||||
self.confirmationEvent = self.confirmationBindable.Event
|
self.confirmationEvent = self.confirmationBindable.Event
|
||||||
@@ -145,28 +145,38 @@ function App:init()
|
|||||||
if
|
if
|
||||||
Settings:get("syncReminder")
|
Settings:get("syncReminder")
|
||||||
and self.serveSession == nil
|
and self.serveSession == nil
|
||||||
and self:getLastSyncTimestamp()
|
and self:getPriorSyncInfo().timestamp ~= nil
|
||||||
and (self:isSyncLockAvailable())
|
and (self:isSyncLockAvailable())
|
||||||
then
|
then
|
||||||
self:addNotification("You've previously synced this place. Would you like to reconnect?", 300, {
|
local syncInfo = self:getPriorSyncInfo()
|
||||||
Connect = {
|
local timeSinceSync = timeUtil.elapsedToText(os.time() - syncInfo.timestamp)
|
||||||
text = "Connect",
|
local syncDetail = if syncInfo.projectName
|
||||||
style = "Solid",
|
then `project '{syncInfo.projectName}'`
|
||||||
layoutOrder = 1,
|
else `{syncInfo.host or Config.defaultHost}:{syncInfo.port or Config.defaultPort}`
|
||||||
onClick = function(notification)
|
|
||||||
notification:dismiss()
|
self:addNotification(
|
||||||
self:startSession()
|
`You synced {syncDetail} to this place {timeSinceSync}. Would you like to reconnect?`,
|
||||||
end,
|
300,
|
||||||
},
|
{
|
||||||
Dismiss = {
|
Connect = {
|
||||||
text = "Dismiss",
|
text = "Connect",
|
||||||
style = "Bordered",
|
style = "Solid",
|
||||||
layoutOrder = 2,
|
layoutOrder = 1,
|
||||||
onClick = function(notification)
|
onClick = function(notification)
|
||||||
notification:dismiss()
|
notification:dismiss()
|
||||||
end,
|
self:startSession()
|
||||||
},
|
end,
|
||||||
})
|
},
|
||||||
|
Dismiss = {
|
||||||
|
text = "Dismiss",
|
||||||
|
style = "Bordered",
|
||||||
|
layoutOrder = 2,
|
||||||
|
onClick = function(notification)
|
||||||
|
notification:dismiss()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -274,54 +284,32 @@ function App:checkForUpdates()
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function App:getPriorEndpoint()
|
function App:getPriorSyncInfo(): { host: string?, port: string?, projectName: string?, timestamp: number? }
|
||||||
local priorEndpoints = Settings:get("priorEndpoints")
|
local priorSyncInfos = Settings:get("priorEndpoints")
|
||||||
if not priorEndpoints then
|
if not priorSyncInfos then
|
||||||
return
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local id = tostring(game.PlaceId)
|
local id = tostring(game.PlaceId)
|
||||||
if ignorePlaceIds[id] then
|
if ignorePlaceIds[id] then
|
||||||
return
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local place = priorEndpoints[id]
|
return priorSyncInfos[id] or {}
|
||||||
if not place then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
return place.host, place.port
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function App:getLastSyncTimestamp()
|
function App:setPriorSyncInfo(host: string, port: string, projectName: string)
|
||||||
local priorEndpoints = Settings:get("priorEndpoints")
|
local priorSyncInfos = Settings:get("priorEndpoints")
|
||||||
if not priorEndpoints then
|
if not priorSyncInfos then
|
||||||
return
|
priorSyncInfos = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local id = tostring(game.PlaceId)
|
local now = os.time()
|
||||||
if ignorePlaceIds[id] then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local place = priorEndpoints[id]
|
|
||||||
if not place then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
return place.timestamp
|
|
||||||
end
|
|
||||||
|
|
||||||
function App:setPriorEndpoint(host: string, port: string)
|
|
||||||
local priorEndpoints = Settings:get("priorEndpoints")
|
|
||||||
if not priorEndpoints then
|
|
||||||
priorEndpoints = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Clear any stale saves to avoid disc bloat
|
-- Clear any stale saves to avoid disc bloat
|
||||||
for placeId, endpoint in priorEndpoints do
|
for placeId, syncInfo in priorSyncInfos do
|
||||||
if os.time() - endpoint.timestamp > 12_960_000 then
|
if now - (syncInfo.timestamp or now) > 12_960_000 then
|
||||||
priorEndpoints[placeId] = nil
|
priorSyncInfos[placeId] = nil
|
||||||
Log.trace("Cleared stale saved endpoint for {}", placeId)
|
Log.trace("Cleared stale saved endpoint for {}", placeId)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -331,14 +319,15 @@ function App:setPriorEndpoint(host: string, port: string)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
priorEndpoints[id] = {
|
priorSyncInfos[id] = {
|
||||||
host = if host ~= Config.defaultHost then host else nil,
|
host = if host ~= Config.defaultHost then host else nil,
|
||||||
port = if port ~= Config.defaultPort then port else nil,
|
port = if port ~= Config.defaultPort then port else nil,
|
||||||
timestamp = os.time(),
|
projectName = projectName,
|
||||||
|
timestamp = now,
|
||||||
}
|
}
|
||||||
Log.trace("Saved last used endpoint for {}", game.PlaceId)
|
Log.trace("Saved last used endpoint for {}", game.PlaceId)
|
||||||
|
|
||||||
Settings:set("priorEndpoints", priorEndpoints)
|
Settings:set("priorEndpoints", priorSyncInfos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function App:getHostAndPort()
|
function App:getHostAndPort()
|
||||||
@@ -533,8 +522,6 @@ function App:startSession()
|
|||||||
|
|
||||||
serveSession:onStatusChanged(function(status, details)
|
serveSession:onStatusChanged(function(status, details)
|
||||||
if status == ServeSession.Status.Connecting then
|
if status == ServeSession.Status.Connecting then
|
||||||
self:setPriorEndpoint(host, port)
|
|
||||||
|
|
||||||
self:setState({
|
self:setState({
|
||||||
appStatus = AppStatus.Connecting,
|
appStatus = AppStatus.Connecting,
|
||||||
toolbarIcon = Assets.Images.PluginButton,
|
toolbarIcon = Assets.Images.PluginButton,
|
||||||
@@ -542,6 +529,7 @@ function App:startSession()
|
|||||||
self:addNotification("Connecting to session...")
|
self:addNotification("Connecting to session...")
|
||||||
elseif status == ServeSession.Status.Connected then
|
elseif status == ServeSession.Status.Connected then
|
||||||
self.knownProjects[details] = true
|
self.knownProjects[details] = true
|
||||||
|
self:setPriorSyncInfo(host, port, details)
|
||||||
self:setRunningConnectionInfo(baseUrl)
|
self:setRunningConnectionInfo(baseUrl)
|
||||||
|
|
||||||
local address = ("%s:%s"):format(host, port)
|
local address = ("%s:%s"):format(host, port)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ local invariant = require(script.Parent.Parent.invariant)
|
|||||||
|
|
||||||
local decodeValue = require(script.Parent.decodeValue)
|
local decodeValue = require(script.Parent.decodeValue)
|
||||||
local reify = require(script.Parent.reify)
|
local reify = require(script.Parent.reify)
|
||||||
|
local reifyInstance, applyDeferredRefs = reify.reifyInstance, reify.applyDeferredRefs
|
||||||
local setProperty = require(script.Parent.setProperty)
|
local setProperty = require(script.Parent.setProperty)
|
||||||
|
|
||||||
local function applyPatch(instanceMap, patch)
|
local function applyPatch(instanceMap, patch)
|
||||||
@@ -29,6 +30,11 @@ local function applyPatch(instanceMap, patch)
|
|||||||
-- Tracks any portions of the patch that could not be applied to the DOM.
|
-- Tracks any portions of the patch that could not be applied to the DOM.
|
||||||
local unappliedPatch = PatchSet.newEmpty()
|
local unappliedPatch = PatchSet.newEmpty()
|
||||||
|
|
||||||
|
-- Contains a list of all of the ref properties that we'll need to assign.
|
||||||
|
-- It is imperative that refs are assigned after all instances are created
|
||||||
|
-- to ensure that referents can be mapped to instances correctly.
|
||||||
|
local deferredRefs = {}
|
||||||
|
|
||||||
for _, removedIdOrInstance in ipairs(patch.removed) do
|
for _, removedIdOrInstance in ipairs(patch.removed) do
|
||||||
local removeInstanceSuccess = pcall(function()
|
local removeInstanceSuccess = pcall(function()
|
||||||
if Types.RbxId(removedIdOrInstance) then
|
if Types.RbxId(removedIdOrInstance) then
|
||||||
@@ -78,7 +84,7 @@ local function applyPatch(instanceMap, patch)
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local failedToReify = reify(instanceMap, patch.added, id, parentInstance)
|
local failedToReify = reifyInstance(deferredRefs, instanceMap, patch.added, id, parentInstance)
|
||||||
|
|
||||||
if not PatchSet.isEmpty(failedToReify) then
|
if not PatchSet.isEmpty(failedToReify) then
|
||||||
Log.debug("Failed to reify as part of applying a patch: {:#?}", failedToReify)
|
Log.debug("Failed to reify as part of applying a patch: {:#?}", failedToReify)
|
||||||
@@ -143,7 +149,7 @@ local function applyPatch(instanceMap, patch)
|
|||||||
[update.id] = mockVirtualInstance,
|
[update.id] = mockVirtualInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
local failedToReify = reify(instanceMap, mockAdded, update.id, instance.Parent)
|
local failedToReify = reifyInstance(deferredRefs, instanceMap, mockAdded, update.id, instance.Parent)
|
||||||
|
|
||||||
local newInstance = instanceMap.fromIds[update.id]
|
local newInstance = instanceMap.fromIds[update.id]
|
||||||
|
|
||||||
@@ -206,6 +212,18 @@ local function applyPatch(instanceMap, patch)
|
|||||||
|
|
||||||
if update.changedProperties ~= nil then
|
if update.changedProperties ~= nil then
|
||||||
for propertyName, propertyValue in pairs(update.changedProperties) do
|
for propertyName, propertyValue in pairs(update.changedProperties) do
|
||||||
|
-- Because refs may refer to instances that we haven't constructed yet,
|
||||||
|
-- we defer applying any ref properties until all instances are created.
|
||||||
|
if next(propertyValue) == "Ref" then
|
||||||
|
table.insert(deferredRefs, {
|
||||||
|
id = update.id,
|
||||||
|
instance = instance,
|
||||||
|
propertyName = propertyName,
|
||||||
|
virtualValue = propertyValue,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
local decodeSuccess, decodedValue = decodeValue(propertyValue, instanceMap)
|
local decodeSuccess, decodedValue = decodeValue(propertyValue, instanceMap)
|
||||||
if not decodeSuccess then
|
if not decodeSuccess then
|
||||||
unappliedUpdate.changedProperties[propertyName] = propertyValue
|
unappliedUpdate.changedProperties[propertyName] = propertyValue
|
||||||
@@ -230,6 +248,8 @@ local function applyPatch(instanceMap, patch)
|
|||||||
ChangeHistoryService:FinishRecording(historyRecording, Enum.FinishRecordingOperation.Commit)
|
ChangeHistoryService:FinishRecording(historyRecording, Enum.FinishRecordingOperation.Commit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
return unappliedPatch
|
return unappliedPatch
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,24 @@ local function diff(instanceMap, virtualInstances, rootId)
|
|||||||
|
|
||||||
if getProperySuccess then
|
if getProperySuccess then
|
||||||
local existingValue = existingValueOrErr
|
local existingValue = existingValueOrErr
|
||||||
local decodeSuccess, decodedValue = decodeValue(virtualValue, instanceMap)
|
local decodeSuccess, decodedValue
|
||||||
|
|
||||||
|
-- If `virtualValue` is a ref then instead of decoding it to an instance,
|
||||||
|
-- we change `existingValue` to be a ref. This is because `virtualValue`
|
||||||
|
-- may point to an Instance which doesn't exist yet and therefore
|
||||||
|
-- decoding it may throw an error.
|
||||||
|
if next(virtualValue) == "Ref" then
|
||||||
|
decodeSuccess, decodedValue = true, virtualValue
|
||||||
|
|
||||||
|
if existingValue and typeof(existingValue) == "Instance" then
|
||||||
|
local existingValueRef = instanceMap.fromInstances[existingValue]
|
||||||
|
if existingValueRef then
|
||||||
|
existingValue = { Ref = existingValueRef }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
decodeSuccess, decodedValue = decodeValue(virtualValue, instanceMap)
|
||||||
|
end
|
||||||
|
|
||||||
if decodeSuccess then
|
if decodeSuccess then
|
||||||
if not trueEquals(existingValue, decodedValue) then
|
if not trueEquals(existingValue, decodedValue) then
|
||||||
|
|||||||
@@ -7,26 +7,6 @@ local PatchSet = require(script.Parent.Parent.PatchSet)
|
|||||||
local setProperty = require(script.Parent.setProperty)
|
local setProperty = require(script.Parent.setProperty)
|
||||||
local decodeValue = require(script.Parent.decodeValue)
|
local decodeValue = require(script.Parent.decodeValue)
|
||||||
|
|
||||||
local reifyInner, applyDeferredRefs
|
|
||||||
|
|
||||||
local function reify(instanceMap, virtualInstances, rootId, parentInstance)
|
|
||||||
-- Create an empty patch that will be populated with any parts of this reify
|
|
||||||
-- that could not happen, like instances that couldn't be created and
|
|
||||||
-- properties that could not be assigned.
|
|
||||||
local unappliedPatch = PatchSet.newEmpty()
|
|
||||||
|
|
||||||
-- Contains a list of all of the ref properties that we'll need to assign
|
|
||||||
-- after all instances are created. We apply refs in a second pass, after
|
|
||||||
-- we create as many instances as we can, so that we ensure that referents
|
|
||||||
-- can be mapped to instances correctly.
|
|
||||||
local deferredRefs = {}
|
|
||||||
|
|
||||||
reifyInner(instanceMap, virtualInstances, rootId, parentInstance, unappliedPatch, deferredRefs)
|
|
||||||
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
|
||||||
|
|
||||||
return unappliedPatch
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Add the given ID and all of its descendants in virtualInstances to the given
|
Add the given ID and all of its descendants in virtualInstances to the given
|
||||||
PatchSet, marked for addition.
|
PatchSet, marked for addition.
|
||||||
@@ -40,10 +20,21 @@ local function addAllToPatch(patchSet, virtualInstances, id)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function reifyInstance(deferredRefs, instanceMap, virtualInstances, rootId, parentInstance)
|
||||||
|
-- Create an empty patch that will be populated with any parts of this reify
|
||||||
|
-- that could not happen, like instances that couldn't be created and
|
||||||
|
-- properties that could not be assigned.
|
||||||
|
local unappliedPatch = PatchSet.newEmpty()
|
||||||
|
|
||||||
|
reifyInstanceInner(unappliedPatch, deferredRefs, instanceMap, virtualInstances, rootId, parentInstance)
|
||||||
|
|
||||||
|
return unappliedPatch
|
||||||
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Inner function that defines the core routine.
|
Inner function that defines the core routine.
|
||||||
]]
|
]]
|
||||||
function reifyInner(instanceMap, virtualInstances, id, parentInstance, unappliedPatch, deferredRefs)
|
function reifyInstanceInner(unappliedPatch, deferredRefs, instanceMap, virtualInstances, id, parentInstance)
|
||||||
local virtualInstance = virtualInstances[id]
|
local virtualInstance = virtualInstances[id]
|
||||||
|
|
||||||
if virtualInstance == nil then
|
if virtualInstance == nil then
|
||||||
@@ -102,7 +93,7 @@ function reifyInner(instanceMap, virtualInstances, id, parentInstance, unapplied
|
|||||||
end
|
end
|
||||||
|
|
||||||
for _, childId in ipairs(virtualInstance.Children) do
|
for _, childId in ipairs(virtualInstance.Children) do
|
||||||
reifyInner(instanceMap, virtualInstances, childId, instance, unappliedPatch, deferredRefs)
|
reifyInstanceInner(unappliedPatch, deferredRefs, instanceMap, virtualInstances, childId, instance)
|
||||||
end
|
end
|
||||||
|
|
||||||
instance.Parent = parentInstance
|
instance.Parent = parentInstance
|
||||||
@@ -143,6 +134,7 @@ function applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local targetInstance = instanceMap.fromIds[refId]
|
local targetInstance = instanceMap.fromIds[refId]
|
||||||
|
|
||||||
if targetInstance == nil then
|
if targetInstance == nil then
|
||||||
markFailed(entry.id, entry.propertyName, entry.virtualValue)
|
markFailed(entry.id, entry.propertyName, entry.virtualValue)
|
||||||
continue
|
continue
|
||||||
@@ -155,4 +147,7 @@ function applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return reify
|
return {
|
||||||
|
reifyInstance = reifyInstance,
|
||||||
|
applyDeferredRefs = applyDeferredRefs,
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
return function()
|
return function()
|
||||||
local reify = require(script.Parent.reify)
|
local reify = require(script.Parent.reify)
|
||||||
|
local reifyInstance, applyDeferredRefs = reify.reifyInstance, reify.applyDeferredRefs
|
||||||
|
|
||||||
local PatchSet = require(script.Parent.Parent.PatchSet)
|
local PatchSet = require(script.Parent.Parent.PatchSet)
|
||||||
local InstanceMap = require(script.Parent.Parent.InstanceMap)
|
local InstanceMap = require(script.Parent.Parent.InstanceMap)
|
||||||
@@ -20,7 +21,11 @@ return function()
|
|||||||
|
|
||||||
it("should throw when given a bogus ID", function()
|
it("should throw when given a bogus ID", function()
|
||||||
expect(function()
|
expect(function()
|
||||||
reify(InstanceMap.new(), {}, "Hi, mom!", game)
|
local deferredRefs = {}
|
||||||
|
local instanceMap = InstanceMap.new()
|
||||||
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, {}, "Hi, mom!", game)
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
end).to.throw()
|
end).to.throw()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@@ -34,8 +39,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT", nil)
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT", nil)
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(instanceMap:size() == 0, "expected instanceMap to be empty")
|
assert(instanceMap:size() == 0, "expected instanceMap to be empty")
|
||||||
|
|
||||||
@@ -60,8 +68,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
||||||
|
|
||||||
@@ -90,8 +101,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
||||||
|
|
||||||
@@ -122,8 +136,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
expect(size(unappliedPatch.added)).to.equal(1)
|
expect(size(unappliedPatch.added)).to.equal(1)
|
||||||
expect(unappliedPatch.added["CHILD"]).to.equal(virtualInstances["CHILD"])
|
expect(unappliedPatch.added["CHILD"]).to.equal(virtualInstances["CHILD"])
|
||||||
@@ -153,8 +170,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
local instance = instanceMap.fromIds["ROOT"]
|
local instance = instanceMap.fromIds["ROOT"]
|
||||||
expect(instance.ClassName).to.equal("StringValue")
|
expect(instance.ClassName).to.equal("StringValue")
|
||||||
@@ -196,8 +216,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
||||||
|
|
||||||
@@ -223,13 +246,16 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
|
|
||||||
local existing = Instance.new("Folder")
|
local existing = Instance.new("Folder")
|
||||||
existing.Name = "Existing"
|
existing.Name = "Existing"
|
||||||
instanceMap:insert("EXISTING", existing)
|
instanceMap:insert("EXISTING", existing)
|
||||||
|
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
||||||
|
|
||||||
@@ -268,8 +294,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
||||||
|
|
||||||
@@ -307,8 +336,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty")
|
||||||
|
|
||||||
@@ -332,8 +364,11 @@ return function()
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local deferredRefs = {}
|
||||||
local instanceMap = InstanceMap.new()
|
local instanceMap = InstanceMap.new()
|
||||||
local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT")
|
local unappliedPatch = reifyInstance(deferredRefs, instanceMap, virtualInstances, "ROOT")
|
||||||
|
|
||||||
|
applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch)
|
||||||
|
|
||||||
assert(not PatchSet.hasRemoves(unappliedPatch), "expected no removes")
|
assert(not PatchSet.hasRemoves(unappliedPatch), "expected no removes")
|
||||||
assert(not PatchSet.hasAdditions(unappliedPatch), "expected no additions")
|
assert(not PatchSet.hasAdditions(unappliedPatch), "expected no additions")
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
rojo build test-place.project.json -o TestPlace.rbxlx
|
|
||||||
run-in-roblox --script run-tests.server.lua --place TestPlace.rbxlx
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
"ReplicatedStorage": {
|
"ReplicatedStorage": {
|
||||||
"Rojo": {
|
"Rojo": {
|
||||||
"$path": "default.project.json"
|
"$path": "../plugin.project.json"
|
||||||
},
|
},
|
||||||
|
|
||||||
"Packages": {
|
"Packages": {
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Continously build the rojo plugin into the local plugin directory on Windows
|
|
||||||
rojo build plugin/default.project.json -o $LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm --watch
|
|
||||||
@@ -6,6 +6,7 @@ expression: contents
|
|||||||
<Item class="Model" referent="0">
|
<Item class="Model" referent="0">
|
||||||
<Properties>
|
<Properties>
|
||||||
<string name="Name">init_meta_class_name</string>
|
<string name="Name">init_meta_class_name</string>
|
||||||
|
<bool name="NeedsPivotMigration">false</bool>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Item>
|
</Item>
|
||||||
</roblox>
|
</roblox>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/build.rs
|
source: tests/tests/build.rs
|
||||||
expression: contents
|
expression: contents
|
||||||
|
|
||||||
---
|
---
|
||||||
<roblox version="4">
|
<roblox version="4">
|
||||||
<Item class="Folder" referent="0">
|
<Item class="Folder" referent="0">
|
||||||
@@ -25,6 +24,7 @@ expression: contents
|
|||||||
<R21>0</R21>
|
<R21>0</R21>
|
||||||
<R22>1</R22>
|
<R22>1</R22>
|
||||||
</CoordinateFrame>
|
</CoordinateFrame>
|
||||||
|
<bool name="NeedsPivotMigration">false</bool>
|
||||||
<Ref name="PrimaryPart">null</Ref>
|
<Ref name="PrimaryPart">null</Ref>
|
||||||
<BinaryString name="Tags"></BinaryString>
|
<BinaryString name="Tags"></BinaryString>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/build.rs
|
source: tests/tests/build.rs
|
||||||
expression: contents
|
expression: contents
|
||||||
|
|
||||||
---
|
---
|
||||||
<roblox version="4">
|
<roblox version="4">
|
||||||
<Item class="DataModel" referent="0">
|
<Item class="DataModel" referent="0">
|
||||||
@@ -22,6 +21,7 @@ expression: contents
|
|||||||
<Item class="Workspace" referent="2">
|
<Item class="Workspace" referent="2">
|
||||||
<Properties>
|
<Properties>
|
||||||
<string name="Name">Workspace</string>
|
<string name="Name">Workspace</string>
|
||||||
|
<bool name="NeedsPivotMigration">false</bool>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Item class="BoolValue" referent="3">
|
<Item class="BoolValue" referent="3">
|
||||||
<Properties>
|
<Properties>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
|
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
gameId: ~
|
gameId: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
|
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
gameId: ~
|
gameId: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
|
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
gameId: ~
|
gameId: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
|
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
|
||||||
|
|
||||||
---
|
---
|
||||||
instances:
|
instances:
|
||||||
id-2:
|
id-2:
|
||||||
@@ -22,7 +21,8 @@ instances:
|
|||||||
ignoreUnknownInstances: false
|
ignoreUnknownInstances: false
|
||||||
Name: test
|
Name: test
|
||||||
Parent: id-2
|
Parent: id-2
|
||||||
Properties: {}
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
messageCursor: 1
|
messageCursor: 1
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
|
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
gameId: ~
|
gameId: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
|
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
|
||||||
|
|
||||||
---
|
---
|
||||||
messageCursor: 1
|
messageCursor: 1
|
||||||
messages:
|
messages:
|
||||||
@@ -14,8 +13,9 @@ messages:
|
|||||||
ignoreUnknownInstances: false
|
ignoreUnknownInstances: false
|
||||||
Name: test
|
Name: test
|
||||||
Parent: id-2
|
Parent: id-2
|
||||||
Properties: {}
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
removed: []
|
removed: []
|
||||||
updated: []
|
updated: []
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
source: tests/tests/serve.rs
|
||||||
|
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
|
||||||
|
---
|
||||||
|
instances:
|
||||||
|
id-2:
|
||||||
|
Children:
|
||||||
|
- id-3
|
||||||
|
ClassName: DataModel
|
||||||
|
Id: id-2
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: pivot_migration
|
||||||
|
Parent: "00000000000000000000000000000000"
|
||||||
|
Properties: {}
|
||||||
|
id-3:
|
||||||
|
Children:
|
||||||
|
- id-4
|
||||||
|
- id-5
|
||||||
|
- id-6
|
||||||
|
ClassName: Workspace
|
||||||
|
Id: id-3
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: Workspace
|
||||||
|
Parent: id-2
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
id-4:
|
||||||
|
Children: []
|
||||||
|
ClassName: Model
|
||||||
|
Id: id-4
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: Model
|
||||||
|
Parent: id-3
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
id-5:
|
||||||
|
Children: []
|
||||||
|
ClassName: Tool
|
||||||
|
Id: id-5
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: false
|
||||||
|
Name: Tool
|
||||||
|
Parent: id-3
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
id-6:
|
||||||
|
Children: []
|
||||||
|
ClassName: Actor
|
||||||
|
Id: id-6
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: Actor
|
||||||
|
Parent: id-3
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
messageCursor: 1
|
||||||
|
sessionId: id-1
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
source: tests/tests/serve.rs
|
||||||
|
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
|
||||||
|
---
|
||||||
|
messageCursor: 1
|
||||||
|
messages:
|
||||||
|
- added:
|
||||||
|
id-6:
|
||||||
|
Children: []
|
||||||
|
ClassName: Actor
|
||||||
|
Id: id-6
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: Actor
|
||||||
|
Parent: id-3
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
removed: []
|
||||||
|
updated:
|
||||||
|
- changedClassName: ~
|
||||||
|
changedMetadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
changedName: ~
|
||||||
|
changedProperties: {}
|
||||||
|
id: id-3
|
||||||
|
sessionId: id-1
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
|
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
gameId: ~
|
gameId: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
assertion_line: 316
|
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
assertion_line: 335
|
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
assertion_line: 351
|
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
source: tests/tests/serve.rs
|
||||||
|
expression: "read_response.intern_and_redact(&mut redactions, root_id)"
|
||||||
|
---
|
||||||
|
instances:
|
||||||
|
id-2:
|
||||||
|
Children:
|
||||||
|
- id-3
|
||||||
|
ClassName: DataModel
|
||||||
|
Id: id-2
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: pivot_migration
|
||||||
|
Parent: "00000000000000000000000000000000"
|
||||||
|
Properties: {}
|
||||||
|
id-3:
|
||||||
|
Children:
|
||||||
|
- id-4
|
||||||
|
- id-5
|
||||||
|
ClassName: Workspace
|
||||||
|
Id: id-3
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: Workspace
|
||||||
|
Parent: id-2
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
id-4:
|
||||||
|
Children: []
|
||||||
|
ClassName: Model
|
||||||
|
Id: id-4
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: true
|
||||||
|
Name: Model
|
||||||
|
Parent: id-3
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
id-5:
|
||||||
|
Children: []
|
||||||
|
ClassName: Tool
|
||||||
|
Id: id-5
|
||||||
|
Metadata:
|
||||||
|
ignoreUnknownInstances: false
|
||||||
|
Name: Tool
|
||||||
|
Parent: id-3
|
||||||
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
|
messageCursor: 0
|
||||||
|
sessionId: id-1
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
source: tests/tests/serve.rs
|
||||||
|
expression: redactions.redacted_yaml(info)
|
||||||
|
---
|
||||||
|
expectedPlaceIds: ~
|
||||||
|
gameId: ~
|
||||||
|
placeId: ~
|
||||||
|
projectName: pivot_migration
|
||||||
|
protocolVersion: 4
|
||||||
|
rootInstanceId: id-2
|
||||||
|
serverVersion: "[server-version]"
|
||||||
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
@@ -31,6 +31,8 @@ instances:
|
|||||||
Attributes:
|
Attributes:
|
||||||
Rojo_Target_PrimaryPart:
|
Rojo_Target_PrimaryPart:
|
||||||
String: project target
|
String: project target
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
PrimaryPart:
|
PrimaryPart:
|
||||||
Ref: id-9
|
Ref: id-9
|
||||||
id-2:
|
id-2:
|
||||||
@@ -55,7 +57,9 @@ instances:
|
|||||||
ignoreUnknownInstances: true
|
ignoreUnknownInstances: true
|
||||||
Name: Workspace
|
Name: Workspace
|
||||||
Parent: id-2
|
Parent: id-2
|
||||||
Properties: {}
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
id-4:
|
id-4:
|
||||||
Children: []
|
Children: []
|
||||||
ClassName: ObjectValue
|
ClassName: ObjectValue
|
||||||
@@ -124,6 +128,8 @@ instances:
|
|||||||
Attributes:
|
Attributes:
|
||||||
Rojo_Target_PrimaryPart:
|
Rojo_Target_PrimaryPart:
|
||||||
String: model target 2
|
String: model target 2
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
PrimaryPart:
|
PrimaryPart:
|
||||||
Ref: id-7
|
Ref: id-7
|
||||||
id-9:
|
id-9:
|
||||||
@@ -138,4 +144,3 @@ instances:
|
|||||||
Properties: {}
|
Properties: {}
|
||||||
messageCursor: 1
|
messageCursor: 1
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ instances:
|
|||||||
ignoreUnknownInstances: true
|
ignoreUnknownInstances: true
|
||||||
Name: Workspace
|
Name: Workspace
|
||||||
Parent: id-2
|
Parent: id-2
|
||||||
Properties: {}
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
id-4:
|
id-4:
|
||||||
Children: []
|
Children: []
|
||||||
ClassName: ObjectValue
|
ClassName: ObjectValue
|
||||||
@@ -104,6 +106,8 @@ instances:
|
|||||||
Attributes:
|
Attributes:
|
||||||
Rojo_Target_PrimaryPart:
|
Rojo_Target_PrimaryPart:
|
||||||
String: model target
|
String: model target
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
PrimaryPart:
|
PrimaryPart:
|
||||||
Ref: id-7
|
Ref: id-7
|
||||||
id-9:
|
id-9:
|
||||||
@@ -118,4 +122,3 @@ instances:
|
|||||||
Properties: {}
|
Properties: {}
|
||||||
messageCursor: 0
|
messageCursor: 0
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ instances:
|
|||||||
ignoreUnknownInstances: true
|
ignoreUnknownInstances: true
|
||||||
Name: Workspace
|
Name: Workspace
|
||||||
Parent: id-2
|
Parent: id-2
|
||||||
Properties: {}
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
id-4:
|
id-4:
|
||||||
Children: []
|
Children: []
|
||||||
ClassName: ObjectValue
|
ClassName: ObjectValue
|
||||||
@@ -104,8 +106,12 @@ instances:
|
|||||||
Attributes:
|
Attributes:
|
||||||
Rojo_Target_PrimaryPart:
|
Rojo_Target_PrimaryPart:
|
||||||
String: model target
|
String: model target
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
PrimaryPart:
|
PrimaryPart:
|
||||||
Ref: id-7
|
Ref: id-7
|
||||||
|
Scale:
|
||||||
|
Float32: 1
|
||||||
id-9:
|
id-9:
|
||||||
Children:
|
Children:
|
||||||
- id-10
|
- id-10
|
||||||
@@ -116,5 +122,5 @@ instances:
|
|||||||
Name: ProjectTarget
|
Name: ProjectTarget
|
||||||
Parent: id-3
|
Parent: id-3
|
||||||
Properties: {}
|
Properties: {}
|
||||||
messageCursor: 0
|
messageCursor: 1
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ instances:
|
|||||||
ignoreUnknownInstances: true
|
ignoreUnknownInstances: true
|
||||||
Name: Workspace
|
Name: Workspace
|
||||||
Parent: id-2
|
Parent: id-2
|
||||||
Properties: {}
|
Properties:
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
id-4:
|
id-4:
|
||||||
Children: []
|
Children: []
|
||||||
ClassName: ObjectValue
|
ClassName: ObjectValue
|
||||||
@@ -104,6 +106,8 @@ instances:
|
|||||||
Attributes:
|
Attributes:
|
||||||
Rojo_Target_PrimaryPart:
|
Rojo_Target_PrimaryPart:
|
||||||
String: model target
|
String: model target
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
PrimaryPart:
|
PrimaryPart:
|
||||||
Ref: id-7
|
Ref: id-7
|
||||||
id-9:
|
id-9:
|
||||||
|
|||||||
@@ -10,3 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
source: tests/tests/serve.rs
|
||||||
|
expression: "subscribe_response.intern_and_redact(&mut redactions, ())"
|
||||||
|
---
|
||||||
|
messageCursor: 1
|
||||||
|
messages:
|
||||||
|
- added: {}
|
||||||
|
removed: []
|
||||||
|
updated:
|
||||||
|
- changedClassName: ~
|
||||||
|
changedMetadata: ~
|
||||||
|
changedName: ~
|
||||||
|
changedProperties:
|
||||||
|
Scale:
|
||||||
|
Float32: 1
|
||||||
|
id: id-8
|
||||||
|
sessionId: id-1
|
||||||
@@ -10,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ messages:
|
|||||||
Attributes:
|
Attributes:
|
||||||
Rojo_Target_PrimaryPart:
|
Rojo_Target_PrimaryPart:
|
||||||
String: project target
|
String: project target
|
||||||
|
NeedsPivotMigration:
|
||||||
|
Bool: false
|
||||||
PrimaryPart:
|
PrimaryPart:
|
||||||
Ref: id-9
|
Ref: id-9
|
||||||
removed: []
|
removed: []
|
||||||
@@ -43,4 +45,3 @@ messages:
|
|||||||
PrimaryPart: ~
|
PrimaryPart: ~
|
||||||
id: id-8
|
id: id-8
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
|
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
gameId: ~
|
gameId: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
|
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
gameId: ~
|
gameId: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
assertion_line: 265
|
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
assertion_line: 281
|
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
assertion_line: 297
|
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
@@ -11,4 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
---
|
---
|
||||||
source: tests/tests/serve.rs
|
source: tests/tests/serve.rs
|
||||||
assertion_line: 383
|
|
||||||
expression: redactions.redacted_yaml(info)
|
expression: redactions.redacted_yaml(info)
|
||||||
---
|
---
|
||||||
expectedPlaceIds: ~
|
expectedPlaceIds: ~
|
||||||
@@ -11,3 +10,4 @@ protocolVersion: 4
|
|||||||
rootInstanceId: id-2
|
rootInstanceId: id-2
|
||||||
serverVersion: "[server-version]"
|
serverVersion: "[server-version]"
|
||||||
sessionId: id-1
|
sessionId: id-1
|
||||||
|
unexpectedPlaceIds: ~
|
||||||
|
|||||||
3
rojo-test/serve-tests/pivot_migration/Tool.model.json
Normal file
3
rojo-test/serve-tests/pivot_migration/Tool.model.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"className": "Tool"
|
||||||
|
}
|
||||||
14
rojo-test/serve-tests/pivot_migration/default.project.json
Normal file
14
rojo-test/serve-tests/pivot_migration/default.project.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "pivot_migration",
|
||||||
|
"tree": {
|
||||||
|
"$className": "DataModel",
|
||||||
|
"Workspace": {
|
||||||
|
"Model": {
|
||||||
|
"$className": "Model"
|
||||||
|
},
|
||||||
|
"Tool": {
|
||||||
|
"$path": "Tool.model.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
scripts/unit-test-plugin.sh
Normal file
2
scripts/unit-test-plugin.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
rojo build plugin/test-place.project.json -o TestPlace.rbxl
|
||||||
|
run-in-roblox --script plugin/run-tests.server.lua --place TestPlace.rbxl
|
||||||
1
scripts/watch-build-plugin.sh
Normal file
1
scripts/watch-build-plugin.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
rojo build plugin.project.json --plugin Rojo.rbxm --watch
|
||||||
@@ -136,7 +136,7 @@ impl JobThreadContext {
|
|||||||
// created all at once.
|
// created all at once.
|
||||||
let mut current_path = path.as_path();
|
let mut current_path = path.as_path();
|
||||||
let affected_ids = loop {
|
let affected_ids = loop {
|
||||||
let ids = tree.get_ids_at_path(¤t_path);
|
let ids = tree.get_ids_at_path(current_path);
|
||||||
|
|
||||||
log::trace!("Path {} affects IDs {:?}", current_path.display(), ids);
|
log::trace!("Path {} affects IDs {:?}", current_path.display(), ids);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const UNKNOWN_PLUGIN_KIND_ERR: &str = "Could not detect what kind of file to bui
|
|||||||
/// Generates a model or place file from the Rojo project.
|
/// Generates a model or place file from the Rojo project.
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
pub struct BuildCommand {
|
pub struct BuildCommand {
|
||||||
/// Path to the project to serve. Defaults to the current directory.
|
/// Path to the project to build. Defaults to the current directory.
|
||||||
#[clap(default_value = "")]
|
#[clap(default_value = "")]
|
||||||
pub project: PathBuf,
|
pub project: PathBuf,
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use clap::Parser;
|
|||||||
use fs_err::File;
|
use fs_err::File;
|
||||||
use memofs::Vfs;
|
use memofs::Vfs;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use rbx_dom_weak::types::Ref;
|
use rbx_dom_weak::{types::Ref, Ustr};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ const PATH_STRIP_FAILED_ERR: &str = "Failed to create relative paths for project
|
|||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct SourcemapNode<'a> {
|
struct SourcemapNode<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
class_name: &'a str,
|
class_name: Ustr,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
file_paths: Vec<PathBuf>,
|
file_paths: Vec<PathBuf>,
|
||||||
@@ -67,7 +67,7 @@ impl SourcemapCommand {
|
|||||||
let vfs = Vfs::new_default();
|
let vfs = Vfs::new_default();
|
||||||
vfs.set_watch_enabled(self.watch);
|
vfs.set_watch_enabled(self.watch);
|
||||||
|
|
||||||
let session = ServeSession::new(vfs, &project_path)?;
|
let session = ServeSession::new(vfs, project_path)?;
|
||||||
let mut cursor = session.message_queue().cursor();
|
let mut cursor = session.message_queue().cursor();
|
||||||
|
|
||||||
let filter = if self.include_non_scripts {
|
let filter = if self.include_non_scripts {
|
||||||
@@ -113,7 +113,7 @@ fn filter_nothing(_instance: &InstanceWithMeta) -> bool {
|
|||||||
|
|
||||||
fn filter_non_scripts(instance: &InstanceWithMeta) -> bool {
|
fn filter_non_scripts(instance: &InstanceWithMeta) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
instance.class_name(),
|
instance.class_name().as_str(),
|
||||||
"Script" | "LocalScript" | "ModuleScript"
|
"Script" | "LocalScript" | "ModuleScript"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ trait FmtLua {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct DisplayLua<T>(T);
|
struct DisplayLua<T>(T);
|
||||||
|
|
||||||
impl<T> fmt::Display for DisplayLua<T>
|
impl<T> fmt::Display for DisplayLua<T>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user