@webspatial/platform-visionos 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/Packages/RealityKitContent/.build/workspace-state.json +7 -0
- package/Packages/RealityKitContent/.swiftpm/xcode/xcuserdata/bytedance.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/Packages/RealityKitContent/Package.realitycomposerpro/ProjectData/main.json +11 -0
- package/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/SceneMetadataList.json +112 -0
- package/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/Settings.rcprojectdata +17 -0
- package/Packages/RealityKitContent/Package.swift +27 -0
- package/Packages/RealityKitContent/README.md +3 -0
- package/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Immersive.usda +50 -0
- package/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Materials/GridMaterial.usda +216 -0
- package/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Scene.usda +59 -0
- package/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift +4 -0
- package/package.json +27 -0
- package/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json +12 -0
- package/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json +6 -0
- package/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Contents.json +17 -0
- package/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json +12 -0
- package/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json +6 -0
- package/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json +12 -0
- package/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json +6 -0
- package/web-spatial/Assets.xcassets/Contents.json +6 -0
- package/web-spatial/Info.plist +33 -0
- package/web-spatial/Preview Content/Preview Assets.xcassets/Contents.json +6 -0
- package/web-spatial/libs/EventEmitter.swift +32 -0
- package/web-spatial/libs/SpatialComponent.swift +31 -0
- package/web-spatial/libs/SpatialEntity.swift +179 -0
- package/web-spatial/libs/SpatialInputComponent.swift +26 -0
- package/web-spatial/libs/SpatialMeshResource.swift +19 -0
- package/web-spatial/libs/SpatialModel3DComponent.swift +51 -0
- package/web-spatial/libs/SpatialModelComponent.swift +32 -0
- package/web-spatial/libs/SpatialObject.swift +144 -0
- package/web-spatial/libs/SpatialPhysicallyBasedMaterial.swift +19 -0
- package/web-spatial/libs/SpatialViewComponent.swift +15 -0
- package/web-spatial/libs/SpatialWindowComponent.swift +443 -0
- package/web-spatial/libs/SpatialWindowContainer.swift +149 -0
- package/web-spatial/libs/Utils/CommandManager.swift +800 -0
- package/web-spatial/libs/Utils/Logger.swift +36 -0
- package/web-spatial/libs/Utils/SceneManager.swift +108 -0
- package/web-spatial/libs/Utils/WindowContainerMgr.swift +117 -0
- package/web-spatial/libs/json/JsonParser.swift +52 -0
- package/web-spatial/libs/uiKitDelegate/Window.swift +34 -0
- package/web-spatial/libs/webView/UpdateSystem.swift +33 -0
- package/web-spatial/libs/webView/backend/NativeWebView.swift +319 -0
- package/web-spatial/libs/webView/manifest.swift +92 -0
- package/web-spatial/static-web/index.html +9 -0
- package/web-spatial/views/HideViewModifier.swift +17 -0
- package/web-spatial/views/ImmersiveView.swift +24 -0
- package/web-spatial/views/LoadingView.swift +29 -0
- package/web-spatial/views/MaterialWithBorderCornerModifier.swift +82 -0
- package/web-spatial/views/OpenDismissHandlerUI.swift +52 -0
- package/web-spatial/views/PlainWindowContainerView.swift +84 -0
- package/web-spatial/views/SpatialModel3DView.swift +193 -0
- package/web-spatial/views/SpatialViewUI.swift +168 -0
- package/web-spatial/views/SpatialWebViewUI.swift +193 -0
- package/web-spatial/views/VolumetricWindowContainerView.swift +38 -0
- package/web-spatial/views/ui/NavView.swift +125 -0
- package/web-spatial/web_spatialApp.swift +158 -0
- package/web-spatial.xcodeproj/project.pbxproj +686 -0
- package/web-spatial.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/web-spatial.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/web-spatial.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +5 -0
- package/web-spatial.xcodeproj/project.xcworkspace/xcuserdata/bytedance.xcuserdatad/WorkspaceSettings.xcsettings +14 -0
- package/web-spatial.xcodeproj/xcshareddata/xcschemes/web-spatial.xcscheme +115 -0
- package/web-spatialTests/web_spatialTests.swift +34 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Logger.swift
|
|
3
|
+
// web-spatial
|
|
4
|
+
//
|
|
5
|
+
// Created by ByteDance on 7/18/24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
class Logger {
|
|
11
|
+
static func getLogger() -> Logger {
|
|
12
|
+
return Logger()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static func initLogger() {}
|
|
16
|
+
|
|
17
|
+
func error(_ str: String) {
|
|
18
|
+
print("error: " + str)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func verbose(_ str: String) {
|
|
22
|
+
print("verbose: " + str)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func debug(_ str: String) {
|
|
26
|
+
print("debug: " + str)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func info(_ str: String) {
|
|
30
|
+
print("info: " + str)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func warning(_ str: String) {
|
|
34
|
+
print("warning: " + str)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SceneManager.swift
|
|
3
|
+
// web-spatial
|
|
4
|
+
//
|
|
5
|
+
// Created by ByteDance on 2025/2/6.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
class SceneManager {
|
|
11
|
+
static let Instance = SceneManager()
|
|
12
|
+
|
|
13
|
+
private init() {}
|
|
14
|
+
|
|
15
|
+
// create scene
|
|
16
|
+
// if config is provided, it show immediately
|
|
17
|
+
// else it won't show until showRoot is called
|
|
18
|
+
func createRoot(target: SpatialWindowComponent, windowID: String, config: WindowContainerOptions? = nil) {
|
|
19
|
+
let windowContainerID = UUID().uuidString
|
|
20
|
+
// open window
|
|
21
|
+
let wgd = WindowContainerData(
|
|
22
|
+
windowStyle: "Plain",
|
|
23
|
+
windowContainerID: windowContainerID
|
|
24
|
+
)
|
|
25
|
+
let ent = SpatialEntity()
|
|
26
|
+
ent.coordinateSpace = CoordinateSpaceMode.ROOT
|
|
27
|
+
let windowComponent = SpatialWindowComponent(
|
|
28
|
+
parentWindowContainerID: windowContainerID
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
if let spawnedWebView = target.spawnedNativeWebviews.removeValue(forKey: windowID) {
|
|
32
|
+
windowComponent.getView()!.destroy()
|
|
33
|
+
windowComponent.setView(wv: spawnedWebView)
|
|
34
|
+
windowComponent.getView()!.webViewHolder.webViewCoordinator!.webViewRef = windowComponent
|
|
35
|
+
// focusRoot need the windowContainerID
|
|
36
|
+
windowComponent.evaluateJS(js: "window._webSpatialGroupID='\(windowContainerID)';")
|
|
37
|
+
// tell new webview parentWindowContainerID to open loadingview
|
|
38
|
+
windowComponent.evaluateJS(js: "window._webSpatialParentGroupID='\(target.parentWindowContainerID)';")
|
|
39
|
+
|
|
40
|
+
if config != nil {
|
|
41
|
+
// signal off hook
|
|
42
|
+
windowComponent.evaluateJS(js: "window._SceneHookOff=true;")
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
logger.warning("Unable to find spawned webview")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
ent.addComponent(windowComponent)
|
|
49
|
+
|
|
50
|
+
let wg = SpatialWindowContainer.getOrCreateSpatialWindowContainer(windowContainerID, wgd)
|
|
51
|
+
ent.setParentWindowContainer(wg: wg)
|
|
52
|
+
|
|
53
|
+
if let config = config {
|
|
54
|
+
showRoot(
|
|
55
|
+
target: windowComponent,
|
|
56
|
+
config: config,
|
|
57
|
+
parentWindowContainerID: target.parentWindowContainerID
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// set defaultvalues for the scene and show it
|
|
63
|
+
func showRoot(target: SpatialWindowComponent, config: WindowContainerOptions, parentWindowContainerID: String) {
|
|
64
|
+
let plainDV = WindowContainerPlainDefaultValues(
|
|
65
|
+
config
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if let pwg = SpatialWindowContainer.getSpatialWindowContainer(parentWindowContainerID),
|
|
69
|
+
let wg = SpatialWindowContainer.getSpatialWindowContainer(
|
|
70
|
+
target.parentWindowContainerID
|
|
71
|
+
)
|
|
72
|
+
{
|
|
73
|
+
WindowContainerMgr.Instance
|
|
74
|
+
.updateWindowContainerPlainDefaultValues(
|
|
75
|
+
plainDV
|
|
76
|
+
) // set default values
|
|
77
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
78
|
+
pwg.openWindowData.send(wg.wgd) // openwindow
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// bring the scene to focus
|
|
84
|
+
func focusRoot(target: SpatialWindowComponent, windowContainerID: String) {
|
|
85
|
+
if let wg = SpatialWindowContainer.getSpatialWindowContainer(windowContainerID) {
|
|
86
|
+
wg.openWindowData.send(wg.wgd)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// show LodingView when window.xrCurrentSceneDefaults is executing
|
|
91
|
+
func setLoading(_ method: LoadingMethod, windowContainerID: String) {
|
|
92
|
+
// trigger open loading view by parent windowContainer due to current windowContainer isn't visible yet
|
|
93
|
+
if let wg = SpatialWindowContainer.getSpatialWindowContainer(windowContainerID) {
|
|
94
|
+
let lwgdata = LoadingWindowContainerData(
|
|
95
|
+
method: method,
|
|
96
|
+
windowStyle: nil
|
|
97
|
+
)
|
|
98
|
+
wg.setLoadingWindowData.send(lwgdata)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// dismiss the scene content when webview closed
|
|
103
|
+
func closeRoot(_ target: SpatialWindowComponent) {
|
|
104
|
+
if let wg = SpatialWindowContainer.getSpatialWindowContainer(target.parentWindowContainerID) {
|
|
105
|
+
wg.closeWindowData.send(wg.wgd)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
//
|
|
2
|
+
// WindowContainerMgr.swift
|
|
3
|
+
// web-spatial
|
|
4
|
+
//
|
|
5
|
+
// Created by ByteDance on 2024/12/13.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
//
|
|
9
|
+
// WindowContainerModel.swift
|
|
10
|
+
// web-spatial
|
|
11
|
+
//
|
|
12
|
+
// Created by ByteDance on 2024/11/25.
|
|
13
|
+
//
|
|
14
|
+
|
|
15
|
+
import Combine
|
|
16
|
+
import SwiftUI
|
|
17
|
+
import UIKit
|
|
18
|
+
|
|
19
|
+
// TODO: maybe get input from pwa manifest
|
|
20
|
+
let defaultWindowContainerConfig = WindowContainerOptions(
|
|
21
|
+
defaultSize: WindowContainerOptions.Size(
|
|
22
|
+
width: DefaultPlainWindowContainerSize.width,
|
|
23
|
+
height: DefaultPlainWindowContainerSize.height
|
|
24
|
+
),
|
|
25
|
+
resizability: nil
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
struct WindowContainerData: Decodable, Hashable, Encodable {
|
|
29
|
+
let windowStyle: String
|
|
30
|
+
let windowContainerID: String
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
enum LoadingMethod: String, Decodable, Encodable, Hashable {
|
|
34
|
+
case show
|
|
35
|
+
case hide
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
struct LoadingWindowContainerData: Decodable, Hashable, Encodable {
|
|
39
|
+
let method: LoadingMethod
|
|
40
|
+
let windowStyle: String?
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
struct WindowContainerPlainDefaultValues {
|
|
44
|
+
var defaultSize: CGSize?
|
|
45
|
+
var windowResizability: WindowResizability?
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// support WindowContainerOptions => WindowContainerPlainDefaultValues
|
|
49
|
+
extension WindowContainerPlainDefaultValues {
|
|
50
|
+
init(_ options: WindowContainerOptions) {
|
|
51
|
+
defaultSize = CGSize(
|
|
52
|
+
width: options.defaultSize?.width ?? DefaultPlainWindowContainerSize.width,
|
|
53
|
+
height: options.defaultSize?.height ?? DefaultPlainWindowContainerSize.height
|
|
54
|
+
)
|
|
55
|
+
windowResizability = getWindowResizability(options.resizability)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// incomming JSB data
|
|
60
|
+
struct WindowContainerOptions: Codable {
|
|
61
|
+
// windowContainer
|
|
62
|
+
let defaultSize: Size?
|
|
63
|
+
let resizability: String?
|
|
64
|
+
struct Size: Codable {
|
|
65
|
+
var width: Double
|
|
66
|
+
var height: Double
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func getWindowResizability(_ windowResizability: String?) -> WindowResizability {
|
|
71
|
+
switch windowResizability {
|
|
72
|
+
case "automatic":
|
|
73
|
+
return .automatic
|
|
74
|
+
case "contentSize":
|
|
75
|
+
return .contentSize
|
|
76
|
+
case "contentMinSize":
|
|
77
|
+
return .contentMinSize
|
|
78
|
+
default:
|
|
79
|
+
return .automatic
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@Observable
|
|
84
|
+
class WindowContainerMgr: ObservableObject {
|
|
85
|
+
static let Instance = WindowContainerMgr()
|
|
86
|
+
|
|
87
|
+
// cache for dynamic loading scene reopen
|
|
88
|
+
var memorizedMainSceneConfig: WindowContainerPlainDefaultValues? = nil
|
|
89
|
+
|
|
90
|
+
private init() {
|
|
91
|
+
setToMainSceneCfg()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private var wgSetting: WindowContainerPlainDefaultValues = .init(
|
|
95
|
+
defaultSize: CGSize(width: 1080, height: 720),
|
|
96
|
+
windowResizability: .automatic
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
func getValue() -> WindowContainerPlainDefaultValues {
|
|
100
|
+
return wgSetting
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
func setToMainSceneCfg() {
|
|
104
|
+
if let cfg = memorizedMainSceneConfig != nil ? memorizedMainSceneConfig : WindowContainerPlainDefaultValues(pwaManager.mainScene) {
|
|
105
|
+
updateWindowContainerPlainDefaultValues(cfg)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
func updateWindowContainerPlainDefaultValues(_ data: WindowContainerPlainDefaultValues) {
|
|
110
|
+
if let newSize = data.defaultSize {
|
|
111
|
+
wgSetting.defaultSize = newSize
|
|
112
|
+
}
|
|
113
|
+
if let newResizability = data.windowResizability {
|
|
114
|
+
wgSetting.windowResizability = newResizability
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//
|
|
2
|
+
// JsonParser.swift
|
|
3
|
+
// web-spatial
|
|
4
|
+
//
|
|
5
|
+
// Created by ByteDance on 5/9/24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
class JsonParser {
|
|
11
|
+
var json: [String: AnyObject]?
|
|
12
|
+
init(str: String?) {
|
|
13
|
+
if let toParse = str {
|
|
14
|
+
if let data = toParse.data(using: .utf8) {
|
|
15
|
+
do {
|
|
16
|
+
json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: AnyObject]
|
|
17
|
+
} catch {}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
func getValue<T>(lookup: [String]) -> T? {
|
|
23
|
+
if var anyObj = json as? AnyObject {
|
|
24
|
+
for (index, str) in lookup.enumerated() {
|
|
25
|
+
if index == lookup.count - 1 {
|
|
26
|
+
return anyObj[str] as? T
|
|
27
|
+
}
|
|
28
|
+
if let o = (anyObj as? [String: AnyObject]),
|
|
29
|
+
let x = o[str]
|
|
30
|
+
{
|
|
31
|
+
anyObj = x
|
|
32
|
+
} else {
|
|
33
|
+
return nil
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return nil
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Convert the instance to a JSON string
|
|
41
|
+
static func serialize<T: Encodable>(_ data: T) -> String? {
|
|
42
|
+
let encoder = JSONEncoder()
|
|
43
|
+
encoder.outputFormatting = .prettyPrinted // Makes the JSON output more readable
|
|
44
|
+
do {
|
|
45
|
+
let jsonData = try encoder.encode(data)
|
|
46
|
+
return String(data: jsonData, encoding: .utf8) // Convert Data to String
|
|
47
|
+
} catch {
|
|
48
|
+
logger.error("Failed to encode WindowContainerOptions to JSON: \(error)")
|
|
49
|
+
return nil
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Window.swift
|
|
3
|
+
// web-spatial
|
|
4
|
+
//
|
|
5
|
+
// Created by ByteDance on 7/3/24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import SwiftUI
|
|
10
|
+
|
|
11
|
+
// Access window (https://stackoverflow.com/questions/60359808/how-to-access-own-window-within-swiftui-view/60359809#60359809)
|
|
12
|
+
class SceneDelegate: NSObject, ObservableObject, UIWindowSceneDelegate {
|
|
13
|
+
var window: UIWindow? // << contract of `UIWindowSceneDelegate`
|
|
14
|
+
|
|
15
|
+
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
|
16
|
+
guard let windowScene = scene as? UIWindowScene else { return }
|
|
17
|
+
window = windowScene.keyWindow // << store !!!
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// do memory cleanup after scene removed, otherwise windowContainer cannot destroy content after being dismissed
|
|
21
|
+
func sceneDidDisconnect(_ scene: UIScene) {
|
|
22
|
+
window = nil
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class AppDelegate: NSObject, UIApplicationDelegate {
|
|
27
|
+
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
|
28
|
+
let configuration = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
|
|
29
|
+
if connectingSceneSession.role == .windowApplication {
|
|
30
|
+
configuration.delegateClass = SceneDelegate.self
|
|
31
|
+
}
|
|
32
|
+
return configuration
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//
|
|
2
|
+
// UpdateSystem.swift
|
|
3
|
+
// web-spatial
|
|
4
|
+
//
|
|
5
|
+
// Created by ByteDance on 5/21/24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import RealityKit
|
|
10
|
+
|
|
11
|
+
struct UpdateWebViewComponent: Component {
|
|
12
|
+
var webView: SpatialWindowComponent?
|
|
13
|
+
init() {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class UpdateWebViewSystem: System {
|
|
17
|
+
static let query = EntityQuery(where: .has(UpdateWebViewComponent.self))
|
|
18
|
+
required init(scene: RealityKit.Scene) {
|
|
19
|
+
// Perform required initialization or setup.
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
var pos = 0.0
|
|
23
|
+
func update(context: SceneUpdateContext) {
|
|
24
|
+
for entity in context.entities(matching: Self.query, updatingSystemWhen: .rendering) {
|
|
25
|
+
pos += context.deltaTime
|
|
26
|
+
|
|
27
|
+
var x = Transform()
|
|
28
|
+
x.translation.x = Float(sin(pos)) * 0.3
|
|
29
|
+
x.translation.z = 0.2
|
|
30
|
+
entity.move(to: x, relativeTo: nil)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|