Preparations to implement reading Exhibits and Pois from json

This commit is contained in:
2018-09-25 18:27:20 +02:00
parent 691149dd44
commit 0985518be2
11 changed files with 370 additions and 17 deletions

View File

@@ -83,9 +83,10 @@ namespace RothenburgAR
poiXmlPreloader = new PoiXmlPreloader();
PoiData poiData = poiXmlPreloader.PreloadPoi(testDirectory);
List<PoiData> poiData = poiXmlPreloader.PreloadPoi(testDirectory);
Assert.NotNull(poiData);
Assert.AreEqual("testPoi", poiData.ID);
Assert.NotZero(poiData.Count);
Assert.AreEqual("testPoi", poiData[0].ID);
}
private void WriteTestPng(string path)

View File

@@ -33,10 +33,16 @@ namespace RothenburgAR
{
PoiDataManager.Instance.AddPoiDataSourcePath(PathHelper.POIPath);
PoiDataManager.Instance.AddPoiPreloader(new PoiXmlPreloader());
PoiDataManager.Instance.AddPoiDataSourcePath(PathHelper.ExhibitionPath);
PoiDataManager.Instance.AddPoiPreloader(new PoiJsonPreloader());
PoiDataManager.Instance.LoadEverySourcePath();
ExhibitionManager.Instance.AddExhibitionSourcePath(PathHelper.ExhibitionPath);
ExhibitionManager.Instance.AddExhibitionPreloader(new ExhibitionXmlPreloader());
ExhibitionManager.Instance.AddExhibitionPreloader(new ExhibitionJsonPreloader());
ExhibitionManager.Instance.LoadEverySourcePath(
(int maxPaths, int currentPaths, int subMaxExhibitions, int subCurrentExhibition) =>
{

View File

@@ -0,0 +1,190 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml;
using RothenburgAR.Common;
using UnityEngine;
namespace RothenburgAR.Exhibition
{
public class ExhibitionJsonPreloader : IExhibitionPreloader
{
public bool CanLoadExhibitionDirectory(string exhibitionDirectory)
{
return false;
if (!Directory.Exists(exhibitionDirectory))
return false;
string xmlFilePath = PathHelper.GetXmlPathFromDirectoryPath(exhibitionDirectory);
if (!File.Exists(xmlFilePath))
return false;
if (!File.Exists(Path.Combine(exhibitionDirectory, "tracker.xml")))
return false;
if (!File.Exists(Path.Combine(exhibitionDirectory, "tracker.dat")))
return false;
// Todo: More validations
return true;
}
public PreloadedExhibition PreloadExhibition(string exhibitionDirectory)
{
throw new System.NotImplementedException();
string xmlFilePath = PathHelper.GetXmlPathFromDirectoryPath(exhibitionDirectory);
if (!File.Exists(xmlFilePath))
throw new FileNotFoundException(xmlFilePath);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
// Read the ID from the xml
if (doc.DocumentElement == null || doc.DocumentElement.Attributes == null ||
doc.DocumentElement.Attributes["id"] == null)
throw new InvalidXMLException("Could not read doc.DocumentElement.Attributes['id] ");
string exhibitionId = doc.DocumentElement.Attributes["id"].Value;
PreloadedExhibition resultExhibition = new PreloadedExhibition
{
ContainedExhibits = new List<PreloadedExhibit>(),
ID = exhibitionId,
DatasetPath = exhibitionDirectory
};
var exhibitNodes = doc.SelectNodes("//exhibition/exhibit");
foreach (XmlNode exhibitNode in exhibitNodes)
{
if (exhibitNode.Attributes == null || exhibitNode.Attributes["id"] == null)
{
// Todo: Log error
continue;
}
var newExhibit = PreloadExhibit(exhibitionDirectory, exhibitNode);
resultExhibition.ContainedExhibits.Add(newExhibit);
}
return resultExhibition;
}
private PreloadedExhibit PreloadExhibit(string exhibitionDirectory, XmlNode exhibitNode)
{
PreloadedExhibit newExhibit = new PreloadedExhibit();
newExhibit.ID = exhibitNode.Attributes["id"].Value;
newExhibit.ReferencedPoiEntries = new List<PreloadedPoiReference>();
// Load Description Text
XmlNodeList descrList = exhibitNode.SelectNodes("description/text");
if (descrList != null && descrList.Count > 0)
{
TextElement exhibitDescr = TextElement.BuildFromXmlNode(exhibitionDirectory, descrList);
newExhibit.Description = exhibitDescr;
}
// Load Title Text
XmlNodeList titleList = exhibitNode.SelectNodes("title/text");
if (titleList != null && titleList.Count > 0)
{
TextElement exhibitTitle = TextElement.BuildFromXmlNode(exhibitionDirectory, titleList);
var fontSize = GetFloatFromXmlNode(exhibitNode.SelectSingleNode("title/font"), "size");
var boxHeight = GetFloatFromXmlNode(exhibitNode.SelectSingleNode("title/dimensions"), "height");
var boxWidth = GetFloatFromXmlNode(exhibitNode.SelectSingleNode("title/dimensions"), "width");
PreloadedExhibitTitle preTitle = new PreloadedExhibitTitle
{
Text = exhibitTitle,
Position = GetVector3FromXmlNode(exhibitNode.SelectSingleNode("title/position")),
Rotation = GetVector3FromXmlNode(exhibitNode.SelectSingleNode("title/rotation")),
FontSize = fontSize ?? 20,
BoxWidth = boxWidth ?? 200,
BoxHeight = boxHeight ?? 25
};
newExhibit.Title = preTitle;
}
// Load POI References
XmlNodeList poiRefList = exhibitNode.SelectNodes("poiList/poi");
if (poiRefList != null && poiRefList.Count > 0)
{
foreach (XmlNode poiRefEntry in poiRefList)
{
if (poiRefEntry.Attributes == null || poiRefEntry.Attributes["ref-id"] == null)
continue;
PreloadedPoiReference poiReference =
new PreloadedPoiReference
{
ReferencedId = poiRefEntry.Attributes["ref-id"].Value,
Position = GetVector3FromXmlNode(poiRefEntry.SelectSingleNode("position")),
Rotation = GetVector3FromXmlNode(poiRefEntry.SelectSingleNode("rotation")),
Scale = GetVector3FromXmlNode(poiRefEntry.SelectSingleNode("scale"))
};
newExhibit.ReferencedPoiEntries.Add(poiReference);
}
}
return newExhibit;
}
private string GetStringFromXmlNode(XmlNode node, string key)
{
if (node == null)
return null;
if (node.Attributes == null)
return null;
if (node.Attributes[key] == null)
return null;
return node.Attributes[key].Value;
}
private float? GetFloatFromXmlNode(XmlNode node, string key)
{
var str = GetStringFromXmlNode(node, key);
if (str == null)
return null;
try
{
return float.Parse(str, CultureInfo.InvariantCulture.NumberFormat);
}
catch
{
return null;
}
}
private Vector3? GetVector3FromXmlNode(XmlNode node)
{
if (node == null)
return null;
if (node.Attributes == null)
return null;
if (node.Attributes["x"] == null)
return null;
if (node.Attributes["y"] == null)
return null;
if (node.Attributes["z"] == null)
return null;
try
{
float posX = float.Parse(node.Attributes["x"].Value,
CultureInfo.InvariantCulture.NumberFormat);
float posY = float.Parse(node.Attributes["y"].Value,
CultureInfo.InvariantCulture.NumberFormat);
float posZ = float.Parse(node.Attributes["z"].Value,
CultureInfo.InvariantCulture.NumberFormat);
return new Vector3(posX, posY, posZ);
}
catch
{
// TODO: log error
return null;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 7806b799db63ba3468e962aea10b2549
timeCreated: 1537892587
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +1,10 @@
namespace RothenburgAR.PointOfInterest
using System.Collections.Generic;
namespace RothenburgAR.PointOfInterest
{
public interface IPoiPreloader
{
bool CanLoadPoiDirectory(string poiDirectory);
PoiData PreloadPoi(string poiDirectory);
List<PoiData> PreloadPoi(string poiDirectory);
}
}

View File

@@ -74,8 +74,11 @@ namespace RothenburgAR.PointOfInterest
}
try
{
var newPoi = preloader.PreloadPoi(path);
AddPoiData(newPoi);
var newPois = preloader.PreloadPoi(path);
foreach (var newPoi in newPois)
{
AddPoiData(newPoi);
}
}
catch (Exception e)
{

View File

@@ -0,0 +1,122 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml;
using RothenburgAR.Common;
using UnityEngine;
namespace RothenburgAR.PointOfInterest
{
public class PoiJsonPreloader : IPoiPreloader
{
public bool CanLoadPoiDirectory(string poiDirectory)
{
//TODO remove
return false;
if (!Directory.Exists(poiDirectory))
return false;
var languageDirs = Directory.GetDirectories(poiDirectory).ToList();
foreach (var dir in languageDirs)
{
var metaFilePath = PathHelper.CombinePaths(poiDirectory, dir, "meta.json");
if (!File.Exists(metaFilePath)) return false;
}
// Todo: More validations
return true;
}
public List<PoiData> PreloadPoi(string poiDirectory)
{
throw new System.NotImplementedException();
string xmlFilePath = PathHelper.GetXmlPathFromDirectoryPath(poiDirectory);
if (!File.Exists(xmlFilePath))
throw new FileNotFoundException(xmlFilePath);
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
// Read the ID from the xml
if (doc.DocumentElement == null || doc.DocumentElement.Attributes == null ||
doc.DocumentElement.Attributes["id"] == null)
throw new InvalidXMLException("Could not read doc.DocumentElement.Attributes['id] ");
string poiId = doc.DocumentElement.Attributes["id"].Value;
// Read the description from the xml
XmlNodeList descNodes = doc.SelectNodes("//poi/description/text");
TextElement descElement = TextElement.BuildFromXmlNode(poiDirectory, descNodes);
// Read the title from the xml
XmlNodeList titleNodes = doc.SelectNodes("//poi/title/text");
TextElement titleElement = TextElement.BuildFromXmlNode(poiDirectory, titleNodes);
PoiData poiData = new PoiData
{
ID = poiId,
Description = descElement,
Title = titleElement,
SourcePath = poiDirectory
};
// Read the model value
XmlNode modelNode = doc.SelectSingleNode("//poi/model");
if (modelNode != null)
{
var pathNode = modelNode.SelectSingleNode("path");
var scaleNode = modelNode.SelectSingleNode("scale");
var rotationNode = modelNode.SelectSingleNode("rotation");
var positionNode = modelNode.SelectSingleNode("position");
var poiModelDescription = new PoiModelDescription
{
ModelPath = Path.Combine(poiDirectory, pathNode.Attributes["value"].Value),
ModelPrefabName = pathNode.Attributes["prefabName"].Value,
Scale = GetVector3FromXmlNode(scaleNode).GetValueOrDefault(Vector3.one),
Rotation = GetVector3FromXmlNode(rotationNode).GetValueOrDefault(Vector3.zero),
Position = GetVector3FromXmlNode(positionNode).GetValueOrDefault(Vector3.zero)
};
poiData.ModelDescription = poiModelDescription;
}
return new List<PoiData> { poiData };
}
private Vector3? GetVector3FromXmlNode(XmlNode node)
{
if (node == null)
return null;
if (node.Attributes == null)
return null;
if (node.Attributes["x"] == null)
return null;
if (node.Attributes["y"] == null)
return null;
if (node.Attributes["z"] == null)
return null;
try
{
float posX = float.Parse(node.Attributes["x"].Value,
CultureInfo.InvariantCulture.NumberFormat);
float posY = float.Parse(node.Attributes["y"].Value,
CultureInfo.InvariantCulture.NumberFormat);
float posZ = float.Parse(node.Attributes["z"].Value,
CultureInfo.InvariantCulture.NumberFormat);
return new Vector3(posX, posY, posZ);
}
catch
{
// TODO: log error
return null;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 65621f7647a1d0a40870d6e20203b6b9
timeCreated: 1537892587
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,4 +1,5 @@
using System.Globalization;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml;
using RothenburgAR.Common;
@@ -23,7 +24,7 @@ namespace RothenburgAR.PointOfInterest
return true;
}
public PoiData PreloadPoi(string poiDirectory)
public List<PoiData> PreloadPoi(string poiDirectory)
{
string xmlFilePath = PathHelper.GetXmlPathFromDirectoryPath(poiDirectory);
@@ -77,7 +78,7 @@ namespace RothenburgAR.PointOfInterest
};
poiData.ModelDescription = poiModelDescription;
}
return poiData;
return new List<PoiData> { poiData };
}
private Vector3? GetVector3FromXmlNode(XmlNode node)

View File

@@ -31,9 +31,11 @@ namespace RothenburgAR.Updater
[Serializable]
public class VersioncheckAnswer
{
[JsonProperty]
public List<string> languages { get; set; }
public List<ExhibitionVersion> data { get; set; }
[JsonProperty("languages")]
public List<string> Languages { get; set; }
[JsonProperty("data")]
public List<ExhibitionVersion> Data { get; set; }
}
[Serializable]

View File

@@ -79,7 +79,7 @@ namespace RothenburgAR.Updater
var answer = VersionAnswer;
if (answer.data.TrueForAll(d => d.Meta.Status == VersionStatus.ok && d.Tracker.Status == VersionStatus.ok))
if (answer.Data.TrueForAll(d => d.Meta.Status == VersionStatus.ok && d.Tracker.Status == VersionStatus.ok))
{
// no updates required, continue to app
LoadMainScene();
@@ -159,8 +159,8 @@ namespace RothenburgAR.Updater
//TODO write languages to file the app can read (so that the languagemanager can decide which languages the user can choose from)
var updatedMeta = VersionAnswer.data.Where(d => d.Meta.Status == VersionStatus.updated).ToList();
var updatedTracker = VersionAnswer.data.Where(d => d.Tracker.Status == VersionStatus.updated).ToList();
var updatedMeta = VersionAnswer.Data.Where(d => d.Meta.Status == VersionStatus.updated).ToList();
var updatedTracker = VersionAnswer.Data.Where(d => d.Tracker.Status == VersionStatus.updated).ToList();
updatedMeta.Union(updatedTracker).ToList().ForEach(updatedExhibition =>
{
// create exhibition directories
@@ -174,7 +174,7 @@ namespace RothenburgAR.Updater
updatedMeta.ForEach(d => UpdateMeta(d));
updatedTracker.ForEach(d => UpdateTracker(d));
var deletedData = VersionAnswer.data.Where(d =>
var deletedData = VersionAnswer.Data.Where(d =>
d.Meta.Status == VersionStatus.deleted
|| d.Tracker.Status == VersionStatus.deleted).ToList();
deletedData.ForEach(d => DeleteExhibition(d));
@@ -188,7 +188,7 @@ namespace RothenburgAR.Updater
private void UpdateMeta(ExhibitionVersion exhibition)
{
foreach (var lang in VersionAnswer.languages)
foreach (var lang in VersionAnswer.Languages)
{
var path = PathHelper.CombinePaths(PathHelper.ExhibitionPath, exhibition.Id, lang);
var url = exhibition.Meta.UpdateUrl.Replace("{lang}", lang);