This repository has been archived on 2025-08-02. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Cryville.EEW.Unity/Assets/Cryville.EEW.Unity/Map/MapElementManager.cs

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;
}
}
}