Compare commits
20 Commits
0.0.3
...
a8f46113d4
| Author | SHA1 | Date | |
|---|---|---|---|
| a8f46113d4 | |||
| 99736f114d | |||
| 4d1a008106 | |||
| 9318cbca4e | |||
| a162f345c4 | |||
| 1af4afc7c6 | |||
| a3efe939e8 | |||
| 5daee1a01a | |||
| 2d5d305528 | |||
| 8da46c0511 | |||
| 75b5d7708c | |||
| 5b2177a795 | |||
| 8cb33dca5f | |||
| ae2e0af18a | |||
| 2ac5a3d4f0 | |||
| 5f78a1afde | |||
| ef5cf78a03 | |||
| b60e62af70 | |||
| 3e59fe1462 | |||
| 4b4bf5ed65 |
@@ -1,19 +1,60 @@
|
||||
using Cryville.Common.Font;
|
||||
using Cryville.Common.Logging;
|
||||
using Cryville.Common.Unity.UI;
|
||||
using Cryville.Culture;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using UnityEngine;
|
||||
using Logger = Cryville.Common.Logging.Logger;
|
||||
|
||||
namespace Cryville.EEW.Unity {
|
||||
class App {
|
||||
public static string AppDataPath { get; private set; }
|
||||
|
||||
public static Logger MainLogger { get; private set; }
|
||||
static FileStream _logFileStream;
|
||||
static StreamLoggerListener _logWriter;
|
||||
|
||||
static bool _init;
|
||||
public static void Init() {
|
||||
if (_init) return;
|
||||
_init = true;
|
||||
|
||||
AppDataPath = Application.persistentDataPath;
|
||||
|
||||
var logPath = Directory.CreateDirectory(Path.Combine(AppDataPath, "logs"));
|
||||
_logFileStream = new FileStream(
|
||||
Path.Combine(
|
||||
logPath.FullName,
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"{0}.log",
|
||||
DateTimeOffset.UtcNow.ToString("yyyyMMddHHmmssfff", CultureInfo.InvariantCulture)
|
||||
)
|
||||
),
|
||||
FileMode.Create, FileAccess.Write, FileShare.Read
|
||||
);
|
||||
_logWriter = new StreamLoggerListener(_logFileStream) { AutoFlush = true };
|
||||
MainLogger = new Logger();
|
||||
var listener = new InstantLoggerListener();
|
||||
listener.Log += MainLogger.Log;
|
||||
MainLogger.AddListener(_logWriter);
|
||||
Application.logMessageReceivedThreaded += OnInternalLog;
|
||||
|
||||
MainLogger.Log(1, "App", null, "App Version: {0}", Application.version);
|
||||
MainLogger.Log(1, "App", null, "Unity Version: {0}", Application.unityVersion);
|
||||
MainLogger.Log(1, "App", null, "Operating System: {0}, Unity = {1}, Family = {2}", Environment.OSVersion, SystemInfo.operatingSystem, SystemInfo.operatingSystemFamily);
|
||||
MainLogger.Log(1, "App", null, "Platform: Build = {0}, Unity = {1}", PlatformConfig.Name, Application.platform);
|
||||
MainLogger.Log(1, "App", null, "Culture: {0}, UI = {1}, Unity = {2}", SharedCultures.CurrentCulture, SharedCultures.CurrentUICulture, Application.systemLanguage);
|
||||
MainLogger.Log(1, "App", null, "Device: Model = {0}, Type = {1}", SystemInfo.deviceModel, SystemInfo.deviceType);
|
||||
MainLogger.Log(1, "App", null, "Graphics: Name = {0}, Type = {1}, Vendor = {2}, Version = {3}", SystemInfo.graphicsDeviceName, SystemInfo.graphicsDeviceType, SystemInfo.graphicsDeviceVendor, SystemInfo.graphicsDeviceVersion);
|
||||
MainLogger.Log(1, "App", null, "Processor: Count = {0}, Frequency = {1}MHz, Type = {2}", SystemInfo.processorCount, SystemInfo.processorFrequency, SystemInfo.processorType);
|
||||
|
||||
MainLogger.Log(1, "App", null, "Initializing font manager");
|
||||
foreach (var res in Resources.LoadAll<TextAsset>("cldr/common/validity")) {
|
||||
IdValidity.Load(LoadXmlDocument(res));
|
||||
}
|
||||
@@ -25,7 +66,10 @@ namespace Cryville.EEW.Unity {
|
||||
};
|
||||
TMPLocalizedText.DefaultShader = Resources.Load<Shader>(PlatformConfig.TextShader);
|
||||
|
||||
MainLogger.Log(1, "App", null, "Loading config");
|
||||
SharedSettings.Instance.Init();
|
||||
|
||||
MainLogger.Log(1, "App", null, "Initialized");
|
||||
}
|
||||
|
||||
static readonly Encoding _encoding = new UTF8Encoding(false, true);
|
||||
@@ -40,5 +84,16 @@ namespace Cryville.EEW.Unity {
|
||||
using var reader = XmlReader.Create(stream, _xmlSettings);
|
||||
return XDocument.Load(reader);
|
||||
}
|
||||
|
||||
static void OnInternalLog(string condition, string stackTrace, LogType type) {
|
||||
var l = type switch {
|
||||
LogType.Log => 1,
|
||||
LogType.Assert => 2,
|
||||
LogType.Warning => 3,
|
||||
LogType.Error or LogType.Exception => 4,
|
||||
_ => 1,
|
||||
};
|
||||
MainLogger.Log(l, "Internal", null, "{0}\n{1}", condition, stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("0.0.3")]
|
||||
[assembly: AssemblyVersion("0.0.7")]
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using Cryville.EEW.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Cryville.EEW.Unity {
|
||||
@@ -8,11 +12,18 @@ namespace Cryville.EEW.Unity {
|
||||
float SeverityColorMappingLuminanceMultiplier,
|
||||
bool UseContinuousColor,
|
||||
string ColorScheme,
|
||||
string LocationNamer,
|
||||
|
||||
string OverrideTimeZone,
|
||||
bool DoDisplayTimeZone,
|
||||
bool DoSwitchBackToHistory,
|
||||
|
||||
string NowcastWarningDelayTolerance,
|
||||
|
||||
string OverrideDisplayCulture,
|
||||
IReadOnlyCollection<TTSCultureConfig> TTSCultures,
|
||||
bool DoIgnoreLanguageVariant,
|
||||
|
||||
IReadOnlyCollection<EventSourceConfig> EventSources
|
||||
) {
|
||||
public static Config Default => new(
|
||||
@@ -20,11 +31,18 @@ namespace Cryville.EEW.Unity {
|
||||
1f,
|
||||
false,
|
||||
"Default",
|
||||
"FERegionLong",
|
||||
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
|
||||
"1:00:00",
|
||||
|
||||
"",
|
||||
new List<TTSCultureConfig> { new(SharedCultures.CurrentUICulture) },
|
||||
true,
|
||||
|
||||
new List<EventSourceConfig> {
|
||||
new JMAAtomEventSourceConfig(Array.Empty<string>()),
|
||||
new UpdateCheckerEventSourceConfig(),
|
||||
@@ -37,6 +55,7 @@ namespace Cryville.EEW.Unity {
|
||||
[JsonDerivedType(typeof(BMKGOpenDataEventSourceConfig), "BMKGOpenData")]
|
||||
[JsonDerivedType(typeof(CWAOpenDataEventSourceConfig), "CWAOpenData")]
|
||||
[JsonDerivedType(typeof(EMSCRealTimeEventSourceConfig), "EMSCRealTime")]
|
||||
[JsonDerivedType(typeof(GeoNetEventSourceConfig), "GeoNet")]
|
||||
[JsonDerivedType(typeof(GlobalQuakeServerEventSourceConfig), "GlobalQuakeServer")]
|
||||
[JsonDerivedType(typeof(GlobalQuakeServer15EventSourceConfig), "GlobalQuakeServer15")]
|
||||
[JsonDerivedType(typeof(JMAAtomEventSourceConfig), "JMAAtom")]
|
||||
@@ -48,15 +67,30 @@ namespace Cryville.EEW.Unity {
|
||||
record BMKGOpenDataEventSourceConfig([property: JsonRequired] string[] Subtypes) : EventSourceConfig;
|
||||
record CWAOpenDataEventSourceConfig([property: JsonRequired] string Subtype, [property: JsonRequired] string Token) : EventSourceConfig;
|
||||
record EMSCRealTimeEventSourceConfig() : EventSourceConfig;
|
||||
record GeoNetEventSourceConfig(int MinimumMMI = 3, bool DoGetFullHistory = false, bool DoGetStrongMotionInfo = true) : EventSourceConfig;
|
||||
record GlobalQuakeServerEventSourceConfig([property: JsonRequired] string Host, int Port = 38000) : EventSourceConfig;
|
||||
record GlobalQuakeServer15EventSourceConfig(string Host, int Port = 38000) : GlobalQuakeServerEventSourceConfig(Host, Port);
|
||||
record JMAAtomEventSourceConfig(IReadOnlyCollection<string> Filter = null, bool IsFilterWhitelist = false) : EventSourceConfig;
|
||||
record NOAAEventSourceConfig([property: JsonRequired] string Subtype) : EventSourceConfig;
|
||||
record UpdateCheckerEventSourceConfig : EventSourceConfig;
|
||||
record USGSQuakeMLEventSourceConfig([property: JsonRequired] string Subtype) : EventSourceConfig;
|
||||
record WolfxEventSourceConfig(IReadOnlyCollection<string> Filter = null, bool IsFilterWhitelist = false) : EventSourceConfig;
|
||||
record WolfxEventSourceConfig(IReadOnlyCollection<string> Filter = null, bool IsFilterWhitelist = false, bool UseRawCENCLocationName = false) : EventSourceConfig;
|
||||
|
||||
[JsonSerializable(typeof(Config))]
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSourceGenerationOptions(Converters = new Type[] { typeof(CultureInfoConverter) }, WriteIndented = true)]
|
||||
sealed partial class ConfigSerializationContext : JsonSerializerContext { }
|
||||
|
||||
sealed class CultureInfoConverter : JsonConverter<CultureInfo> {
|
||||
public override CultureInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
||||
Debug.Assert(typeToConvert == typeof(CultureInfo));
|
||||
var value = reader.GetString();
|
||||
if (value == null) return CultureInfo.InvariantCulture;
|
||||
if (value == "") return SharedCultures.CurrentUICulture;
|
||||
return SharedCultures.Get(value);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, CultureInfo value, JsonSerializerOptions options) {
|
||||
writer.WriteStringValue(value.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:b92f9c7ac10b1c04e86fc48210f62ab1",
|
||||
"GUID:1e0937e40dadba24a97b7342c4559580",
|
||||
"GUID:e5b7e7f40a80a814ba706299d68f9213",
|
||||
"GUID:da293eebbcb9a4947a212534c52d1a32"
|
||||
],
|
||||
|
||||
@@ -17,19 +17,24 @@ namespace Cryville.EEW.Unity.Map {
|
||||
GameObject m_prefabTile;
|
||||
[SerializeField]
|
||||
GameObject m_prefabBitmapHolder;
|
||||
[SerializeField]
|
||||
int m_maxMapTileZoom = 10;
|
||||
[SerializeField]
|
||||
bool m_isEditor;
|
||||
|
||||
readonly MapTileCacheManager _tiles = new();
|
||||
MapTileCacheManager _tiles;
|
||||
float _elementLayerZ;
|
||||
|
||||
void Start() {
|
||||
_camera = GetComponent<Camera>();
|
||||
_tiles = m_isEditor ? new EditorMapTileCacheManager() : new MapTileCacheManager();
|
||||
_tiles.ExtraCachedZoomLevel = 20;
|
||||
_tiles.Parent = m_layerTile;
|
||||
_tiles.PrefabTile = m_prefabTile;
|
||||
_tiles.PrefabBitmapHolder = m_prefabBitmapHolder;
|
||||
_tiles.CacheDir = Application.temporaryCachePath;
|
||||
_camera.orthographicSize = 0.5f / MathF.Max(1, (float)_camera.pixelWidth / _camera.pixelHeight);
|
||||
_elementLayerZ = m_layerElement.transform.position.z;
|
||||
if (m_layerElement != null) _elementLayerZ = m_layerElement.transform.position.z;
|
||||
_mapElementUpdated = true;
|
||||
}
|
||||
void OnDestroy() {
|
||||
@@ -74,7 +79,7 @@ namespace Cryville.EEW.Unity.Map {
|
||||
}
|
||||
}
|
||||
void ZoomToMapElement() {
|
||||
var aabb = m_layerElement.AABB;
|
||||
var aabb = m_layerElement != null ? m_layerElement.AABB : null;
|
||||
if (aabb is not RectangleF b) return;
|
||||
if (b.Width * _camera.pixelHeight < _camera.pixelWidth * b.Height)
|
||||
Scale = b.Height;
|
||||
@@ -97,26 +102,30 @@ namespace Cryville.EEW.Unity.Map {
|
||||
transform.localPosition = new(nx, Math.Clamp(transform.position.y, h / 2 - 1, -h / 2), -20);
|
||||
|
||||
var bounds = new Bounds((Vector2)transform.position, new Vector2(w, h));
|
||||
int zoom = Math.Clamp((int)Math.Log(vz / 256, 2) + 1, 0, 10);
|
||||
int zoom = Math.Clamp((int)Math.Log(vz / 256, 2) + 1, 0, m_maxMapTileZoom);
|
||||
int zoomScale = 1 << zoom;
|
||||
_tiles.MoveTo(
|
||||
new(Mathf.FloorToInt(bounds.min.x * zoomScale), Mathf.FloorToInt(-bounds.max.y * zoomScale), zoom),
|
||||
new(Mathf.CeilToInt(bounds.max.x * zoomScale), Mathf.CeilToInt(-bounds.min.y * zoomScale), zoom)
|
||||
);
|
||||
|
||||
m_layerElement.Scale = h;
|
||||
m_layerElementSub.Scale = h;
|
||||
if (m_layerElement != null) {
|
||||
m_layerElement.Scale = h;
|
||||
}
|
||||
if (m_layerElementSub != null) {
|
||||
m_layerElementSub.Scale = h;
|
||||
|
||||
if (nx - w / 2 < 0) {
|
||||
m_layerElementSub.gameObject.SetActive(true);
|
||||
m_layerElementSub.transform.localPosition = new(-1, 0, _elementLayerZ);
|
||||
}
|
||||
else if (nx + w / 2 > 1) {
|
||||
m_layerElementSub.gameObject.SetActive(true);
|
||||
m_layerElementSub.transform.localPosition = new(1, 0, _elementLayerZ);
|
||||
}
|
||||
else {
|
||||
m_layerElementSub.gameObject.SetActive(false);
|
||||
if (nx - w / 2 < 0) {
|
||||
m_layerElementSub.gameObject.SetActive(true);
|
||||
m_layerElementSub.transform.localPosition = new(-1, 0, _elementLayerZ);
|
||||
}
|
||||
else if (nx + w / 2 > 1) {
|
||||
m_layerElementSub.gameObject.SetActive(true);
|
||||
m_layerElementSub.transform.localPosition = new(1, 0, _elementLayerZ);
|
||||
}
|
||||
else {
|
||||
m_layerElementSub.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
Assets/Cryville.EEW.Unity/Map/EditorMapTileCacheManager.cs
Normal file
15
Assets/Cryville.EEW.Unity/Map/EditorMapTileCacheManager.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Cryville.EEW.Core.Map;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity.Map {
|
||||
sealed class EditorMapTileCacheManager : MapTileCacheManager {
|
||||
protected override MapTileBitmapHolder CreateBitmapHolder(MapTileIndex index) => new(
|
||||
index,
|
||||
GameObject.Instantiate(PrefabBitmapHolder, Parent, false),
|
||||
new($"https://tile.openstreetmap.org/{index.Z}/{index.NX}/{index.NY}.png")
|
||||
);
|
||||
|
||||
protected override string GetCacheFilePath(MapTileIndex index) => Path.Combine(CacheDir, $"map_editor/{index.Z}/{index.NX}/{index.NY}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 478198b8ecc0082449fa3f68795174a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -2,6 +2,7 @@ using Cryville.EEW.BMKGOpenData.Map;
|
||||
using Cryville.EEW.Core;
|
||||
using Cryville.EEW.CWAOpenData.Map;
|
||||
using Cryville.EEW.EMSC.Map;
|
||||
using Cryville.EEW.GeoNet.Map;
|
||||
using Cryville.EEW.GlobalQuake.Map;
|
||||
using Cryville.EEW.JMAAtom.Map;
|
||||
using Cryville.EEW.Map;
|
||||
@@ -135,6 +136,9 @@ namespace Cryville.EEW.Unity.Map {
|
||||
new CWATsunamiMapGenerator(),
|
||||
new EMSCRealTimeEventMapGenerator(),
|
||||
new FujianEEWMapGenerator(),
|
||||
new GeoNetQuakeHistoryMapGenerator(),
|
||||
new GeoNetQuakeMapGenerator(),
|
||||
new GeoNetStrongMapGenerator(),
|
||||
new GlobalQuakeMapViewGenerator(),
|
||||
new JMAAtomMapGenerator(),
|
||||
new JMAEEWMapGenerator(),
|
||||
|
||||
@@ -7,10 +7,12 @@ using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity.Map {
|
||||
sealed class MapTileBitmapHolder : Core.Map.MapTileBitmapHolder {
|
||||
MapTileBitmapHolderBehaviour _behaviour;
|
||||
readonly MapTileBitmapHolderBehaviour _behaviour;
|
||||
readonly Uri _uri;
|
||||
|
||||
public MapTileBitmapHolder(MapTileIndex index, GameObject gameObject) : base(index) {
|
||||
public MapTileBitmapHolder(MapTileIndex index, GameObject gameObject, Uri uri) : base(index) {
|
||||
_behaviour = gameObject.GetComponent<MapTileBitmapHolderBehaviour>();
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing) {
|
||||
@@ -20,8 +22,7 @@ namespace Cryville.EEW.Unity.Map {
|
||||
}
|
||||
}
|
||||
|
||||
protected override Uri GetUri() =>
|
||||
new($"https://server.arcgisonline.com/ArcGIS/rest/services/Ocean/World_Ocean_Base/MapServer/tile/{Index.Z}/{Index.NY}/{Index.NX}");
|
||||
protected override Uri GetUri() => _uri;
|
||||
|
||||
protected override Task LoadBitmap(FileInfo file, CancellationToken cancellationToken) {
|
||||
_behaviour.Load(file);
|
||||
|
||||
@@ -40,18 +40,18 @@ namespace Cryville.EEW.Unity.Map {
|
||||
_req.SendWebRequest();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Debug.LogException(ex);
|
||||
App.MainLogger.Log(4, "Map", null, "An error occurred when loading map tile {0}: {1}", _localFile, ex);
|
||||
}
|
||||
_isReady = false;
|
||||
}
|
||||
if (_req == null || !_req.isDone) return;
|
||||
if (_texHandler.isDone) {
|
||||
if (_texHandler.isDone && _texHandler.texture != null) {
|
||||
_tex = _texHandler.texture;
|
||||
_tex.wrapMode = TextureWrapMode.Clamp;
|
||||
_sprite = Sprite.Create(_tex, new Rect(0, 0, _tex.width, _tex.height), Vector2.zero, _tex.height, 0, SpriteMeshType.FullRect, Vector4.zero, false);
|
||||
}
|
||||
else {
|
||||
Debug.LogError(_req.error);
|
||||
App.MainLogger.Log(4, "Map", null, "An error occurred when loading map tile {0}: {1}", _localFile, _texHandler.error);
|
||||
_localFile.Delete();
|
||||
}
|
||||
_req.Dispose();
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity.Map {
|
||||
sealed class MapTileCacheManager : MapTileCacheManager<MapTileBitmapHolder> {
|
||||
class MapTileCacheManager : MapTileCacheManager<MapTileBitmapHolder> {
|
||||
public GameObject PrefabTile { get; set; }
|
||||
public GameObject PrefabBitmapHolder { get; set; }
|
||||
|
||||
@@ -12,8 +12,12 @@ namespace Cryville.EEW.Unity.Map {
|
||||
|
||||
public string CacheDir { get; set; }
|
||||
|
||||
protected override MapTileBitmapHolder CreateBitmapHolder(MapTileIndex index) => new(index, GameObject.Instantiate(PrefabBitmapHolder, Parent, false));
|
||||
|
||||
protected override MapTileBitmapHolder CreateBitmapHolder(MapTileIndex index) => new(
|
||||
index,
|
||||
GameObject.Instantiate(PrefabBitmapHolder, Parent, false),
|
||||
new($"https://server.arcgisonline.com/ArcGIS/rest/services/Ocean/World_Ocean_Base/MapServer/tile/{index.Z}/{index.NY}/{index.NX}")
|
||||
);
|
||||
|
||||
protected override string GetCacheFilePath(MapTileIndex index) => Path.Combine(CacheDir, $"map/{index.Z}/{index.NX}/{index.NY}");
|
||||
|
||||
readonly Dictionary<MapTile<MapTileBitmapHolder>, MapTile> _map = new();
|
||||
|
||||
219
Assets/Cryville.EEW.Unity/Map/RegionEditor.cs
Normal file
219
Assets/Cryville.EEW.Unity/Map/RegionEditor.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity.Map {
|
||||
sealed class RegionEditor : MonoBehaviour {
|
||||
QuadTreeNode _root;
|
||||
|
||||
[SerializeField] CameraController m_cameraController;
|
||||
[SerializeField] GameObject m_regionViewPrefab;
|
||||
|
||||
[SerializeField] TMP_Text m_textSelectedInfo;
|
||||
[SerializeField] TMP_Text m_textHoveredInfo;
|
||||
[SerializeField] TMP_InputField m_inputId;
|
||||
|
||||
readonly Dictionary<QuadTreeNode, RegionView> _map = new();
|
||||
|
||||
void Start() {
|
||||
var file = new FileInfo(Path.Combine(Application.persistentDataPath, "regions.json"));
|
||||
if (file.Exists) {
|
||||
using var stream = file.OpenRead();
|
||||
_root = JsonSerializer.Deserialize<QuadTreeNode>(stream);
|
||||
}
|
||||
else {
|
||||
_root = NewNode();
|
||||
}
|
||||
BuildView(_root);
|
||||
}
|
||||
|
||||
public void Save() {
|
||||
var file = new FileInfo(Path.Combine(Application.persistentDataPath, "regions.json"));
|
||||
using var stream = file.Open(FileMode.Create);
|
||||
JsonSerializer.Serialize(stream, _root);
|
||||
}
|
||||
|
||||
void BuildView(QuadTreeNode node) {
|
||||
var view = Instantiate(m_regionViewPrefab, transform, false).GetComponent<RegionView>();
|
||||
view.Init(node.X, node.Y, node.Z);
|
||||
view.Id = node.Data.Id;
|
||||
view.IsLeaf = node.Children == null;
|
||||
_map.Add(node, view);
|
||||
BuildChildViews(node);
|
||||
}
|
||||
|
||||
void BuildChildViews(QuadTreeNode node) {
|
||||
if (node.Children == null) return;
|
||||
foreach (var child in node.Children) {
|
||||
BuildView(child);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyChildViews(QuadTreeNode node) {
|
||||
if (node.Children == null) return;
|
||||
foreach (var child in node.Children) {
|
||||
Destroy(_map[child].gameObject);
|
||||
_map.Remove(child);
|
||||
}
|
||||
}
|
||||
|
||||
QuadTreeNode _hoveredNode;
|
||||
QuadTreeNode _selectedNode;
|
||||
Vector3? _ppos;
|
||||
void Update() {
|
||||
var pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
|
||||
pos.y += 1;
|
||||
var hoveredNode = _root.Get(pos);
|
||||
if (hoveredNode != _hoveredNode) {
|
||||
HoverNode(hoveredNode);
|
||||
}
|
||||
if (Input.GetMouseButtonDown(0)) {
|
||||
_ppos = Input.mousePosition;
|
||||
}
|
||||
if (Input.GetMouseButton(0) && _ppos is Vector3 pos0) {
|
||||
if (Input.mousePosition != pos0) {
|
||||
_ppos = null;
|
||||
}
|
||||
}
|
||||
if (hoveredNode == null) return;
|
||||
if (Input.GetMouseButtonUp(0) && _ppos != null) {
|
||||
SelectNode(hoveredNode);
|
||||
_ppos = null;
|
||||
}
|
||||
if (m_inputId.isFocused)
|
||||
return;
|
||||
if (Input.GetKeyUp(KeyCode.A)) {
|
||||
MergeNode(hoveredNode);
|
||||
}
|
||||
if (Input.GetKeyUp(KeyCode.S)) {
|
||||
SplitNode(hoveredNode);
|
||||
}
|
||||
if (Input.GetKeyUp(KeyCode.C)) {
|
||||
m_inputId.text = hoveredNode.Data.Id;
|
||||
}
|
||||
if (Input.GetKeyUp(KeyCode.V)) {
|
||||
hoveredNode.Data.Id = m_inputId.text;
|
||||
_map[hoveredNode].Id = hoveredNode.Data.Id;
|
||||
}
|
||||
}
|
||||
void HoverNode(QuadTreeNode node) {
|
||||
if (_hoveredNode != null) {
|
||||
_map[_hoveredNode].IsHovered = false;
|
||||
}
|
||||
_hoveredNode = node;
|
||||
if (_hoveredNode != null) {
|
||||
_map[_hoveredNode].IsHovered = true;
|
||||
m_textHoveredInfo.text = string.Format(CultureInfo.InvariantCulture, "<Hovered>\nZ: {2}, XY: ({0}, {1})\nD: {3}", node.X, node.Y, node.Z, node.Data.Id);
|
||||
}
|
||||
else {
|
||||
m_textHoveredInfo.text = "";
|
||||
}
|
||||
}
|
||||
void SelectNode(QuadTreeNode node) {
|
||||
if (_selectedNode != null) {
|
||||
_map[_selectedNode].IsSelected = false;
|
||||
}
|
||||
_selectedNode = node;
|
||||
if (_selectedNode != null) {
|
||||
_map[_selectedNode].IsSelected = true;
|
||||
m_textSelectedInfo.text = string.Format(CultureInfo.InvariantCulture, "<Selected>\nZ: {2}, XY: ({0}, {1})\nD: {3}", node.X, node.Y, node.Z, node.Data.Id);
|
||||
}
|
||||
else {
|
||||
m_textSelectedInfo.text = "";
|
||||
}
|
||||
}
|
||||
void MergeNode(QuadTreeNode node) {
|
||||
var parent = node.Parent;
|
||||
if (parent == null)
|
||||
return;
|
||||
DestroyChildViews(parent);
|
||||
_map[parent].IsLeaf = true;
|
||||
parent.Merge();
|
||||
_hoveredNode = null;
|
||||
if (_selectedNode != null && !_map.ContainsKey(_selectedNode)) {
|
||||
_selectedNode = null;
|
||||
}
|
||||
}
|
||||
void SplitNode(QuadTreeNode node) {
|
||||
node.Split();
|
||||
_map[node].IsLeaf = false;
|
||||
BuildChildViews(node);
|
||||
}
|
||||
|
||||
static QuadTreeNode NewNode() => new() { Data = new("") };
|
||||
|
||||
sealed class QuadTreeNode {
|
||||
QuadTreeNode[] m_children;
|
||||
public QuadTreeNode[] Children {
|
||||
get => m_children;
|
||||
set {
|
||||
if (m_children != null) {
|
||||
foreach (var child in m_children) {
|
||||
child.DetachFromParent();
|
||||
}
|
||||
}
|
||||
m_children = value;
|
||||
UpdateChildren();
|
||||
}
|
||||
}
|
||||
QuadTreeNode m_parent;
|
||||
[JsonIgnore] public QuadTreeNode Parent => m_parent;
|
||||
void AttachToParent(QuadTreeNode parent, int index) {
|
||||
if (m_parent != null && m_parent != parent)
|
||||
throw new InvalidOperationException("Node already in a tree.");
|
||||
m_parent = parent;
|
||||
X = (parent.X << 1) | (index is 0 or 3 ? 1 : 0);
|
||||
Y = (parent.Y << 1) | (index is 0 or 1 ? 1 : 0);
|
||||
Z = parent.Z + 1;
|
||||
UpdateChildren();
|
||||
}
|
||||
void DetachFromParent() => m_parent = null;
|
||||
void UpdateChildren() {
|
||||
if (m_children != null) {
|
||||
for (int i = 0; i < m_children.Length; i++) {
|
||||
m_children[i].AttachToParent(this, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
[JsonIgnore] public int X { get; private set; }
|
||||
[JsonIgnore] public int Y { get; private set; }
|
||||
[JsonIgnore] public int Z { get; private set; }
|
||||
public RegionData Data { get; set; }
|
||||
|
||||
public QuadTreeNode Get(Vector2 pos) {
|
||||
if ((pos.x is < 0 or >= 1) || (pos.y is < 0 or >= 1))
|
||||
return null;
|
||||
if (m_children == null)
|
||||
return this;
|
||||
Vector2 subPos = pos * 2;
|
||||
subPos.x %= 1;
|
||||
subPos.y %= 1;
|
||||
return pos.x >= 0.5f
|
||||
? (pos.y >= 0.5f ? m_children[0] : m_children[3]).Get(subPos)
|
||||
: (pos.y >= 0.5f ? m_children[1] : m_children[2]).Get(subPos);
|
||||
}
|
||||
|
||||
public void Merge() {
|
||||
Children = null;
|
||||
}
|
||||
|
||||
public void Split() {
|
||||
Children = new QuadTreeNode[] {
|
||||
new() { Data = Data.Copy() },
|
||||
new() { Data = Data.Copy() },
|
||||
new() { Data = Data.Copy() },
|
||||
new() { Data = Data.Copy() },
|
||||
};
|
||||
}
|
||||
}
|
||||
sealed record RegionData(string Id) {
|
||||
public string Id { get; set; } = Id;
|
||||
public RegionData Copy() => (RegionData)MemberwiseClone();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Cryville.EEW.Unity/Map/RegionEditor.cs.meta
Normal file
11
Assets/Cryville.EEW.Unity/Map/RegionEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd7b70d11ebfe324e830806e394cc334
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
68
Assets/Cryville.EEW.Unity/Map/RegionView.cs
Normal file
68
Assets/Cryville.EEW.Unity/Map/RegionView.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity.Map {
|
||||
sealed class RegionView : MonoBehaviour {
|
||||
[SerializeField]
|
||||
SpriteRenderer m_spriteRenderer;
|
||||
|
||||
Color _color;
|
||||
|
||||
bool m_isHovered;
|
||||
public bool IsHovered {
|
||||
get => m_isHovered;
|
||||
set {
|
||||
m_isHovered = value;
|
||||
UpdateColor();
|
||||
}
|
||||
}
|
||||
|
||||
bool m_isSelected;
|
||||
public bool IsSelected {
|
||||
get => m_isSelected;
|
||||
set {
|
||||
m_isSelected = value;
|
||||
UpdateColor();
|
||||
}
|
||||
}
|
||||
|
||||
bool m_isLeaf = true;
|
||||
public bool IsLeaf {
|
||||
get => m_isLeaf;
|
||||
set {
|
||||
m_isLeaf = value;
|
||||
UpdateColor();
|
||||
}
|
||||
}
|
||||
|
||||
string m_id;
|
||||
public string Id {
|
||||
get => m_id;
|
||||
set {
|
||||
m_id = value;
|
||||
unchecked {
|
||||
uint hash = (uint)value.GetHashCode();
|
||||
_color = Color.HSVToRGB(((hash >> 24) ^ ((hash >> 16) & 0xff) ^ ((hash >> 8) & 0xff) ^ (hash & 0xff)) / (float)0xff, 1, 1);
|
||||
}
|
||||
UpdateColor();
|
||||
}
|
||||
}
|
||||
|
||||
public void Init(int x, int y, int z) {
|
||||
float scale = 1f / (1 << z);
|
||||
transform.localScale = new Vector3(scale, scale, 1);
|
||||
transform.localPosition = new Vector3(x * scale, y * scale - 1, -1 - z / 100f);
|
||||
}
|
||||
|
||||
void UpdateColor() {
|
||||
if (!m_isLeaf)
|
||||
_color.a = 0.0f;
|
||||
else if (m_isSelected)
|
||||
_color.a = 0.6f;
|
||||
else if (m_isHovered)
|
||||
_color.a = 0.4f;
|
||||
else
|
||||
_color.a = 0.2f;
|
||||
m_spriteRenderer.color = _color;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Cryville.EEW.Unity/Map/RegionView.cs.meta
Normal file
11
Assets/Cryville.EEW.Unity/Map/RegionView.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c57a0e86eb63b6048ba265e9d98e84f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,5 @@
|
||||
using Cryville.EEW.Colors;
|
||||
using Cryville.EEW.Core;
|
||||
using Cryville.EEW.Core.Colors;
|
||||
using Cryville.EEW.FERegion;
|
||||
using Cryville.EEW.Map;
|
||||
@@ -25,8 +26,23 @@ namespace Cryville.EEW.Unity {
|
||||
public IColorScheme ColorScheme { get; private set; } = new SeverityBasedColorScheme(DefaultSeverityScheme.Instance, DefaultSeverityColorMapping.Instance);
|
||||
public ISubColorScheme BorderColorScheme { get; private set; } = new WrappedColorScheme(new SeverityBasedColorScheme(DefaultSeverityScheme.Instance, DefaultSeverityColorMapping.SecondaryInstance));
|
||||
public ISubColorScheme TextColorScheme { get; private set; } = new DefaultTextColorScheme(Color.White, Color.Black);
|
||||
public ILocationConverter LocationConverter => new FERegionLongConverter(); // TODO TTS
|
||||
public TimeSpan NowcastWarningDelayTolerance => TimeSpan.FromMinutes(60); // TODO TTS
|
||||
public TimeSpan NowcastWarningDelayTolerance { get; private set; } = TimeSpan.FromMinutes(60);
|
||||
|
||||
public CultureInfo RVMCulture { get; private set; } = SharedCultures.CurrentUICulture;
|
||||
readonly int _infoLocationSpecificity = 3;
|
||||
readonly int _ttsLocationSpecificity = 3;
|
||||
readonly LocationNamer _locationNamer = new() { Namer = new FERegionLongNamer() };
|
||||
public bool NameLocation(double lat, double lon, CultureInfo localCulture, ref CultureInfo targetCulture, out string name, out int specificity) {
|
||||
specificity = _ttsLocationSpecificity;
|
||||
return _locationNamer.Name(lat, lon, localCulture, ref targetCulture, out name, ref specificity);
|
||||
}
|
||||
public bool NameLocation(double lat, double lon, CultureInfo localCulture, ref CultureInfo targetCulture, out string name) {
|
||||
int specificity = _infoLocationSpecificity;
|
||||
return _locationNamer.Name(lat, lon, localCulture, ref targetCulture, out name, ref specificity);
|
||||
}
|
||||
|
||||
public IReadOnlyCollection<TTSCultureConfig> TTSCultures { get; private set; }
|
||||
public bool DoIgnoreLanguageVariant { get; private set; }
|
||||
|
||||
public TimeZoneInfo OverrideTimeZone { get; private set; }
|
||||
public bool DoDisplayTimeZone { get; private set; } = true;
|
||||
@@ -101,9 +117,20 @@ namespace Cryville.EEW.Unity {
|
||||
"SREV" => new DefaultTextColorScheme(Color.White, Color.FromArgb(28, 28, 28), 0.555f),
|
||||
_ => new DefaultTextColorScheme(Color.White, Color.Black),
|
||||
};
|
||||
_locationNamer.Namer = config.LocationNamer switch {
|
||||
"FERegionShort" => new FERegionShortNamer(),
|
||||
_ => new FERegionLongNamer(),
|
||||
};
|
||||
if (config.NowcastWarningDelayTolerance is string nowcastWarningDelayTolerance)
|
||||
NowcastWarningDelayTolerance = TimeSpan.Parse(nowcastWarningDelayTolerance, CultureInfo.InvariantCulture);
|
||||
OverrideTimeZone = ParseTimeZone(config.OverrideTimeZone);
|
||||
DoDisplayTimeZone = config.DoDisplayTimeZone;
|
||||
DoSwitchBackToHistory = config.DoSwitchBackToHistory;
|
||||
RVMCulture = config.OverrideDisplayCulture is string rvmCulture
|
||||
? (string.IsNullOrEmpty(rvmCulture) ? SharedCultures.CurrentUICulture : SharedCultures.Get(rvmCulture))
|
||||
: CultureInfo.InvariantCulture;
|
||||
TTSCultures = config.TTSCultures ?? new List<TTSCultureConfig> { new(CultureInfo.InvariantCulture) };
|
||||
DoIgnoreLanguageVariant = config.DoIgnoreLanguageVariant;
|
||||
EventSources = config.EventSources;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity {
|
||||
class SoundPlayer : Core.SoundPlayer {
|
||||
class SoundPlayer : Core.Audio.SoundPlayer {
|
||||
public SoundPlayer() : base(GetEngineList(), AudioUsage.NotificationEvent) { }
|
||||
static List<Type> GetEngineList() => new() {
|
||||
typeof(Audio.Wasapi.MMDeviceEnumeratorWrapper),
|
||||
@@ -13,6 +13,7 @@ namespace Cryville.EEW.Unity {
|
||||
};
|
||||
|
||||
protected override Stream Open(string path) {
|
||||
App.MainLogger.Log(0, "Audio", null, "Opening audio file {0}", path);
|
||||
path = Path.Combine(Application.streamingAssetsPath, "Sounds", path + ".ogg");
|
||||
if (!File.Exists(path)) return null;
|
||||
return new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
|
||||
@@ -1,25 +1,53 @@
|
||||
using SpeechLib;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Cryville.EEW.Unity {
|
||||
class TTSWorker : Core.TTSWorker {
|
||||
public TTSWorker() : base(CreateSoundPlayer()) { }
|
||||
class TTSWorker : Core.Audio.TTSWorker {
|
||||
readonly ISpVoice _voice;
|
||||
|
||||
public TTSWorker() : base(CreateSoundPlayer()) {
|
||||
App.MainLogger.Log(1, "Audio", null, "Initializing TTS worker");
|
||||
try {
|
||||
_voice = new SpVoiceClass();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
static SoundPlayer CreateSoundPlayer() {
|
||||
App.MainLogger.Log(1, "Audio", null, "Creating sound player");
|
||||
try {
|
||||
return new SoundPlayer();
|
||||
}
|
||||
catch (InvalidOperationException) {
|
||||
catch (InvalidOperationException ex) {
|
||||
App.MainLogger.Log(3, "Audio", null, "An error occurred when creating sound player: {0}", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool IsSpeaking() => false;
|
||||
protected override bool IsSpeaking() {
|
||||
if (_voice == null) return false;
|
||||
_voice.GetStatus(out var status, out _);
|
||||
return (status.dwRunningState & (uint)SpeechRunState.SRSEIsSpeaking) != 0;
|
||||
}
|
||||
|
||||
protected override Task Speak(CultureInfo culture, string content, CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
protected override Task Speak(CultureInfo culture, string content, CancellationToken cancellationToken) {
|
||||
if (_voice == null) return Task.CompletedTask;
|
||||
_voice.Speak(
|
||||
string.Format(CultureInfo.InvariantCulture, "<LANG LANGID=\"{0:x}\">{1}</LANG>", culture.LCID, content),
|
||||
(uint)(SpeechVoiceSpeakFlags.SVSFlagsAsync | SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak),
|
||||
out _
|
||||
);
|
||||
App.MainLogger.Log(0, "Audio", null, "TTS ({0}): {1}", culture, content);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override void StopCurrent() { }
|
||||
protected override void StopCurrent() {
|
||||
if (_voice == null) return;
|
||||
App.MainLogger.Log(0, "Audio", null, "TTS stopping current");
|
||||
_voice.Skip("SENTENCE", int.MaxValue, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Cryville.EEW.Unity.UI {
|
||||
child.SetViewModel(e);
|
||||
child.transform.SetParent(m_listView, false);
|
||||
_displayingViews.Add(child);
|
||||
OnDisplayingViewsChanged();
|
||||
|
||||
SwitchTo(_displayingReports.Count - 1);
|
||||
|
||||
@@ -37,6 +38,7 @@ namespace Cryville.EEW.Unity.UI {
|
||||
child.SetParent(null, false);
|
||||
Destroy(child.gameObject);
|
||||
_displayingViews.RemoveAt(index);
|
||||
OnDisplayingViewsChanged();
|
||||
|
||||
if (_displayingReports.Count == 0) {
|
||||
m_currentView.gameObject.SetActive(false);
|
||||
@@ -49,6 +51,14 @@ namespace Cryville.EEW.Unity.UI {
|
||||
|
||||
if (_displayingReports.Count <= 1) m_listView.gameObject.SetActive(false);
|
||||
}
|
||||
void OnDisplayingViewsChanged() {
|
||||
_maxBaseDuration = 1;
|
||||
foreach (var e in _displayingReports) {
|
||||
float duration = GetBaseDuration(e);
|
||||
if (duration > _maxBaseDuration)
|
||||
_maxBaseDuration = duration;
|
||||
}
|
||||
}
|
||||
|
||||
void Awake() {
|
||||
if (Instance != null) {
|
||||
@@ -63,6 +73,7 @@ namespace Cryville.EEW.Unity.UI {
|
||||
|
||||
int _index = -1;
|
||||
float _tickDown;
|
||||
float _maxBaseDuration;
|
||||
void Update() {
|
||||
if (_displayingReports.Count == 0) return;
|
||||
_tickDown -= Time.deltaTime;
|
||||
@@ -77,12 +88,15 @@ namespace Cryville.EEW.Unity.UI {
|
||||
_index = index;
|
||||
var e = _displayingReports[index];
|
||||
m_currentView.SetViewModel(e, true);
|
||||
var keyProp = e.Properties.FirstOrDefault();
|
||||
_displayingViews[_index].SetCurrent(true);
|
||||
_tickDown = MathF.Exp(Math.Max(-1f, keyProp?.Severity ?? -1f) + 1);
|
||||
_tickDown = GetBaseDuration(e) / Math.Min(_maxBaseDuration, 4) * 4;
|
||||
m_currentView.gameObject.SetActive(true);
|
||||
Worker.Instance.SetCurrent(e);
|
||||
}
|
||||
static float GetBaseDuration(ReportViewModel e) {
|
||||
return MathF.Exp(Math.Max(-1f, e.Properties.FirstOrDefault()?.Severity ?? -1f) + 1);
|
||||
}
|
||||
|
||||
public void OnItemClicked(ReportViewModel viewModel) {
|
||||
int index = _displayingReports.IndexOf(viewModel);
|
||||
if (index == -1) return;
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace Cryville.EEW.Unity.UI {
|
||||
_textView = GetComponent<TMP_Text>();
|
||||
}
|
||||
|
||||
StringBuilder _sb = new();
|
||||
char[] _buffer = new char[256];
|
||||
readonly StringBuilder _sb = new();
|
||||
readonly char[] _buffer = new char[256];
|
||||
void Update() {
|
||||
_sb.Clear();
|
||||
_sb.AppendFormat(
|
||||
|
||||
@@ -5,6 +5,8 @@ using Cryville.EEW.CWAOpenData;
|
||||
using Cryville.EEW.CWAOpenData.Model;
|
||||
using Cryville.EEW.CWAOpenData.TTS;
|
||||
using Cryville.EEW.EMSC;
|
||||
using Cryville.EEW.GeoNet;
|
||||
using Cryville.EEW.GeoNet.TTS;
|
||||
using Cryville.EEW.GlobalQuake;
|
||||
using Cryville.EEW.JMAAtom;
|
||||
using Cryville.EEW.JMAAtom.TTS;
|
||||
@@ -58,16 +60,21 @@ namespace Cryville.EEW.Unity {
|
||||
}
|
||||
|
||||
void Start() {
|
||||
App.MainLogger.Log(1, "App", null, "Initializing localized resources manager");
|
||||
LocalizedResources.Init(new LocalizedResourcesManager());
|
||||
RegisterViewModelGenerators(_worker);
|
||||
RegisterTTSMessageGenerators(_worker);
|
||||
BuildWorkers();
|
||||
_worker.RVMGeneratorContext = SharedSettings.Instance;
|
||||
_worker.TTSMessageGeneratorContext = SharedSettings.Instance;
|
||||
_worker.RVMCulture = SharedSettings.Instance.RVMCulture;
|
||||
_worker.SetTTSCultures(SharedSettings.Instance.TTSCultures ?? new TTSCultureConfig[0]);
|
||||
_worker.IgnoreLanguageVariant = SharedSettings.Instance.DoIgnoreLanguageVariant;
|
||||
_ongoingReportManager.Changed += OnOngoingReported;
|
||||
_worker.Reported += OnReported;
|
||||
_grouper.GroupUpdated += OnGroupUpdated;
|
||||
_grouper.GroupRemoved += OnGroupRemoved;
|
||||
App.MainLogger.Log(1, "App", null, "Worker ready");
|
||||
Task.Run(() => GatewayVerify(_cancellationTokenSource.Token)).ContinueWith(task => {
|
||||
if (task.IsFaulted) {
|
||||
OnReported(this, new() { Title = task.Exception.Message });
|
||||
@@ -87,15 +94,19 @@ namespace Cryville.EEW.Unity {
|
||||
_ongoingReportManager.Dispose();
|
||||
}
|
||||
|
||||
static void RegisterViewModelGenerators(CoreWorker worker) {
|
||||
CENCEarthquakeRVMGenerator _cencEarthquakeRVMGenerator;
|
||||
void RegisterViewModelGenerators(CoreWorker worker) {
|
||||
worker.RegisterViewModelGenerator(new BMKGEarthquakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new CENCEarthquakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(_cencEarthquakeRVMGenerator = new CENCEarthquakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new CENCEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new CWAEarthquakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new CWAEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new CWATsunamiRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new EMSCRealTimeEventRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new FujianEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GeoNetQuakeHistoryRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GeoNetQuakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GeoNetStrongRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GlobalQuakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new JMAAtomRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new JMAEEWRVMGenerator());
|
||||
@@ -104,14 +115,18 @@ namespace Cryville.EEW.Unity {
|
||||
worker.RegisterViewModelGenerator(new SichuanEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new VersionRVMGenerator());
|
||||
}
|
||||
static void RegisterTTSMessageGenerators(CoreWorker worker) {
|
||||
CENCEarthquakeTTSMessageGenerator _cencEarthquakeTTSMessageGenerator;
|
||||
void RegisterTTSMessageGenerators(CoreWorker worker) {
|
||||
worker.RegisterTTSMessageGenerator(new BMKGEarthquakeTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new CENCEarthquakeTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(_cencEarthquakeTTSMessageGenerator = new CENCEarthquakeTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new CENCEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new CWAEarthquakeTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new CWAEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new CWATsunamiTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new FujianEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new GeoNetQuakeHistoryTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new GeoNetQuakeTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new GeoNetStrongTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new JMAAtomTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new JMAEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new NOAATTSMessageGenerator());
|
||||
@@ -120,6 +135,7 @@ namespace Cryville.EEW.Unity {
|
||||
|
||||
bool _verified;
|
||||
void BuildWorkers() {
|
||||
App.MainLogger.Log(1, "App", null, "Building workers");
|
||||
#if UNITY_EDITOR
|
||||
_worker.AddWorker(new WolfxWorker(new Uri("ws://localhost:9995/wolfx")));
|
||||
_worker.AddWorker(new JMAAtomWorker(new Uri("http://localhost:9095/eqvol.xml")));
|
||||
@@ -129,30 +145,31 @@ namespace Cryville.EEW.Unity {
|
||||
BMKGOpenDataWorker bmkgWorker = new(new Uri("http://localhost:9095/autogempa.json"));
|
||||
bmkgWorker.SetDataUris(new Uri[] { new("http://localhost:9095/gempadirasakan.json") });
|
||||
_worker.AddWorker(bmkgWorker);
|
||||
_worker.AddWorker(new NOAAAtomWorker(new("http://localhost:9095/PAAQAtom.xml")));
|
||||
_worker.AddWorker(new NOAAAtomWorker(new("http://localhost:9095/PAAQAtom.xml"), forceHttps: false));
|
||||
_worker.AddWorker(new UpdateCheckerWorker(typeof(Worker).Assembly.GetName().Version?.ToString(3) ?? "", "unity"));
|
||||
#else
|
||||
foreach (var source in SharedSettings.Instance.EventSources) {
|
||||
_worker.AddWorker(source switch {
|
||||
BMKGOpenDataEventSourceConfig bmkgOpenData => BuildBMKGOpenDataWorkerUris(new BMKGOpenDataWorker(new("https://data.bmkg.go.id/DataMKG/TEWS/autogempa.json")), bmkgOpenData),
|
||||
BMKGOpenDataEventSourceConfig bmkgOpenData => BuildBMKGOpenDataWorkerUris(new(new("https://data.bmkg.go.id/DataMKG/TEWS/autogempa.json")), bmkgOpenData),
|
||||
CWAOpenDataEventSourceConfig cwaOpenData => cwaOpenData.Subtype switch {
|
||||
"E-A0014-001" => new CWAReportWorker<Tsunami>(new Uri("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0014-001"), cwaOpenData.Token, 1440, 17280),
|
||||
"E-A0015-001" => new CWAReportWorker<Earthquake>(new Uri("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001"), cwaOpenData.Token),
|
||||
"E-A0016-001" => new CWAReportWorker<Earthquake>(new Uri("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0016-001"), cwaOpenData.Token),
|
||||
"E-A0014-001" => new CWAReportWorker<Tsunami>(new("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0014-001"), cwaOpenData.Token, 1440, 17280),
|
||||
"E-A0015-001" => new CWAReportWorker<Earthquake>(new("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001"), cwaOpenData.Token),
|
||||
"E-A0016-001" => new CWAReportWorker<Earthquake>(new("https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0016-001"), cwaOpenData.Token),
|
||||
_ => throw new InvalidOperationException("Unknown CWA open data sub-type."),
|
||||
},
|
||||
EMSCRealTimeEventSourceConfig => new EMSCRealTimeWorker(new("wss://www.seismicportal.eu/standing_order/websocket")),
|
||||
GeoNetEventSourceConfig geoNet => BuildGeoNetWorker(new(new("https://api.geonet.org.nz/quake"), new("https://api.geonet.org.nz/quake/history/index"), new("https://api.geonet.org.nz/intensity/strong/processed/index")), geoNet),
|
||||
GlobalQuakeServer15EventSourceConfig gq => new GlobalQuakeWorker15(gq.Host, gq.Port),
|
||||
GlobalQuakeServerEventSourceConfig gq => new GlobalQuakeWorker(gq.Host, gq.Port),
|
||||
JMAAtomEventSourceConfig jmaAtom => BuildJMAAtomWorkerFilter(new JMAAtomWorker(new("https://www.data.jma.go.jp/developer/xml/feed/eqvol.xml")), jmaAtom),
|
||||
JMAAtomEventSourceConfig jmaAtom => BuildJMAAtomWorkerFilter(new(new("https://www.data.jma.go.jp/developer/xml/feed/eqvol.xml")), jmaAtom),
|
||||
NOAAEventSourceConfig noaaAtom => noaaAtom.Subtype switch {
|
||||
"PAAQ" => new NOAAAtomWorker(new("https://www.tsunami.gov/events/xml/PAAQAtom.xml"), new("https://www.tsunami.gov/"), new("/php/esri.php?e=t", UriKind.Relative), "PAAQ"),
|
||||
"PHEB" => new NOAAAtomWorker(new("https://www.tsunami.gov/events/xml/PHEBAtom.xml"), new("https://www.tsunami.gov/"), new("/php/esri.php?e=t", UriKind.Relative), "PHEB"),
|
||||
_ => throw new InvalidOperationException("Unknown NOAA sub-type."),
|
||||
},
|
||||
UpdateCheckerEventSourceConfig => new UpdateCheckerWorker(typeof(Worker).Assembly.GetName().Version?.ToString(3) ?? "", "unity"),
|
||||
USGSQuakeMLEventSourceConfig usgsQuakeML => BuildUSGSQuakeMLWorkerUri(new USGSQuakeMLWorker(new Uri("https://earthquake.usgs.gov/earthquakes/feed/v1.0/quakeml.php")), usgsQuakeML),
|
||||
WolfxEventSourceConfig wolfx => BuildWolfxWorkerFilter(new WolfxWorker(new Uri("wss://ws-api.wolfx.jp/all_eew")), wolfx),
|
||||
USGSQuakeMLEventSourceConfig usgsQuakeML => BuildUSGSQuakeMLWorkerUri(new USGSQuakeMLWorker(new("https://earthquake.usgs.gov/earthquakes/feed/v1.0/quakeml.php")), usgsQuakeML),
|
||||
WolfxEventSourceConfig wolfx => BuildWolfxWorkerFilter(new WolfxWorker(new("wss://ws-api.wolfx.jp/all_eew")), wolfx),
|
||||
_ => throw new InvalidOperationException("Unknown event source type."),
|
||||
});
|
||||
}
|
||||
@@ -163,7 +180,7 @@ namespace Cryville.EEW.Unity {
|
||||
worker.IsFilterWhitelist = config.IsFilterWhitelist;
|
||||
return worker;
|
||||
}
|
||||
static WolfxWorker BuildWolfxWorkerFilter(WolfxWorker worker, WolfxEventSourceConfig config) {
|
||||
WolfxWorker BuildWolfxWorkerFilter(WolfxWorker worker, WolfxEventSourceConfig config) {
|
||||
if (config.Filter != null) worker.SetFilter(config.Filter.Select(i => i switch {
|
||||
"cenc_eew" => typeof(CENCEEW),
|
||||
"cenc_eqlist" => typeof(WolfxEarthquakeList<CENCEarthquake>),
|
||||
@@ -174,12 +191,23 @@ namespace Cryville.EEW.Unity {
|
||||
_ => throw new InvalidOperationException("Unknown Wolfx event type."),
|
||||
}));
|
||||
worker.IsFilterWhitelist = config.IsFilterWhitelist;
|
||||
|
||||
_cencEarthquakeRVMGenerator.UseRawLocationName
|
||||
= _cencEarthquakeTTSMessageGenerator.UseRawLocationName
|
||||
= config.UseRawCENCLocationName;
|
||||
|
||||
return worker;
|
||||
}
|
||||
static BMKGOpenDataWorker BuildBMKGOpenDataWorkerUris(BMKGOpenDataWorker worker, BMKGOpenDataEventSourceConfig config) {
|
||||
worker.SetDataUris(config.Subtypes.Select(i => new Uri(string.Format(CultureInfo.InvariantCulture, "https://data.bmkg.go.id/DataMKG/TEWS/{0}.json", i))));
|
||||
return worker;
|
||||
}
|
||||
static GeoNetWorker BuildGeoNetWorker(GeoNetWorker worker, GeoNetEventSourceConfig pref) {
|
||||
worker.MinimumMMI = pref.MinimumMMI;
|
||||
worker.DoGetFullHistory = pref.DoGetFullHistory;
|
||||
worker.DoGetStrongMotionInfo = pref.DoGetStrongMotionInfo;
|
||||
return worker;
|
||||
}
|
||||
static USGSQuakeMLWorker BuildUSGSQuakeMLWorkerUri(USGSQuakeMLWorker worker, USGSQuakeMLEventSourceConfig config) {
|
||||
worker.SetFeedRelativeUri(new(string.Format(CultureInfo.InvariantCulture, "/earthquakes/feed/v1.0/summary/{0}.quakeml", config.Subtype), UriKind.Relative));
|
||||
return worker;
|
||||
@@ -190,7 +218,7 @@ namespace Cryville.EEW.Unity {
|
||||
ReportViewModel _latestHistoryReport;
|
||||
void OnReported(object sender, ReportViewModel e) {
|
||||
if (e.Model is Exception && e.Model is not SourceWorkerNetworkException)
|
||||
Debug.LogError(e);
|
||||
App.MainLogger.Log(4, "Map", null, "Received an error from {0}: {1}", sender.GetType(), e.Model);
|
||||
_grouper.Report(e);
|
||||
_ongoingReportManager.Report(e);
|
||||
_uiActionQueue.Enqueue(() => {
|
||||
|
||||
Binary file not shown.
BIN
Assets/Plugins/Cryville.Common.Logging.dll
Normal file
BIN
Assets/Plugins/Cryville.Common.Logging.dll
Normal file
Binary file not shown.
33
Assets/Plugins/Cryville.Common.Logging.dll.meta
Normal file
33
Assets/Plugins/Cryville.Common.Logging.dll.meta
Normal file
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7aa0c56ccfdaf9443b58f26bf40eed01
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
185
Assets/Plugins/Cryville.Common.Logging.xml
Normal file
185
Assets/Plugins/Cryville.Common.Logging.xml
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>Cryville.Common.Logging</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Cryville.Common.Logging.Logger">
|
||||
<summary>
|
||||
A logger.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.AddListener(Cryville.Common.Logging.LoggerListener)">
|
||||
<summary>
|
||||
Attaches a listener to the logger.
|
||||
</summary>
|
||||
<param name="listener">The logger listener.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.RemoveListener(Cryville.Common.Logging.LoggerListener)">
|
||||
<summary>
|
||||
Detaches a listener from the logger.
|
||||
</summary>
|
||||
<param name="listener">The logger listener.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.String,System.Object[])">
|
||||
<summary>
|
||||
Logs to the logger.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="format">The format string.</param>
|
||||
<param name="args">The arguments for formatting.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.IFormatProvider,System.String,System.Object[])">
|
||||
<summary>
|
||||
Logs to the logger.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="provider">The format provider.</param>
|
||||
<param name="format">The format string.</param>
|
||||
<param name="args">The arguments for formatting.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.String)">
|
||||
<summary>
|
||||
Logs to the logger.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">The message.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.Char[])">
|
||||
<summary>
|
||||
Logs to the logger.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">An array of <see cref="T:System.Char" /> containing the message.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.Char[],System.Int32,System.Int32)">
|
||||
<summary>
|
||||
Logs to the logger.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">An array of <see cref="T:System.Char" /> containing the message.</param>
|
||||
<param name="index">A zero-based index of the first character of the message within <paramref name="message" />.</param>
|
||||
<param name="length">The length of the message.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.Logger.Log(System.Int32,System.String,System.Char*,System.Int32)">
|
||||
<summary>
|
||||
Logs to the logger.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">A pointer to the first character of the message.</param>
|
||||
<param name="length">The length of the message.</param>
|
||||
</member>
|
||||
<member name="T:Cryville.Common.Logging.LoggerListener">
|
||||
<summary>
|
||||
A logger listener.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.LoggerListener.Dispose(System.Boolean)">
|
||||
<summary>
|
||||
Closes the logger listener and cleans up all the resources.
|
||||
</summary>
|
||||
<param name="disposing">Whether to clean up managed resources.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.LoggerListener.Dispose">
|
||||
<summary>
|
||||
Closes the logger listener.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.LoggerListener.OnLog(System.Int32,System.String,System.String)">
|
||||
<summary>
|
||||
Handles an incoming log.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">The message.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.LoggerListener.OnLog(System.Int32,System.String,System.Char[],System.Int32,System.Int32)">
|
||||
<summary>
|
||||
Handles an incoming log.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">An array of <see cref="T:System.Char" /> containing the message.</param>
|
||||
<param name="index">A zero-based index of the first character of the message within <paramref name="message" />.</param>
|
||||
<param name="length">The length of the message.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.LoggerListener.OnLog(System.Int32,System.String,System.Char*,System.Int32)">
|
||||
<summary>
|
||||
Handles an incoming log.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">A pointer to the first character of the message.</param>
|
||||
<param name="length">The length of the message.</param>
|
||||
</member>
|
||||
<member name="T:Cryville.Common.Logging.InstantLoggerListener">
|
||||
<summary>
|
||||
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that calls a callback function on log.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="E:Cryville.Common.Logging.InstantLoggerListener.Log">
|
||||
<summary>
|
||||
Occurs when a log is logged to the logger.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.InstantLoggerListener.OnLog(System.Int32,System.String,System.String)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:Cryville.Common.Logging.BufferedLoggerListener">
|
||||
<summary>
|
||||
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that buffers the logs for enumeration.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.BufferedLoggerListener.OnLog(System.Int32,System.String,System.String)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.BufferedLoggerListener.Enumerate(Cryville.Common.Logging.LogHandler)">
|
||||
<summary>
|
||||
Enumerates the buffered logs.
|
||||
</summary>
|
||||
<param name="callback">The callback function to receive the logs.</param>
|
||||
</member>
|
||||
<member name="T:Cryville.Common.Logging.StreamLoggerListener">
|
||||
<summary>
|
||||
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that writes logs into a stream.
|
||||
</summary>
|
||||
<param name="stream">The stream.</param>
|
||||
<param name="encoding">The encoding.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.StreamLoggerListener.#ctor(System.IO.Stream,System.Text.Encoding)">
|
||||
<summary>
|
||||
A <see cref="T:Cryville.Common.Logging.LoggerListener" /> that writes logs into a stream.
|
||||
</summary>
|
||||
<param name="stream">The stream.</param>
|
||||
<param name="encoding">The encoding.</param>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.StreamLoggerListener.#ctor(System.IO.Stream)">
|
||||
<summary>
|
||||
Creates an instance of the <see cref="T:Cryville.Common.Logging.StreamLoggerListener" /> class.
|
||||
</summary>
|
||||
<param name="stream">The stream.</param>
|
||||
</member>
|
||||
<member name="P:Cryville.Common.Logging.StreamLoggerListener.AutoFlush">
|
||||
<summary>
|
||||
Whether to flush the stream every time a log is written.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Cryville.Common.Logging.StreamLoggerListener.OnLog(System.Int32,System.String,System.String)">
|
||||
<inheritdoc />
|
||||
</member>
|
||||
<member name="T:Cryville.Common.Logging.LogHandler">
|
||||
<summary>
|
||||
Represents the method that will handle a log.
|
||||
</summary>
|
||||
<param name="level">The severity level.</param>
|
||||
<param name="category">The category.</param>
|
||||
<param name="message">The message.</param>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
7
Assets/Plugins/Cryville.Common.Logging.xml.meta
Normal file
7
Assets/Plugins/Cryville.Common.Logging.xml.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72ded0675457e0348809193a9c1092b5
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Assets/Plugins/Cryville.EEW.CENCStrongGroundMotion.Map.dll
Normal file
BIN
Assets/Plugins/Cryville.EEW.CENCStrongGroundMotion.Map.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user