230 lines
8.8 KiB
C#
230 lines
8.8 KiB
C#
using Cryville.EEW.Core;
|
|
using Cryville.EEW.Core.Map;
|
|
using Cryville.EEW.CWAOpenData.Map;
|
|
using Cryville.EEW.GlobalQuake.Map;
|
|
using Cryville.EEW.JMAAtom.Map;
|
|
using Cryville.EEW.Map;
|
|
using Cryville.EEW.Models.GeoJSON;
|
|
using Cryville.EEW.NOAA.Map;
|
|
using Cryville.EEW.Report;
|
|
using Cryville.EEW.Wolfx.Map;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using UnityEngine;
|
|
using UnityMapElement = Cryville.EEW.Unity.Map.Element.MapElement;
|
|
|
|
namespace Cryville.EEW.Unity.Map {
|
|
sealed class MapElementManager : MonoBehaviour {
|
|
ReportViewModel _selected;
|
|
readonly List<UnityMapElement> _displayingElements = new();
|
|
readonly List<ReportViewModel> _displayingReports = new();
|
|
readonly List<int> _displayingOrder = new();
|
|
|
|
[SerializeField] MapElementManager m_subManager;
|
|
|
|
public RectangleF? AABB {
|
|
get {
|
|
RectangleF? ret = null;
|
|
foreach (var element in _displayingElements) {
|
|
if (element == null) continue;
|
|
if (element.AABB is not RectangleF aabb) continue;
|
|
if (ret == null) ret = aabb; // TODO dynamic
|
|
else ret = MapTileUtils.UnionTileAABBs(ret.Value, aabb);
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
public void AddOngoing(ReportViewModel e) => Add(e);
|
|
public void RemoveOngoing(ReportViewModel e) => Remove(e);
|
|
public void SetSelected(ReportViewModel e) {
|
|
if (_selected is not null)
|
|
Remove(_selected);
|
|
if (_displayingReports.Contains(e)) {
|
|
_selected = null;
|
|
}
|
|
else {
|
|
Add(e);
|
|
_selected = e;
|
|
}
|
|
}
|
|
|
|
void Add(ReportViewModel e) {
|
|
var element = Build(e.Model, out _, out int order);
|
|
if (element == null) return;
|
|
var pos = element.transform.localPosition;
|
|
pos.z = OrderToZ(_displayingOrder.Sum());
|
|
element.transform.localPosition = pos;
|
|
_displayingElements.Add(element);
|
|
_displayingReports.Add(e);
|
|
_displayingOrder.Add(order);
|
|
element.transform.SetParent(transform, false);
|
|
if (m_subManager != null) m_subManager.Add(e);
|
|
}
|
|
void Remove(ReportViewModel e) {
|
|
int index = _displayingReports.IndexOf(e);
|
|
if (index == -1) return;
|
|
_displayingElements.RemoveAt(index);
|
|
_displayingReports.RemoveAt(index);
|
|
_displayingOrder.RemoveAt(index);
|
|
var element = transform.GetChild(index);
|
|
element.SetParent(null, false);
|
|
Destroy(element.gameObject);
|
|
|
|
int order = _displayingOrder.Take(index).Sum();
|
|
for (int i = index; i < transform.childCount; i++) {
|
|
var child = transform.GetChild(i);
|
|
var pos = child.localPosition;
|
|
pos.z = OrderToZ(order);
|
|
child.localPosition = pos;
|
|
order += _displayingOrder[i];
|
|
}
|
|
|
|
if (m_subManager != null) m_subManager.Remove(e);
|
|
}
|
|
|
|
float m_scale = 1;
|
|
public float Scale {
|
|
get => m_scale;
|
|
set {
|
|
m_scale = value;
|
|
foreach (Transform element in transform) {
|
|
element.GetComponent<UnityMapElement>().Scale = value;
|
|
}
|
|
if (m_subManager != null) m_subManager.Scale = value;
|
|
}
|
|
}
|
|
|
|
readonly ContextedGeneratorManager<IMapGeneratorContext, MapElement> _gen = new(new IContextedGenerator<IMapGeneratorContext, MapElement>[] {
|
|
new CENCEarthquakeMapGenerator(),
|
|
new CENCEEWMapGenerator(),
|
|
new CWAEarthquakeMapGenerator(),
|
|
new CWAEEWMapGenerator(),
|
|
new CWATsunamiMapGenerator(),
|
|
new FujianEEWMapGenerator(),
|
|
new GlobalQuakeMapViewGenerator(),
|
|
new JMAAtomMapGenerator(),
|
|
new JMAEEWMapGenerator(),
|
|
new NOAAMapGenerator(),
|
|
new SichuanEEWMapGenerator(),
|
|
});
|
|
public UnityMapElement Build(object e, out CultureInfo culture, out int order) {
|
|
culture = CultureInfo.InvariantCulture;
|
|
order = 0;
|
|
var ret = Convert(_gen.TryGenerate(e, SharedSettings.Instance, ref culture), ref order);
|
|
if (ret == null)
|
|
return null;
|
|
ret.Scale = Scale;
|
|
return ret;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static float OrderToZ(int order) => order / -1000f;
|
|
|
|
[SerializeField] Element.GroupElement m_prefabGroupElement;
|
|
[SerializeField] Element.MaskedGroupElement m_prefabMaskedGroupElement;
|
|
[SerializeField] Element.OngoingGroupElement m_prefabOngoingGroupElement;
|
|
[SerializeField] Element.HypocenterElement m_prefabHypocenterElement;
|
|
[SerializeField] Element.LabeledPointElement m_prefabLabeledPointElement;
|
|
[SerializeField] Element.MultiLineElement m_prefabMultiLineElement;
|
|
[SerializeField] Element.MultiPolygonElement m_prefabMultiPolygonElement;
|
|
[SerializeField] Element.PointElement m_prefabPointElement;
|
|
[SerializeField] Element.TsunamiHeightElement m_prefabTsunamiHeightElement;
|
|
[SerializeField] Element.WaveCircleElement m_prefabWaveCircleElement;
|
|
public UnityMapElement Convert(MapElement mapElement, ref int order) => mapElement switch {
|
|
MaskedGroupElement maskedGroup => ConvertMaskedGroup(maskedGroup, ref order),
|
|
OngoingGroupElement ongoingGroup => ConvertOngoingGroup(ongoingGroup, ref order),
|
|
GroupElement group => ConvertGroup(group, m_prefabGroupElement, ref order),
|
|
HypocenterElement hypocenter => ConvertHypocenter(hypocenter, ref order),
|
|
LabeledPointElement labeledPoint => ConvertLabeledPoint(labeledPoint, ref order),
|
|
MultiLineElement multiLine => ConvertMultiLine(multiLine, ref order),
|
|
MultiPolygonElement multiPolygon => ConvertMultiPolygon(multiPolygon, ref order),
|
|
PointElement point => ConvertPoint(point, ref order),
|
|
TsunamiHeightElement tsunamiHeight => ConvertTsunamiHeight(tsunamiHeight, ref order),
|
|
WaveCircleElement waveCircle => ConvertWaveCircle(waveCircle, ref order),
|
|
_ => null,
|
|
};
|
|
T Convert<T>(MapElement element, T prefab) where T : UnityMapElement {
|
|
var ret = Instantiate(prefab);
|
|
ret.MaxScale = element.MaxScale;
|
|
return ret;
|
|
}
|
|
T ConvertGroup<T>(GroupElement group, T prefab, ref int order) where T : Element.GroupElement {
|
|
var ret = Convert(group, prefab);
|
|
foreach (var e in group.Elements) ret.AddElement(Convert(e, ref order));
|
|
return ret;
|
|
}
|
|
Element.MaskedGroupElement ConvertMaskedGroup(MaskedGroupElement maskedGroup, ref int order) {
|
|
var ret = ConvertGroup(maskedGroup, m_prefabMaskedGroupElement, ref order);
|
|
ret.SetMasks(maskedGroup.Masks);
|
|
return ret;
|
|
}
|
|
Element.OngoingGroupElement ConvertOngoingGroup(OngoingGroupElement ongoingGroup, ref int order) {
|
|
var ret = ConvertGroup(ongoingGroup, m_prefabOngoingGroupElement, ref order);
|
|
ret.BlinkingPeriod = ongoingGroup.BlinkingPeriod;
|
|
return ret;
|
|
}
|
|
Element.HypocenterElement ConvertHypocenter(HypocenterElement hypocenter, ref int order) {
|
|
var ret = Convert(hypocenter, m_prefabHypocenterElement);
|
|
ret.SetLocation(hypocenter.Location, ref order);
|
|
ret.IsLowQuality = hypocenter.IsLowQuality;
|
|
ret.Size = hypocenter.Size;
|
|
return ret;
|
|
}
|
|
Element.LabeledPointElement ConvertLabeledPoint(LabeledPointElement labeledPoint, ref int order) {
|
|
var ret = Convert(labeledPoint, m_prefabLabeledPointElement);
|
|
ret.SetLocation(labeledPoint.Location, ref order);
|
|
ret.Text = labeledPoint.Text;
|
|
ret.Color = labeledPoint.FillColor.ToUnityColor();
|
|
ret.TextColor = labeledPoint.TextColor.ToUnityColor();
|
|
ret.IsArea = labeledPoint.IsAreaLabel;
|
|
ret.Size = labeledPoint.Size;
|
|
return ret;
|
|
}
|
|
Element.MultiLineElement ConvertMultiLine(MultiLineElement multiLine, ref int order) {
|
|
var ret = Convert(multiLine, m_prefabMultiLineElement);
|
|
ret.SetLines(multiLine.Lines, ref order);
|
|
ret.Color = multiLine.BorderColor.ToUnityColor();
|
|
ret.Width = multiLine.StrokeWidth;
|
|
return ret;
|
|
}
|
|
Element.MultiPolygonElement ConvertMultiPolygon(MultiPolygonElement multiPolygon, ref int order) {
|
|
var ret = Convert(multiPolygon, m_prefabMultiPolygonElement);
|
|
ret.SetPolygons(multiPolygon.Polygons, ref order);
|
|
ret.FillColor = multiPolygon.FillColor.ToUnityColor();
|
|
ret.BorderColor = multiPolygon.BorderColor.ToUnityColor();
|
|
ret.BorderWidth = multiPolygon.StrokeWidth;
|
|
return ret;
|
|
}
|
|
Element.PointElement ConvertPoint(PointElement point, ref int order) {
|
|
var ret = Convert(point, m_prefabPointElement);
|
|
ret.SetLocation(point.Location, ref order);
|
|
ret.Color = point.FillColor.ToUnityColor();
|
|
ret.Size = point.Size;
|
|
return ret;
|
|
}
|
|
Element.TsunamiHeightElement ConvertTsunamiHeight(TsunamiHeightElement tsunamiHeight, ref int order) {
|
|
var ret = Convert(tsunamiHeight, m_prefabTsunamiHeightElement);
|
|
ret.SetLocation(tsunamiHeight.Location, ref order);
|
|
ret.Height = tsunamiHeight.Height;
|
|
ret.Color = tsunamiHeight.FillColor.ToUnityColor();
|
|
ret.IsRising = tsunamiHeight.IsRising;
|
|
ret.IsOutOfRange = tsunamiHeight.IsOutOfRange;
|
|
ret.IsMissing = tsunamiHeight.IsMissing;
|
|
ret.Width = tsunamiHeight.Width;
|
|
return ret;
|
|
}
|
|
Element.WaveCircleElement ConvertWaveCircle(WaveCircleElement waveCircle, ref int order) {
|
|
var ret = Convert(waveCircle, m_prefabWaveCircleElement);
|
|
ret.SetHypocenterLocation(waveCircle.HypocenterLocation, ref order);
|
|
ret.OriginTime = waveCircle.OriginTime;
|
|
ret.Depth = waveCircle.Depth;
|
|
ret.ReportTime = waveCircle.ReportTime;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|