@@ -26,6 +26,7 @@
|
|
26
26
|
// console.log("Update vite defines -------------------------------------------");
|
27
27
|
if (!viteConfig.define) viteConfig.define = {};
|
28
28
|
const version = tryGetNeedleEngineVersion();
|
29
|
+
console.log("Needle Engine Version:", version, needleEngineConfig?.generator);
|
29
30
|
if (version)
|
30
31
|
viteConfig.define.NEEDLE_ENGINE_VERSION = "\"" + version + "\"";
|
31
32
|
if (needleEngineConfig)
|
@@ -8,5 +8,14 @@
|
|
8
8
|
const version = json.version;
|
9
9
|
return version;
|
10
10
|
}
|
11
|
+
// check if we're in the needle engine package directory (for a release)
|
12
|
+
const packageJsonPath = process.cwd() + "/package.json";
|
13
|
+
if (existsSync(packageJsonPath)) {
|
14
|
+
const json = JSON.parse(readFileSync(packageJsonPath));
|
15
|
+
if (json.name === "@needle-tools/engine") {
|
16
|
+
const version = json.version;
|
17
|
+
return version;
|
18
|
+
}
|
19
|
+
}
|
11
20
|
return null;
|
12
21
|
}
|
@@ -880,8 +880,8 @@
|
|
880
880
|
}
|
881
881
|
|
882
882
|
const loader = getLoader();
|
883
|
-
|
884
|
-
|
883
|
+
// this hash should be constant since it is used to initialize the UIDProvider per initially loaded scene
|
884
|
+
const loadingHash = 0;
|
885
885
|
for (let i = 0; i < files.length; i++) {
|
886
886
|
// abort loading if the create id has changed
|
887
887
|
if (createId !== this._createId) {
|
@@ -889,7 +889,6 @@
|
|
889
889
|
break;
|
890
890
|
}
|
891
891
|
const file = files[i];
|
892
|
-
|
893
892
|
if (!file.includes(".glb") && !file.includes(".gltf")) {
|
894
893
|
const warning = `Needle Engine: found suspicious src "${file}"`;
|
895
894
|
console.warn(warning);
|
@@ -897,6 +896,7 @@
|
|
897
896
|
}
|
898
897
|
|
899
898
|
args?.onLoadingStart?.call(this, i, file);
|
899
|
+
if(debug) console.log("Context Load " + file);
|
900
900
|
const res = await loader.loadSync(this, file, file, loadingHash, prog => {
|
901
901
|
progressArg.name = file;
|
902
902
|
progressArg.progress = prog;
|
@@ -203,6 +203,7 @@
|
|
203
203
|
this._loadingElement.style.flexDirection = "column";
|
204
204
|
this._loadingElement.style.pointerEvents = "none";
|
205
205
|
this._loadingElement.style.color = "white";
|
206
|
+
this._loadingElement.style.fontFamily = "Roboto, sans-serif, Arial";
|
206
207
|
if (loadingStyle === "light")
|
207
208
|
this._loadingElement.style.color = "rgba(0,0,0,.8)";
|
208
209
|
else
|
@@ -300,7 +301,6 @@
|
|
300
301
|
messageContainer.style.fontSize = ".8em";
|
301
302
|
messageContainer.style.paddingTop = ".5em";
|
302
303
|
messageContainer.style.fontWeight = "200";
|
303
|
-
messageContainer.style.fontFamily = "Roboto, sans-serif, Arial";
|
304
304
|
// messageContainer.style.border = "1px solid rgba(255,255,255,.1)";
|
305
305
|
messageContainer.style.justifyContent = "center";
|
306
306
|
this._loadingElement.appendChild(messageContainer);
|
@@ -171,12 +171,15 @@
|
|
171
171
|
|
172
172
|
if (!this.getAttribute("src")) {
|
173
173
|
const global = globalThis["needle:codegen_files"] as unknown as string;
|
174
|
+
if(debug) console.log("src is null, trying to load from globalThis[\"needle:codegen_files\"]", global);
|
174
175
|
if (global) {
|
175
176
|
if (debug) console.log("globalThis[\"needle:codegen_files\"]", global);
|
176
177
|
this.setAttribute("src", global);
|
177
178
|
}
|
178
179
|
}
|
179
180
|
|
181
|
+
if(debug) console.log("src", this.getAttribute("src"));
|
182
|
+
|
180
183
|
// we have to wait because codegen does set the src attribute when it's loaded
|
181
184
|
// which might happen after the element is connected
|
182
185
|
// if the `src` is then still null we want to initialize the default scene
|
@@ -114,6 +114,16 @@
|
|
114
114
|
resolveGuids: (guidsMap: GuidsMap) => void;
|
115
115
|
}
|
116
116
|
|
117
|
+
const originalComponentNameKey = Symbol("original-component-name");
|
118
|
+
|
119
|
+
/**
|
120
|
+
* We want to create one id provider per component
|
121
|
+
* If a component is used multiple times we want to create a new id provider for each instance
|
122
|
+
* That way the order of components in the scene doesnt affect the result GUID
|
123
|
+
*/
|
124
|
+
// TODO: clear this when re-loading the context
|
125
|
+
const componentIdProviderCache = new Map<string, InstantiateIdProvider>();
|
126
|
+
|
117
127
|
function recursiveCreateGuids(obj: IGameObject, idProvider: UIDProvider | null, guidsMap: GuidsMap, resolveGuids: IHasResolveGuids[]) {
|
118
128
|
if (idProvider === null) return;
|
119
129
|
if (!obj) return;
|
@@ -125,8 +135,21 @@
|
|
125
135
|
if (obj && obj.userData && obj.userData.components) {
|
126
136
|
for (const comp of obj.userData.components) {
|
127
137
|
if (comp === null) continue;
|
138
|
+
|
139
|
+
// by default we use the component guid as a key - order of the components in the scene doesnt matter with this approach
|
140
|
+
// this is to prevent cases where multiple GLBs are loaded with the same component guid
|
141
|
+
const idProviderKey = comp.guid;
|
142
|
+
if (idProviderKey) {
|
143
|
+
if (!componentIdProviderCache.has(idProviderKey)) {
|
144
|
+
if (debug) console.log("Creating InstanceIdProvider with key \"" + idProviderKey + "\" for component " + comp[originalComponentNameKey]);
|
145
|
+
componentIdProviderCache.set(idProviderKey, new InstantiateIdProvider(idProviderKey));
|
146
|
+
}
|
147
|
+
}
|
148
|
+
else if(debug) console.warn("Can not create IdProvider: component " + comp[originalComponentNameKey] + " has no guid", comp.guid);
|
149
|
+
const componentIdProvider = componentIdProviderCache.get(idProviderKey) || idProvider
|
150
|
+
|
128
151
|
const prev = comp.guid;
|
129
|
-
comp.guid =
|
152
|
+
comp.guid = componentIdProvider.generateUUID();
|
130
153
|
if (prev && prev !== "invalid")
|
131
154
|
guidsMap[prev] = comp.guid;
|
132
155
|
if (comp.resolveGuids)
|
@@ -181,11 +204,14 @@
|
|
181
204
|
|
182
205
|
// assign basic fields
|
183
206
|
assign(instance, compData, context.implementationInformation);
|
184
|
-
|
207
|
+
|
185
208
|
// assign the guid of the original instance
|
186
|
-
if("guid" in compData)
|
209
|
+
if ("guid" in compData)
|
187
210
|
instance[editorGuidKeyName] = compData.guid;
|
188
|
-
|
211
|
+
|
212
|
+
// we store the original component name per component which will later be used to get or initialize the InstanceIdProvider
|
213
|
+
instance[originalComponentNameKey] = compData.name;
|
214
|
+
|
189
215
|
// Object.assign(instance, compData);
|
190
216
|
// dont call awake here because some references might not be resolved yet and components that access those fields in awake will throw
|
191
217
|
// for example Duplicatable reference to object might still be { node: id }
|
@@ -44,9 +44,7 @@
|
|
44
44
|
private _handleReceivingMethod?: Function;
|
45
45
|
|
46
46
|
get networkingKey(): string {
|
47
|
-
|
48
|
-
const key = obj.constructor.name;
|
49
|
-
return key;
|
47
|
+
return this.comp.guid;
|
50
48
|
}
|
51
49
|
|
52
50
|
/** is set to true in on receive call to avoid circular sending */
|
@@ -81,7 +79,7 @@
|
|
81
79
|
|
82
80
|
notifyChanged(propertyName: string, value: any) {
|
83
81
|
if (this._isReceiving) return;
|
84
|
-
|
82
|
+
if(debug) console.log("Property changed: " + propertyName, value);
|
85
83
|
this.hasChanges = true;
|
86
84
|
this.changedProperties[propertyName] = value;
|
87
85
|
}
|
@@ -111,6 +109,7 @@
|
|
111
109
|
}
|
112
110
|
|
113
111
|
private onHandleReceiving(val) {
|
112
|
+
if(debug) console.log("RECEIVE", this.comp.name, this.comp.guid, val);
|
114
113
|
if (!this._isInit) return;
|
115
114
|
if (!this.comp) return;
|
116
115
|
const guid = val.guid;
|
@@ -660,7 +660,8 @@
|
|
660
660
|
const model = message.data as unknown as UserJoinedOrLeftRoomModel;
|
661
661
|
const index = this._currentInRoom.indexOf(model.userId);
|
662
662
|
if (index >= 0) {
|
663
|
-
|
663
|
+
if (debugNet)
|
664
|
+
console.log(model.userId + " left", "now in room:", this._currentInRoom);
|
664
665
|
this._currentInRoom.splice(index, 1);
|
665
666
|
}
|
666
667
|
if (model.userId === this.connectionId) {
|