Skip to content

Commit ebbda14

Browse files
committed
feat: insert
1 parent 37d4c5a commit ebbda14

21 files changed

Lines changed: 324 additions & 37 deletions

extensions/arcs.luau

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ local UserInputService = game:GetService("UserInputService")
88
local Extension = require("@src/core/Extension")
99
local Gizmos = require("@src/core/Gizmos")
1010
local Iris = require("@src/Iris")
11+
local UserIds = require("@src/constants/UserIds")
1112
local assets = require("@include/assets")
12-
local constants = require("@src/constants")
1313
local createCoreExtension = require("@src/core/constructors/createCoreExtension")
1414

1515
local FACE_AXES: { [Enum.NormalId]: { normal: Vector3, u: Vector3, v: Vector3 } } = {
@@ -33,8 +33,8 @@ local ext = createCoreExtension({
3333
description = "Create smooth arcs from the selected parts.",
3434
icon = assets.extensions.rocket,
3535
contributors = {
36-
{ type = "user", id = constants.userIds.syylvi },
37-
{ type = "user", id = constants.userIds.znotfireman },
36+
{ type = "user", id = UserIds.syylvi },
37+
{ type = "user", id = UserIds.znotfireman },
3838
},
3939
})
4040

extensions/color-picker.luau

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
local Extension = require("@src/core/Extension")
2+
local UserIds = require("@src/constants/UserIds")
23
local assets = require("@include/assets")
3-
local constants = require("@src/constants")
44
local createCoreExtension = require("@src/core/constructors/createCoreExtension")
55

66
local ext = createCoreExtension({
@@ -9,7 +9,7 @@ local ext = createCoreExtension({
99
description = "TBA",
1010
icon = assets.extensions.rocket,
1111
contributors = {
12-
{ type = "user", id = constants.userIds.znotfireman },
12+
{ type = "user", id = UserIds.znotfireman },
1313
},
1414
})
1515

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
local types = require("./types")
2+
3+
local function wrapClassInserter(class: string, assetProperty: string): types.Inserter
4+
return function(product)
5+
local instance = Instance.new(class);
6+
(instance :: any)[assetProperty] = `rbxassetid://{product.AssetId}`
7+
return instance
8+
end
9+
end
10+
11+
local insertImageOptions: { types.InsertOptions } = {
12+
{ label = "As Decal", insert = wrapClassInserter("Decal", "Texture") },
13+
{ label = "As Texture", insert = wrapClassInserter("Texture", "Texture") },
14+
{ label = "As ImageLabel", insert = wrapClassInserter("ImageLabel", "Image") },
15+
{ label = "As ImageButton", insert = wrapClassInserter("ImageButton", "Image") },
16+
}
17+
18+
local insertAssetOptions = {
19+
{
20+
label = "Insert",
21+
insert = function(product: types.ProductInfo)
22+
-- InsertSevice:LoadAsset requires you to own the asset </3
23+
local objects = game:GetObjects(`rbxassetid://{product.AssetId}`)
24+
if #objects == 1 then
25+
return objects[1]
26+
end
27+
28+
local container: Instance = Instance.new("Model")
29+
container.Name = product.Name
30+
31+
for _, child in objects do
32+
child.Parent = container
33+
end
34+
35+
return container
36+
end,
37+
},
38+
}
39+
40+
local assetInserters: { [number]: { types.InsertOptions }? } = {
41+
[Enum.AssetType.Image.Value] = insertImageOptions,
42+
[Enum.AssetType.Decal.Value] = insertImageOptions,
43+
44+
[Enum.AssetType.Lua.Value] = insertAssetOptions,
45+
[Enum.AssetType.Plugin.Value] = insertAssetOptions,
46+
[Enum.AssetType.MeshPart.Value] = insertAssetOptions,
47+
48+
[Enum.AssetType.Audio.Value] = {
49+
{ label = "Insert", insert = wrapClassInserter("Sound", "SoundId") },
50+
},
51+
52+
[Enum.AssetType.Mesh.Value] = {
53+
{
54+
label = "Insert",
55+
insert = function(product: types.ProductInfo)
56+
local instance = Instance.new("Part")
57+
instance.Anchored = true
58+
59+
local mesh = Instance.new("SpecialMesh")
60+
mesh.MeshId = `rbxassetid://{product.AssetId}`
61+
mesh.Parent = instance
62+
63+
return instance
64+
end,
65+
},
66+
},
67+
}
68+
69+
return assetInserters

extensions/insert/init.luau

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
local UserInputService = game:GetService("UserInputService")
2+
local Workspace = game:GetService("Workspace")
3+
4+
local Extension = require("@src/core/Extension")
5+
local Iris = require("@src/Iris")
6+
local UserIds = require("@src/constants/UserIds")
7+
local assetInserters = require("@self/assetInserters")
8+
local assets = require("@include/assets")
9+
local createCoreExtension = require("@src/core/constructors/createCoreExtension")
10+
local products = require("@self/products")
11+
local types = require("@self/types")
12+
local widgets = require("@src/widgets")
13+
14+
local ext = createCoreExtension {
15+
id = "rocket-insert",
16+
title = "Insert",
17+
description = "TBA",
18+
icon = assets.extensions.rocket,
19+
contributors = {
20+
{ type = "user", id = UserIds.znotfireman },
21+
},
22+
}
23+
24+
ext:newCommand({
25+
id = "insert-asset",
26+
title = "Insert Asset",
27+
description = "Fetches and inserts the given asset ID into the game.",
28+
}, function(r: Extension.CommandRuntime)
29+
local output = r:createCommandOutput()
30+
31+
function output.renderWindow(window: Iris.Window)
32+
local maybeAssetId, assetInput = widgets.InstantInputText({ hint = "ie. 1234567890", label = "Asset ID" })
33+
34+
if r.isFirstRun then
35+
window.state.position:set(UserInputService:GetMouseLocation())
36+
assetInput.state.text:set("")
37+
maybeAssetId = ""
38+
end
39+
40+
local assetId = tonumber(maybeAssetId)
41+
if not assetId then
42+
return
43+
end
44+
45+
local product = products.fetch(assetId)
46+
if not product then
47+
widgets.Subtext({
48+
if products.invalidIds[assetId] then `Invalid asset ID "{assetId}"!` else "Fetching asset...",
49+
})
50+
return
51+
end
52+
53+
local assetTypeId = product.AssetTypeId
54+
-- selene: allow(incorrect_standard_library_use)
55+
local maybeAssetType = Enum.AssetType:FromValue(assetTypeId)
56+
local assetTypeName = if maybeAssetType then maybeAssetType.Name else "Unknown"
57+
58+
local inserter = assetInserters[assetTypeId]
59+
if not inserter then
60+
Iris.Text({ `Rocket doesn't support inserting assets of type {assetTypeName}!` })
61+
widgets.Subtext({ `asset type ID: {assetTypeId}` })
62+
return
63+
end
64+
65+
widgets.Subtext({ `Got asset of type {assetTypeName}! (asset type ID: {assetTypeId})` })
66+
67+
Iris.SameLine()
68+
for _, options in inserter do
69+
if not Iris.Button({ options.label }).clicked() then
70+
continue
71+
end
72+
73+
task.spawn(function(r: Extension.CommandRuntime, product: types.ProductInfo)
74+
window.state.isOpened:set(false)
75+
local finishRecording = r:recordChangeHistory()
76+
77+
local success, inserted: Instance = pcall(options.insert, product)
78+
local recordingOperation = Enum.FinishRecordingOperation.Commit
79+
if success then
80+
r.log:trace(`Successfully inserted "{product.Name}" (ID: {product.AssetId}) as`, inserted)
81+
inserted.Parent = r:useSelection()[1] or Workspace
82+
r:setSelection({ inserted })
83+
else
84+
r.log:warn(`Failed to insert "{product.Name}" (ID: {product.AssetId}):`, inserted)
85+
recordingOperation = Enum.FinishRecordingOperation.Cancel
86+
end
87+
88+
finishRecording(recordingOperation)
89+
window.state.isOpened:set(true)
90+
r:cleanup()
91+
end, r, product)
92+
end
93+
Iris.End()
94+
end
95+
96+
return output
97+
end)
98+
99+
ext:newCommand({
100+
id = "insert-avatar",
101+
title = "Insert Avatar",
102+
description = "Search, fetches, and inserts the given user's avatar into the game.",
103+
}, function()
104+
-- TODO
105+
end)
106+
107+
ext:newCommand({
108+
id = "insert-pkg-pesde",
109+
title = "Insert Package from pesde",
110+
description = "Search, fetches, and inserts from the pesde package manager.",
111+
}, function()
112+
-- TODO
113+
end)
114+
115+
ext:newCommand({
116+
id = "insert-pkg-wally",
117+
title = "Insert Package from Wally",
118+
description = "Search, fetches, and inserts from the Wally package manager.",
119+
}, function()
120+
-- TODO
121+
end)
122+
123+
ext:newCommand({
124+
id = "insert-git",
125+
title = "Insert from Git",
126+
description = "Inserts a Git repository into the game.",
127+
}, function()
128+
-- TODO
129+
end)
130+
131+
return ext

extensions/insert/products.luau

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
local MarketplaceService = game:GetService("MarketplaceService")
2+
3+
local pluginTrove = require("@src/pluginTrove")
4+
local types = require("./types")
5+
6+
local cache: { [number]: types.ProductInfo } = {}
7+
local threads = {}
8+
local invalidIds = {}
9+
10+
local function fetch(assetId: number): types.ProductInfo?
11+
local existing = cache[assetId]
12+
if existing then
13+
return existing
14+
end
15+
16+
if not (threads[assetId] or invalidIds[assetId]) then
17+
threads[assetId] = task.spawn(function(assetId: number)
18+
local productExists, productInfo =
19+
pcall(MarketplaceService.GetProductInfoAsync, MarketplaceService, assetId, nil)
20+
21+
if productExists then
22+
cache[assetId] = productInfo
23+
else
24+
invalidIds[assetId] = true
25+
end
26+
27+
threads[assetId] = nil
28+
end, assetId)
29+
end
30+
31+
return nil
32+
end
33+
34+
pluginTrove:Add(function()
35+
for _, thread in threads do
36+
pcall(task.cancel, thread)
37+
end
38+
39+
table.clear(cache)
40+
table.clear(threads)
41+
table.clear(invalidIds)
42+
end)
43+
44+
return table.freeze({
45+
cache = cache,
46+
threads = threads,
47+
invalidIds = invalidIds,
48+
fetch = fetch,
49+
})

extensions/insert/types.luau

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export type Inserter = (product: ProductInfo) -> Instance
2+
export type InsertOptions = { label: string, insert: Inserter }
3+
4+
export type ProductInfo = {
5+
Name: string,
6+
Description: string,
7+
PriceInRobux: number,
8+
ProductId: number,
9+
ProductType: string,
10+
Created: string,
11+
Updated: string,
12+
ContentRatingTypeId: number,
13+
MinimumMembershipLevel: number,
14+
IsPublicDomain: boolean,
15+
TargetId: number,
16+
17+
AssetId: number,
18+
AssetTypeId: number,
19+
}
20+
21+
return nil

extensions/light-sources/init.luau

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ local UserInputService = game:GetService("UserInputService")
33

44
local Extension = require("@src/core/Extension")
55
local Iris = require("@src/Iris")
6+
local UserIds = require("@src/constants/UserIds")
67
local assets = require("@include/assets")
7-
local constants = require("@src/constants")
88
local createCoreExtension = require("@src/core/constructors/createCoreExtension")
99
local getRepositionState = require("@self/utils/getRepositionState")
1010
local repositions = require("@self/repositions")
@@ -17,7 +17,7 @@ local ext = createCoreExtension {
1717
description = "Artist-friendly visual control of the sun, the moon, and light instances.",
1818
icon = assets.extensions.lighting.sun,
1919
contributors = {
20-
{ type = "user", id = constants.userIds.znotfireman },
20+
{ type = "user", id = UserIds.znotfireman },
2121
},
2222
}
2323

extensions/lighting.luau

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
local Lighting = game:GetService("Lighting")
22

33
local Extension = require("@src/core/Extension")
4+
local UserIds = require("@src/constants/UserIds")
45
local assets = require("@include/assets")
5-
local constants = require("@src/constants")
66
local createCoreExtension = require("@src/core/constructors/createCoreExtension")
77

88
local ext = createCoreExtension {
@@ -11,7 +11,7 @@ local ext = createCoreExtension {
1111
description = "Artist-friendly lighting control with visual control of the sun and moon.",
1212
icon = assets.extensions.lighting.sun,
1313
contributors = {
14-
{ type = "user", id = constants.userIds.znotfireman },
14+
{ type = "user", id = UserIds.znotfireman },
1515
},
1616
}
1717

extensions/rocket.luau

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ local Command = require("@src/core/commands/Command")
22
local CommandStore = require("@src/core/commands/CommandStore")
33
local Extension = require("@src/core/Extension")
44
local Iris = require("@src/Iris")
5+
local UserIds = require("@src/constants/UserIds")
56
local assets = require("@include/assets")
6-
local constants = require("@src/constants")
77
local createCoreExtension = require("@src/core/constructors/createCoreExtension")
88
local widgets = require("@src/widgets")
99

@@ -13,7 +13,7 @@ local ext = createCoreExtension {
1313
description = "Basic Rocket utilities and commands.",
1414
icon = assets.extensions.rocket,
1515
contributors = {
16-
{ type = "user", id = constants.userIds.znotfireman },
16+
{ type = "user", id = UserIds.znotfireman },
1717
},
1818
}
1919

extensions/scripts.luau

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ local ScriptEditorService = game:GetService("ScriptEditorService")
22

33
local Extension = require("@src/core/Extension")
44
local Iris = require("@src/Iris")
5+
local UserIds = require("@src/constants/UserIds")
56
local assets = require("@include/assets")
6-
local constants = require("@src/constants")
77
local createCoreExtension = require("@src/core/constructors/createCoreExtension")
88
local pluginTrove = require("@src/pluginTrove")
99
local widgets = require("@src/widgets")
@@ -14,7 +14,7 @@ local ext = createCoreExtension {
1414
description = "TBA",
1515
icon = assets.extensions.rocket,
1616
contributors = {
17-
{ type = "user", id = constants.userIds.znotfireman },
17+
{ type = "user", id = UserIds.znotfireman },
1818
},
1919
}
2020

0 commit comments

Comments
 (0)