@@ -140,6 +140,149 @@ const char *GDScriptFunctions::get_func_name(Function p_func) {
140
140
return _names[p_func];
141
141
}
142
142
143
+ Variant GDScriptFunctions::_inst2dict (const Variant &p_arg, Variant::CallError &r_error) {
144
+ if (p_arg.get_type () == Variant::NIL) {
145
+ return Variant ();
146
+ } else if (p_arg.get_type () != Variant::OBJECT) {
147
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
148
+ r_error.argument = 0 ;
149
+ return Variant ();
150
+ } else {
151
+
152
+ Object *obj = p_arg;
153
+ if (!obj) {
154
+ return Variant ();
155
+
156
+ } else if (!obj->get_script_instance () || obj->get_script_instance ()->get_language () != GDScriptLanguage::get_singleton ()) {
157
+
158
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
159
+ r_error.argument = 0 ;
160
+ r_error.expected = Variant::DICTIONARY;
161
+ return RTR (" Not a script with an instance" );
162
+ } else {
163
+
164
+ GDScriptInstance *ins = static_cast <GDScriptInstance *>(obj->get_script_instance ());
165
+ Ref<GDScript> base = ins->get_script ();
166
+ if (base.is_null ()) {
167
+
168
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
169
+ r_error.argument = 0 ;
170
+ r_error.expected = Variant::DICTIONARY;
171
+ return RTR (" Not based on a script" );
172
+ }
173
+
174
+ GDScript *p = base.ptr ();
175
+ Vector<StringName> sname;
176
+
177
+ while (p->_owner ) {
178
+
179
+ sname.push_back (p->name );
180
+ p = p->_owner ;
181
+ }
182
+ sname.invert ();
183
+
184
+ if (!p->path .is_resource_file ()) {
185
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
186
+ r_error.argument = 0 ;
187
+ r_error.expected = Variant::DICTIONARY;
188
+ return RTR (" Not based on a resource file" );
189
+ }
190
+
191
+ NodePath cp (sname, Vector<StringName>(), false );
192
+
193
+ Dictionary d;
194
+ d[" @subpath" ] = cp;
195
+ d[" @path" ] = p->get_path ();
196
+
197
+ for (Map<StringName, GDScript::MemberInfo>::Element *E = base->member_indices .front (); E; E = E->next ()) {
198
+ if (!d.has (E->key ())) {
199
+ if (ins->members [E->get ().index ].get_type () == Variant::OBJECT) {
200
+ Variant::CallError err;
201
+ err.error = Variant::CallError::CALL_OK;
202
+ Dictionary sub_inst = _inst2dict (ins->members [E->get ().index ], err);
203
+ if (err.error == Variant::CallError::CALL_OK)
204
+ d[E->key ()] = sub_inst;
205
+ } else {
206
+ d[E->key ()] = ins->members [E->get ().index ];
207
+ }
208
+ }
209
+ }
210
+ return d;
211
+ }
212
+ }
213
+ }
214
+
215
+ Variant GDScriptFunctions::_dict2inst (const Dictionary &dict, Variant::CallError &r_error) {
216
+
217
+ if (!dict.has (" @path" )) {
218
+
219
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
220
+ r_error.argument = 0 ;
221
+ r_error.expected = Variant::OBJECT;
222
+ return RTR (" Invalid instance dictionary format (missing @path)" );
223
+ }
224
+
225
+ Ref<Script> scr = ResourceLoader::load (dict[" @path" ]);
226
+ if (!scr.is_valid ()) {
227
+
228
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
229
+ r_error.argument = 0 ;
230
+ r_error.expected = Variant::OBJECT;
231
+ return RTR (" Invalid instance dictionary format (can't load script at @path)" );
232
+ }
233
+
234
+ Ref<GDScript> gdscr = scr;
235
+
236
+ if (!gdscr.is_valid ()) {
237
+
238
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
239
+ r_error.argument = 0 ;
240
+ r_error.expected = Variant::OBJECT;
241
+ return RTR (" Invalid instance dictionary format (invalid script at @path)" );
242
+ }
243
+
244
+ NodePath sub;
245
+ if (dict.has (" @subpath" )) {
246
+ sub = dict[" @subpath" ];
247
+ }
248
+
249
+ for (int i = 0 ; i < sub.get_name_count (); i++) {
250
+
251
+ gdscr = gdscr->subclasses [sub.get_name (i)];
252
+ if (!gdscr.is_valid ()) {
253
+
254
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
255
+ r_error.argument = 0 ;
256
+ r_error.expected = Variant::OBJECT;
257
+ return RTR (" Invalid instance dictionary (invalid subclasses)" );
258
+ }
259
+ }
260
+
261
+ Variant ret = gdscr->_new (nullptr , 0 , r_error);
262
+
263
+ GDScriptInstance *ins = static_cast <GDScriptInstance *>(static_cast <Object *>(ret)->get_script_instance ());
264
+ Ref<GDScript> gd_ref = ins->get_script ();
265
+
266
+ for (Map<StringName, GDScript::MemberInfo>::Element *E = gd_ref->member_indices .front (); E; E = E->next ()) {
267
+ if (dict.has (E->key ())) {
268
+ if (dict[E->key ()].get_type () == Variant::DICTIONARY && ins->members [E->get ().index ].get_type () != Variant::DICTIONARY) {
269
+ const Dictionary &sub_dict = static_cast <const Dictionary>(dict[E->key ()]);
270
+ Variant::CallError err;
271
+ err.error = Variant::CallError::CALL_OK;
272
+ Variant sub_inst = _dict2inst (sub_dict, err);
273
+ if (err.error == Variant::CallError::CALL_OK)
274
+ ins->members .write [E->get ().index ] = sub_inst;
275
+ else
276
+ ins->members .write [E->get ().index ] = dict[E->key ()];
277
+ } else {
278
+ ins->members .write [E->get ().index ] = dict[E->key ()];
279
+ }
280
+ }
281
+ }
282
+
283
+ return ret;
284
+ }
285
+
143
286
void GDScriptFunctions::call (Function p_func, const Variant **p_args, int p_arg_count, Variant &r_ret, Variant::CallError &r_error) {
144
287
145
288
r_error.error = Variant::CallError::CALL_OK;
@@ -1069,73 +1212,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
1069
1212
1070
1213
VALIDATE_ARG_COUNT (1 );
1071
1214
1072
- if (p_args[0 ]->get_type () == Variant::NIL) {
1073
- r_ret = Variant ();
1074
- } else if (p_args[0 ]->get_type () != Variant::OBJECT) {
1075
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1076
- r_error.argument = 0 ;
1077
- r_ret = Variant ();
1078
- } else {
1079
-
1080
- Object *obj = *p_args[0 ];
1081
- if (!obj) {
1082
- r_ret = Variant ();
1083
-
1084
- } else if (!obj->get_script_instance () || obj->get_script_instance ()->get_language () != GDScriptLanguage::get_singleton ()) {
1085
-
1086
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1087
- r_error.argument = 0 ;
1088
- r_error.expected = Variant::DICTIONARY;
1089
- r_ret = RTR (" Not a script with an instance" );
1090
- return ;
1091
- } else {
1092
-
1093
- GDScriptInstance *ins = static_cast <GDScriptInstance *>(obj->get_script_instance ());
1094
- Ref<GDScript> base = ins->get_script ();
1095
- if (base.is_null ()) {
1096
-
1097
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1098
- r_error.argument = 0 ;
1099
- r_error.expected = Variant::DICTIONARY;
1100
- r_ret = RTR (" Not based on a script" );
1101
- return ;
1102
- }
1103
-
1104
- GDScript *p = base.ptr ();
1105
- Vector<StringName> sname;
1106
-
1107
- while (p->_owner ) {
1108
-
1109
- sname.push_back (p->name );
1110
- p = p->_owner ;
1111
- }
1112
- sname.invert ();
1113
-
1114
- if (!p->path .is_resource_file ()) {
1115
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1116
- r_error.argument = 0 ;
1117
- r_error.expected = Variant::DICTIONARY;
1118
- r_ret = Variant ();
1119
-
1120
- r_ret = RTR (" Not based on a resource file" );
1121
-
1122
- return ;
1123
- }
1124
-
1125
- NodePath cp (sname, Vector<StringName>(), false );
1126
-
1127
- Dictionary d;
1128
- d[" @subpath" ] = cp;
1129
- d[" @path" ] = p->get_path ();
1130
-
1131
- for (Map<StringName, GDScript::MemberInfo>::Element *E = base->member_indices .front (); E; E = E->next ()) {
1132
- if (!d.has (E->key ())) {
1133
- d[E->key ()] = ins->members [E->get ().index ];
1134
- }
1135
- }
1136
- r_ret = d;
1137
- }
1138
- }
1215
+ r_ret = _inst2dict (*p_args[0 ], r_error);
1139
1216
1140
1217
} break ;
1141
1218
case DICT2INST: {
@@ -1152,69 +1229,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
1152
1229
return ;
1153
1230
}
1154
1231
1155
- Dictionary d = *p_args[0 ];
1156
-
1157
- if (!d.has (" @path" )) {
1158
-
1159
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1160
- r_error.argument = 0 ;
1161
- r_error.expected = Variant::OBJECT;
1162
- r_ret = RTR (" Invalid instance dictionary format (missing @path)" );
1163
-
1164
- return ;
1165
- }
1166
-
1167
- Ref<Script> scr = ResourceLoader::load (d[" @path" ]);
1168
- if (!scr.is_valid ()) {
1169
-
1170
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1171
- r_error.argument = 0 ;
1172
- r_error.expected = Variant::OBJECT;
1173
- r_ret = RTR (" Invalid instance dictionary format (can't load script at @path)" );
1174
- return ;
1175
- }
1176
-
1177
- Ref<GDScript> gdscr = scr;
1178
-
1179
- if (!gdscr.is_valid ()) {
1180
-
1181
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1182
- r_error.argument = 0 ;
1183
- r_error.expected = Variant::OBJECT;
1184
- r_ret = Variant ();
1185
- r_ret = RTR (" Invalid instance dictionary format (invalid script at @path)" );
1186
- return ;
1187
- }
1188
-
1189
- NodePath sub;
1190
- if (d.has (" @subpath" )) {
1191
- sub = d[" @subpath" ];
1192
- }
1193
-
1194
- for (int i = 0 ; i < sub.get_name_count (); i++) {
1195
-
1196
- gdscr = gdscr->subclasses [sub.get_name (i)];
1197
- if (!gdscr.is_valid ()) {
1198
-
1199
- r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
1200
- r_error.argument = 0 ;
1201
- r_error.expected = Variant::OBJECT;
1202
- r_ret = Variant ();
1203
- r_ret = RTR (" Invalid instance dictionary (invalid subclasses)" );
1204
- return ;
1205
- }
1206
- }
1207
-
1208
- r_ret = gdscr->_new (NULL , 0 , r_error);
1209
-
1210
- GDScriptInstance *ins = static_cast <GDScriptInstance *>(static_cast <Object *>(r_ret)->get_script_instance ());
1211
- Ref<GDScript> gd_ref = ins->get_script ();
1212
-
1213
- for (Map<StringName, GDScript::MemberInfo>::Element *E = gd_ref->member_indices .front (); E; E = E->next ()) {
1214
- if (d.has (E->key ())) {
1215
- ins->members .write [E->get ().index ] = d[E->key ()];
1216
- }
1217
- }
1232
+ r_ret = _dict2inst (*p_args[0 ], r_error);
1218
1233
1219
1234
} break ;
1220
1235
case VALIDATE_JSON: {
0 commit comments