public async Task <GameObject> NewViewFromSchema(JsonSchema schema, JsonSchemaToView generator) { AssertV2.IsNotNull(schema, "schema"); AssertV2.IsNotNull(generator, "generator"); if (schema.properties == null) { AssertV2.IsFalse(generator.schemaGenerator.schemas.IsNullOrEmpty(), "generator.schema dict is emtpy!"); if (generator.schemaGenerator.schemas.TryGetValue(schema.modelType, out JsonSchema vm)) { schema = vm; } else { Log.e($"No Schema found for schema.modelType={schema.modelType}"); } } AssertV2.IsNotNull(schema.properties, "schema.properties"); GameObject rootContainerView = await generator.NewRootContainerView(rootPrefabName); rootContainerView.GetComponentInChildren <FieldView>().field = schema; var innerContainer = await generator.SelectInnerViewContainerFromObjectFieldView(rootContainerView); await generator.ObjectJsonSchemaToView(schema, innerContainer); return(rootContainerView); }
private static void AddToSchemaDictionary(JsonSchemaToView self, ObjectFieldView objectFieldView) { if (objectFieldView == null) { Log.w("Passed fieldView was null, will skip AddToSchemaDictionary process"); return; } RestorePropertiesFromChildrenGOs(objectFieldView); JsonSchema schema = objectFieldView.field; if (schema.modelType.IsNullOrEmpty()) { Log.w("Missing schema.modelType in passsed ObjectFieldView.field", objectFieldView.gameObject); return; } if (!schema.properties.IsNullOrEmpty()) { // After the fieldView properties are reconstructed correctly again fill the schemaGenerator fieldView map to have a central lookup location if (!self.schemaGenerator.schemas.ContainsKey(schema.modelType)) { self.schemaGenerator.schemas.Add(schema.modelType, schema); } } else { Log.d($"Will skip {schema.title} since it seems to be a partly unresolved type"); } }
/// <summary> fills the schema dictionary of the generator with the schemas found in the target view </summary> private static void SetupSchemaDictionary(this JsonSchemaToView self, GameObject targetView) { AddToSchemaDictionary(self, targetView.GetComponent <ObjectFieldView>()); foreach (var fieldView in targetView.GetComponentsInChildren <ObjectFieldView>(includeInactive: true)) { AddToSchemaDictionary(self, fieldView); } }
private static async Task <FieldView> CreateChildEntryView( ListFieldView self, JObject root, JsonSchemaToView viewGenerator, JToken modelEntry, string fieldName) { JsonSchema newEntryVm = GetMatchingSchema(modelEntry, self.field.items); GameObject childView = await AddChildEntryView(self, viewGenerator, fieldName, newEntryVm); await childView.LinkToJsonModel(root, viewGenerator); return(childView.GetComponentInChildren <FieldView>()); }
public static void ShowChildModelInNewScreen(this RecursiveFieldView self, JsonSchemaToView viewGenerator, GameObject currentScreen, JObject jObj) { self.openButton.SetOnClickAction(async delegate { var newScreen = await self.NewViewFromSchema(viewGenerator); var viewStack = currentScreen.GetViewStack(); viewStack.ShowView(newScreen, currentScreen); var presenter = new JsonSchemaPresenter(viewGenerator); presenter.targetView = newScreen; await presenter.LoadModelIntoView(jObj); }).LogOnError(); }
/// <summary> Can be used to generate a view directly from a model, if the json schema does not have to be customized, e.g. /// because the model uses Annotations this is the easiest way to generate a fully usable UI from any class </summary> /// true so that the used prefabs in the view are still linked correctly. </param> /// <param name="modelType"> The type of the model </param> /// <param name="keepReferenceToEditorPrefab"> If the view is generated during editor time this should be set to /// <returns> The generated view which can be used to load a model instance into it </returns> public static async Task <GameObject> GenerateViewFrom(this JsonSchemaToView self, Type modelType, bool keepReferenceToEditorPrefab = false) { var timing = Log.MethodEnteredWith(modelType); JsonSchema schema = self.schemaGenerator.ToJsonSchema(modelType.Name, modelType); self.keepReferenceToEditorPrefab = keepReferenceToEditorPrefab; var view = await self.ToView(schema); view.name = schema.title; Log.MethodDone(timing); return(view); }
private static async Task <GameObject> AddChildEntryView( ListFieldView self, JsonSchemaToView viewGenerator, string fieldName, JsonSchema entryVm) { var parentView = self.mainLink.gameObject; if (CanBeShownInListViewEntry(entryVm.GetJTokenType())) { GameObject childGo = await viewGenerator.AddChild(parentView, await viewGenerator.NewListViewEntry()); await viewGenerator.InitChild(childGo, fieldName, entryVm); return(childGo); } else { return(await viewGenerator.AddViewForJsonSchemaField(parentView, entryVm, fieldName)); } }
private static void SetupButtons(ListFieldView listView, JObject root, JsonSchemaToView viewGenerator, JArray modelArray, Dictionary <FieldView, JToken> map) { listView.add.SetOnClickAction(async delegate { JToken entry = listView.field.items.First().NewDefaultJInstance(); modelArray.Add(entry); var fieldName = "" + (modelArray.Count - 1); var fv = await CreateChildEntryView(listView, root, viewGenerator, entry, fieldName); map.Add(fv, entry); }); listView.up.SetOnClickAction(delegate { foreach (var v in GetSelectedViews(listView)) { var selectedData = map[v]; var index = modelArray.IndexOf(selectedData); if (index > 0) { modelArray.RemoveAt(index); modelArray.Insert(index - 1, selectedData); v.transform.SetSiblingIndex(v.transform.GetSiblingIndex() - 1); } } }); listView.down.SetOnClickAction(delegate { foreach (var v in GetSelectedViews(listView).Reverse()) { var selectedData = map[v]; var index = modelArray.IndexOf(selectedData); if (index < modelArray.Count - 1) { modelArray.RemoveAt(index); modelArray.Insert(index + 1, selectedData); v.transform.SetSiblingIndex(v.transform.GetSiblingIndex() + 1); } } }); listView.delete.SetOnClickAction(delegate { foreach (var v in GetSelectedViews(listView)) { var selectedData = map[v]; modelArray.Remove(selectedData); v.gameObject.Destroy(); } }); }
/// <summary> Can be used to generate a view directly from a model, if the json schema does not have to be customized, e.g. /// because the model uses Annotations this is the easiest way to generate a fully usable UI from any class </summary> /// <typeparam name="T"> The type of the model </typeparam> /// <param name="keepReferenceToEditorPrefab"> If the view is generated during editor time this should be set to /// true so that the used prefabs in the view are still linked correctly. </param> /// <returns> The generated view which can be used to load a model instance into it </returns> public static async Task <GameObject> GenerateViewFrom <T>(this JsonSchemaToView self, bool keepReferenceToEditorPrefab = false) { return(await self.GenerateViewFrom(typeof(T), keepReferenceToEditorPrefab)); }
public static async Task LinkToJsonModel(this GameObject targetView, JObject root, JsonSchemaToView viewGenerator) { viewGenerator.SetupSchemaDictionary(targetView); foreach (var fieldView in targetView.GetFieldViewMap().Values) { var value = fieldView.GetFieldJModel(root); if (!fieldView.LinkToJsonModel(root, value)) { if (fieldView is RecursiveFieldView r) { r.ShowChildModelInNewScreen(viewGenerator, targetView, value as JObject); } else if (fieldView is ObjectFieldView) { // Do nothing (object fields are individually set up themselves) } else if (fieldView is ListFieldView l) { await l.LoadModelList(root, viewGenerator); } else { Log.e($"Did not link {fieldView.GetType()}: {fieldView.fullPath}"); } } } }
public static async Task LoadModelList(this ListFieldView self, JObject root, JsonSchemaToView viewGenerator) { JArray modelArray = self.GetFieldJModel(root) as JArray; AssertV2.IsNotNull(modelArray, "modelArray"); var map = new Dictionary <FieldView, JToken>(); for (int i = 0; i < modelArray.Count; i++) { var fieldName = "" + i; JToken entry = modelArray[i]; var fv = await CreateChildEntryView(self, root, viewGenerator, entry, fieldName); map.Add(fv, entry); } SetupButtons(self, root, viewGenerator, modelArray, map); }
public static async Task LogAnyDiffToNewGeneratedUi(this Dictionary <string, FieldView> self, Type modelType, JsonSchemaToView generator, bool forceAlwaysDelete) { GameObject generatedUi = await generator.GenerateViewFrom(modelType, keepReferenceToEditorPrefab : true); generatedUi.name = "Delete me"; if (!LogAnyDiffToNewFieldViews(self, generatedUi.GetFieldViewMap()) || forceAlwaysDelete) { generatedUi.Destroy(); // If there are no additions in the new UI it can be destroyed right away again after logging is done } }
public static async Task LogAnyDiffToNewGeneratedUi <T>(this Dictionary <string, FieldView> self, JsonSchemaToView generator, bool forceAlwaysDelete) { await LogAnyDiffToNewGeneratedUi(self, typeof(T), generator, forceAlwaysDelete); }
public async Task <GameObject> NewViewFromSchema(JsonSchemaToView generator) { return(await NewViewFromSchema(field, generator)); }
public JsonSchemaPresenter(JsonSchemaToView viewGenerator) { this.viewGenerator = viewGenerator; }