Compare commits
27 Commits
0.0.5
...
a131ed10f9
| Author | SHA1 | Date | |
|---|---|---|---|
| a131ed10f9 | |||
| ad0797585b | |||
| 304ab10491 | |||
| 130f880d5d | |||
| cf6d76d4c0 | |||
| 4628db1d49 | |||
| 1eeaa4f728 | |||
| 309ee12b93 | |||
| 59335c9102 | |||
| e182ebd53f | |||
| 65b158f387 | |||
| 9f844f2744 | |||
| ae917a8e51 | |||
| 44a72d1a8f | |||
| 4758b65159 | |||
| de3196d38a | |||
| c2311fb7a4 | |||
| 7562be2c09 | |||
| a8f46113d4 | |||
| 99736f114d | |||
| 4d1a008106 | |||
| 9318cbca4e | |||
| a162f345c4 | |||
| 1af4afc7c6 | |||
| a3efe939e8 | |||
| 5daee1a01a | |||
| 2d5d305528 |
@@ -2,7 +2,7 @@
|
||||
"name": "Cryville.Common",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:da293eebbcb9a4947a212534c52d1a32"
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -23,6 +23,12 @@ namespace Cryville.Common.Unity.UI {
|
||||
[SerializeField]
|
||||
protected bool m_ChildScaleHeight;
|
||||
|
||||
[SerializeField]
|
||||
protected bool m_ChildOverflowWidth;
|
||||
|
||||
[SerializeField]
|
||||
protected bool m_ChildOverflowHeight;
|
||||
|
||||
public override void CalculateLayoutInputHorizontal() {
|
||||
base.CalculateLayoutInputHorizontal();
|
||||
CalcAlongAxis(0);
|
||||
@@ -60,9 +66,10 @@ namespace Cryville.Common.Unity.UI {
|
||||
float size = rectTransform.rect.size[axis];
|
||||
bool controlSize = (axis == 0) ? m_ChildControlWidth : m_ChildControlHeight;
|
||||
bool useScale = (axis == 0) ? m_ChildScaleWidth : m_ChildScaleHeight;
|
||||
bool overflow = (axis == 0) ? m_ChildOverflowWidth : m_ChildOverflowHeight;
|
||||
bool childForceExpandSize = (axis == 0) ? m_ChildForceExpandWidth : m_ChildForceExpandHeight;
|
||||
float alignmentOnAxis = GetAlignmentOnAxis(axis);
|
||||
float innerSize = size - ((axis == 0) ? padding.horizontal : padding.vertical);
|
||||
float innerSize = overflow ? float.PositiveInfinity : (size - ((axis == 0) ? padding.horizontal : padding.vertical));
|
||||
RectTransform child = rectChildren[0];
|
||||
GetChildSizes(child, axis, controlSize, childForceExpandSize, out var min2, out var preferred2, out var flexible2);
|
||||
float scaleFactor2 = useScale ? child.localScale[axis] : 1f;
|
||||
|
||||
@@ -6,8 +6,9 @@ using System.Globalization;
|
||||
using System.Reflection;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TextCore;
|
||||
using UnityEngine.TextCore.LowLevel;
|
||||
using UnityEngine.TextCore.Text;
|
||||
using AtlasPopulationMode = TMPro.AtlasPopulationMode;
|
||||
|
||||
namespace Cryville.Common.Unity.UI {
|
||||
[RequireComponent(typeof(TMP_Text))]
|
||||
@@ -16,7 +17,7 @@ namespace Cryville.Common.Unity.UI {
|
||||
public static FontMatcher FontMatcher;
|
||||
public static int MaxFallbackCount = 4;
|
||||
|
||||
static readonly Dictionary<CultureInfo, FontAsset> _cachedFonts = new();
|
||||
static readonly Dictionary<CultureInfo, TMP_FontAsset> _cachedFonts = new();
|
||||
|
||||
[SerializeField]
|
||||
Shader m_shader;
|
||||
@@ -46,7 +47,7 @@ namespace Cryville.Common.Unity.UI {
|
||||
if (MaxFallbackCount <= 0) break;
|
||||
}
|
||||
else {
|
||||
font.fallbackFontAssetTable ??= new List<FontAsset>();
|
||||
font.fallbackFontAssetTable ??= new List<TMP_FontAsset>();
|
||||
font.fallbackFontAssetTable.Add(ifont);
|
||||
if (font.fallbackFontAssetTable.Count >= MaxFallbackCount) break;
|
||||
}
|
||||
@@ -58,23 +59,93 @@ namespace Cryville.Common.Unity.UI {
|
||||
Text.font = font;
|
||||
}
|
||||
|
||||
static MethodInfo _methodCreateFontAsset;
|
||||
static readonly object[] _paramsCreateFontAsset = new object[] { null, null, 90, 9, GlyphRenderMode.SDFAA, 1024, 1024, Type.Missing, Type.Missing };
|
||||
static FontAsset CreateFontAsset(string path, int index) {
|
||||
if (_methodCreateFontAsset == null) {
|
||||
_methodCreateFontAsset = typeof(FontAsset).GetMethod(
|
||||
"CreateFontAsset", BindingFlags.Static | BindingFlags.NonPublic, null,
|
||||
new Type[] {
|
||||
typeof(string), typeof(int), typeof(int), typeof(int),
|
||||
typeof(GlyphRenderMode), typeof(int), typeof(int),
|
||||
typeof(AtlasPopulationMode), typeof(bool)
|
||||
},
|
||||
null
|
||||
);
|
||||
static TMP_FontAsset CreateFontAsset(string path, int index) => CreateFontAsset(path, index, 90, 9, GlyphRenderMode.SDFAA, 1024, 1024, AtlasPopulationMode.Dynamic);
|
||||
|
||||
static readonly Lazy<FieldInfo> _f_m_Version = new(() => typeof(TMP_FontAsset).GetField("m_Version", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
static readonly Lazy<PropertyInfo> _p_atlasWidth = new(() => typeof(TMP_FontAsset).GetProperty("atlasWidth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
static readonly Lazy<PropertyInfo> _p_atlasHeight = new(() => typeof(TMP_FontAsset).GetProperty("atlasHeight", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
static readonly Lazy<PropertyInfo> _p_atlasPadding = new(() => typeof(TMP_FontAsset).GetProperty("atlasPadding", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
static readonly Lazy<PropertyInfo> _p_atlasRenderMode = new(() => typeof(TMP_FontAsset).GetProperty("atlasRenderMode", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
static readonly Lazy<PropertyInfo> _p_freeGlyphRects = new(() => typeof(TMP_FontAsset).GetProperty("freeGlyphRects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
static readonly Lazy<PropertyInfo> _p_usedGlyphRects = new(() => typeof(TMP_FontAsset).GetProperty("usedGlyphRects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
|
||||
static readonly Lazy<PropertyInfo> _p_ShaderRef_MobileBitmap = new(() => typeof(ShaderUtilities).GetProperty("ShaderRef_MobileBitmap", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
static readonly Lazy<PropertyInfo> _p_ShaderRef_MobileSDF = new(() => typeof(ShaderUtilities).GetProperty("ShaderRef_MobileSDF", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
|
||||
public static TMP_FontAsset CreateFontAsset(string path, int faceIndex, int samplingPointSize, int atlasPadding, GlyphRenderMode renderMode, int atlasWidth, int atlasHeight, AtlasPopulationMode atlasPopulationMode = AtlasPopulationMode.Dynamic, bool enableMultiAtlasSupport = true) {
|
||||
// Initialize FontEngine
|
||||
FontEngine.InitializeFontEngine();
|
||||
|
||||
// Load Font Face
|
||||
if (FontEngine.LoadFontFace(path, samplingPointSize, faceIndex) != FontEngineError.Success) {
|
||||
Debug.LogWarning("Unable to load font face at path " + path);
|
||||
return null;
|
||||
}
|
||||
_paramsCreateFontAsset[0] = path;
|
||||
_paramsCreateFontAsset[1] = index;
|
||||
return (FontAsset)_methodCreateFontAsset.Invoke(null, _paramsCreateFontAsset);
|
||||
|
||||
// Create new font asset
|
||||
TMP_FontAsset fontAsset = ScriptableObject.CreateInstance<TMP_FontAsset>();
|
||||
|
||||
_f_m_Version.Value.SetValue(fontAsset, "1.1.0");
|
||||
fontAsset.faceInfo = FontEngine.GetFaceInfo();
|
||||
|
||||
fontAsset.atlasPopulationMode = atlasPopulationMode;
|
||||
|
||||
_p_atlasWidth.Value.SetValue(fontAsset, atlasWidth);
|
||||
_p_atlasHeight.Value.SetValue(fontAsset, atlasHeight);
|
||||
_p_atlasPadding.Value.SetValue(fontAsset, atlasPadding);
|
||||
_p_atlasRenderMode.Value.SetValue(fontAsset, renderMode);
|
||||
|
||||
// Initialize array for the font atlas textures.
|
||||
fontAsset.atlasTextures = new Texture2D[1];
|
||||
|
||||
// Create and add font atlas texture.
|
||||
var texture = new Texture2D(0, 0, TextureFormat.Alpha8, false);
|
||||
fontAsset.atlasTextures[0] = texture;
|
||||
|
||||
fontAsset.isMultiAtlasTexturesEnabled = enableMultiAtlasSupport;
|
||||
|
||||
// Add free rectangle of the size of the texture.
|
||||
int packingModifier;
|
||||
if (((int)renderMode & 0x10) != 0) {
|
||||
packingModifier = 0;
|
||||
|
||||
// Optimize by adding static ref to shader.
|
||||
var tmp_material = new Material((Shader)_p_ShaderRef_MobileBitmap.Value.GetValue(null));
|
||||
|
||||
//tmp_material.name = texture.name + " Material";
|
||||
tmp_material.SetTexture(ShaderUtilities.ID_MainTex, texture);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureWidth, atlasWidth);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureHeight, atlasHeight);
|
||||
|
||||
fontAsset.material = tmp_material;
|
||||
}
|
||||
else {
|
||||
packingModifier = 1;
|
||||
|
||||
// Optimize by adding static ref to shader.
|
||||
var tmp_material = new Material((Shader)_p_ShaderRef_MobileSDF.Value.GetValue(null));
|
||||
|
||||
//tmp_material.name = texture.name + " Material";
|
||||
tmp_material.SetTexture(ShaderUtilities.ID_MainTex, texture);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureWidth, atlasWidth);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_TextureHeight, atlasHeight);
|
||||
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_GradientScale, atlasPadding + packingModifier);
|
||||
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_WeightNormal, fontAsset.normalStyle);
|
||||
tmp_material.SetFloat(ShaderUtilities.ID_WeightBold, fontAsset.boldStyle);
|
||||
|
||||
fontAsset.material = tmp_material;
|
||||
}
|
||||
|
||||
_p_freeGlyphRects.Value.SetValue(fontAsset, new List<GlyphRect>(8) { new(0, 0, atlasWidth - packingModifier, atlasHeight - packingModifier) });
|
||||
_p_usedGlyphRects.Value.SetValue(fontAsset, new List<GlyphRect>(8));
|
||||
|
||||
// TODO: Consider adding support for extracting glyph positioning data
|
||||
|
||||
fontAsset.ReadFontAssetDefinition();
|
||||
|
||||
return fontAsset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
executionOrder: -95
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
|
||||
@@ -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.5")]
|
||||
[assembly: AssemblyVersion("0.0.10")]
|
||||
|
||||
@@ -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,12 +12,18 @@ namespace Cryville.EEW.Unity {
|
||||
float SeverityColorMappingLuminanceMultiplier,
|
||||
bool UseContinuousColor,
|
||||
string ColorScheme,
|
||||
float HillshadeLayerOpacity,
|
||||
string LocationNamer,
|
||||
|
||||
string OverrideTimeZone,
|
||||
bool DoDisplayTimeZone,
|
||||
bool DoSwitchBackToHistory,
|
||||
|
||||
string NowcastWarningDelayTolerance,
|
||||
|
||||
string OverrideDisplayCulture,
|
||||
IReadOnlyCollection<TTSCultureConfig> TTSCultures,
|
||||
bool DoIgnoreLanguageVariant,
|
||||
|
||||
IReadOnlyCollection<EventSourceConfig> EventSources
|
||||
) {
|
||||
@@ -22,12 +32,18 @@ namespace Cryville.EEW.Unity {
|
||||
1f,
|
||||
false,
|
||||
"Default",
|
||||
1,
|
||||
"FERegionLong",
|
||||
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
|
||||
"1:00:00",
|
||||
|
||||
"",
|
||||
new List<TTSCultureConfig> { new(SharedCultures.CurrentUICulture) },
|
||||
true,
|
||||
|
||||
new List<EventSourceConfig> {
|
||||
new JMAAtomEventSourceConfig(Array.Empty<string>()),
|
||||
@@ -41,26 +57,44 @@ namespace Cryville.EEW.Unity {
|
||||
[JsonDerivedType(typeof(BMKGOpenDataEventSourceConfig), "BMKGOpenData")]
|
||||
[JsonDerivedType(typeof(CWAOpenDataEventSourceConfig), "CWAOpenData")]
|
||||
[JsonDerivedType(typeof(EMSCRealTimeEventSourceConfig), "EMSCRealTime")]
|
||||
[JsonDerivedType(typeof(FANStudioEventSourceConfig), "FANStudio")]
|
||||
[JsonDerivedType(typeof(GeoNetEventSourceConfig), "GeoNet")]
|
||||
[JsonDerivedType(typeof(GlobalQuakeServerEventSourceConfig), "GlobalQuakeServer")]
|
||||
[JsonDerivedType(typeof(GlobalQuakeServer15EventSourceConfig), "GlobalQuakeServer15")]
|
||||
[JsonDerivedType(typeof(JMAAtomEventSourceConfig), "JMAAtom")]
|
||||
[JsonDerivedType(typeof(NOAAEventSourceConfig), "NOAA")]
|
||||
[JsonDerivedType(typeof(UpdateCheckerEventSourceConfig), "UpdateChecker")]
|
||||
[JsonDerivedType(typeof(USGSQuakeMLEventSourceConfig), "USGSQuakeML")]
|
||||
[JsonDerivedType(typeof(USGSEventSourceConfig), "USGSQuakeML")]
|
||||
[JsonDerivedType(typeof(WolfxEventSourceConfig), "Wolfx")]
|
||||
abstract record EventSourceConfig();
|
||||
record BMKGOpenDataEventSourceConfig([property: JsonRequired] string[] Subtypes) : EventSourceConfig;
|
||||
record CWAOpenDataEventSourceConfig([property: JsonRequired] string Subtype, [property: JsonRequired] string Token) : EventSourceConfig;
|
||||
record EMSCRealTimeEventSourceConfig() : EventSourceConfig;
|
||||
record FANStudioEventSourceConfig([property: JsonRequired] string Subtype) : 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 USGSEventSourceConfig([property: JsonRequired] string Subtype, bool UseGeoJSONFeeds, string[] Products) : 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,8 +3,9 @@
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:b92f9c7ac10b1c04e86fc48210f62ab1",
|
||||
"GUID:1e0937e40dadba24a97b7342c4559580",
|
||||
"GUID:e5b7e7f40a80a814ba706299d68f9213",
|
||||
"GUID:da293eebbcb9a4947a212534c52d1a32"
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Cryville.EEW.Core.Map;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using UnityEngine;
|
||||
@@ -10,12 +11,16 @@ namespace Cryville.EEW.Unity.Map {
|
||||
[SerializeField]
|
||||
Transform m_layerTile;
|
||||
[SerializeField]
|
||||
Transform m_layerTileHillshade;
|
||||
[SerializeField]
|
||||
MapElementManager m_layerElement;
|
||||
[SerializeField]
|
||||
MapElementManager m_layerElementSub;
|
||||
[SerializeField]
|
||||
GameObject m_prefabTile;
|
||||
[SerializeField]
|
||||
GameObject m_prefabTileHillshade;
|
||||
[SerializeField]
|
||||
GameObject m_prefabBitmapHolder;
|
||||
[SerializeField]
|
||||
int m_maxMapTileZoom = 10;
|
||||
@@ -23,6 +28,7 @@ namespace Cryville.EEW.Unity.Map {
|
||||
bool m_isEditor;
|
||||
|
||||
MapTileCacheManager _tiles;
|
||||
MapTileCacheManager _tilesHillshade;
|
||||
float _elementLayerZ;
|
||||
|
||||
void Start() {
|
||||
@@ -33,12 +39,23 @@ namespace Cryville.EEW.Unity.Map {
|
||||
_tiles.PrefabTile = m_prefabTile;
|
||||
_tiles.PrefabBitmapHolder = m_prefabBitmapHolder;
|
||||
_tiles.CacheDir = Application.temporaryCachePath;
|
||||
if (m_layerTileHillshade) {
|
||||
m_prefabTileHillshade.GetComponent<SpriteRenderer>().sharedMaterial.color = new UnityEngine.Color(1, 1, 1, SharedSettings.Instance.HillshadeLayerOpacity);
|
||||
_tilesHillshade = new HillshadeMapTileCacheManager {
|
||||
ExtraCachedZoomLevel = 20,
|
||||
Parent = m_layerTileHillshade,
|
||||
PrefabTile = m_prefabTileHillshade,
|
||||
PrefabBitmapHolder = m_prefabBitmapHolder,
|
||||
CacheDir = Application.temporaryCachePath,
|
||||
};
|
||||
}
|
||||
_camera.orthographicSize = 0.5f / MathF.Max(1, (float)_camera.pixelWidth / _camera.pixelHeight);
|
||||
if (m_layerElement != null) _elementLayerZ = m_layerElement.transform.position.z;
|
||||
_mapElementUpdated = true;
|
||||
}
|
||||
void OnDestroy() {
|
||||
_tiles.Dispose();
|
||||
_tilesHillshade?.Dispose();
|
||||
}
|
||||
|
||||
float Scale {
|
||||
@@ -104,10 +121,10 @@ namespace Cryville.EEW.Unity.Map {
|
||||
var bounds = new Bounds((Vector2)transform.position, new Vector2(w, h));
|
||||
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)
|
||||
);
|
||||
var a = new MapTileIndex(Mathf.FloorToInt(bounds.min.x * zoomScale), Mathf.FloorToInt(-bounds.max.y * zoomScale), zoom);
|
||||
var b = new MapTileIndex(Mathf.CeilToInt(bounds.max.x * zoomScale), Mathf.CeilToInt(-bounds.min.y * zoomScale), zoom);
|
||||
_tiles.MoveTo(a, b);
|
||||
_tilesHillshade?.MoveTo(a, b);
|
||||
|
||||
if (m_layerElement != null) {
|
||||
m_layerElement.Scale = h;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
using Cryville.EEW.Core.Map;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity.Map {
|
||||
sealed class HillshadeMapTileCacheManager : MapTileCacheManager {
|
||||
protected override MapTileBitmapHolder CreateBitmapHolder(MapTileIndex index) => new(
|
||||
index,
|
||||
GameObject.Instantiate(PrefabBitmapHolder, Parent, false),
|
||||
new($"https://services.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer/tile/{index.Z}/{index.NY}/{index.NX}.png")
|
||||
);
|
||||
|
||||
protected override string GetCacheFilePath(MapTileIndex index) => Path.Combine(CacheDir, $"map_hillshade/{index.Z}/{index.NX}/{index.NY}");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e8aa96a139a7414cb4d2031a22588db
|
||||
guid: d5fed9b884a4ff54f837aa0f2265ad36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -2,12 +2,15 @@ using Cryville.EEW.BMKGOpenData.Map;
|
||||
using Cryville.EEW.Core;
|
||||
using Cryville.EEW.CWAOpenData.Map;
|
||||
using Cryville.EEW.EMSC.Map;
|
||||
using Cryville.EEW.FANStudio.Map;
|
||||
using Cryville.EEW.GeoNet.Map;
|
||||
using Cryville.EEW.GlobalQuake.Map;
|
||||
using Cryville.EEW.JMAAtom.Map;
|
||||
using Cryville.EEW.Map;
|
||||
using Cryville.EEW.NOAA.Map;
|
||||
using Cryville.EEW.QuakeML.Map;
|
||||
using Cryville.EEW.Report;
|
||||
using Cryville.EEW.USGS.Map;
|
||||
using Cryville.EEW.Wolfx.Map;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
@@ -128,19 +131,27 @@ namespace Cryville.EEW.Unity.Map {
|
||||
|
||||
readonly ContextedGeneratorManager<IMapGeneratorContext, MapElement> _gen = new(new IContextedGenerator<IMapGeneratorContext, MapElement>[] {
|
||||
new BMKGEarthquakeMapGenerator(),
|
||||
new CEAEEWMapGenerator(),
|
||||
new CENCEarthquakeMapGenerator(),
|
||||
new CENCEEWMapGenerator(),
|
||||
new CWAEarthquakeMapGenerator(),
|
||||
new CWAEEWMapGenerator(),
|
||||
new CWATsunamiMapGenerator(),
|
||||
new EMSCRealTimeEventMapGenerator(),
|
||||
new FujianEEWMapGenerator(),
|
||||
new FANStudio.Map.FujianEEWMapGenerator(),
|
||||
new Wolfx.Map.FujianEEWMapGenerator(),
|
||||
new GeoNetQuakeHistoryMapGenerator(),
|
||||
new GeoNetQuakeMapGenerator(),
|
||||
new GeoNetStrongMapGenerator(),
|
||||
new GlobalQuakeMapViewGenerator(),
|
||||
new ICLEEWMapGenerator(),
|
||||
new JMAAtomMapGenerator(),
|
||||
new JMAEEWMapGenerator(),
|
||||
new NOAAMapGenerator(),
|
||||
new FANStudio.Map.SichuanEEWMapGenerator(),
|
||||
new Wolfx.Map.SichuanEEWMapGenerator(),
|
||||
new QuakeMLEventMapGenerator(),
|
||||
new SichuanEEWMapGenerator(),
|
||||
new USGSContoursMapGenerator(),
|
||||
});
|
||||
public UnityMapElement Build(object e, out CultureInfo culture, out int order) {
|
||||
culture = CultureInfo.InvariantCulture;
|
||||
|
||||
@@ -19,10 +19,12 @@ namespace Cryville.EEW.Unity.Map {
|
||||
float z = 1 << index.Z;
|
||||
transform.localPosition = new(index.X / z, -(index.Y + 1) / z, -index.Z / 100f);
|
||||
transform.localScale = new Vector3(1 / z, 1 / z, 1);
|
||||
_idView.gameObject.SetActive(true);
|
||||
byte e = SharedSettings.Instance.IdBytes[((index.X << 2) + index.Y) & 0x1f];
|
||||
int ex = e >> 4, ey = e & 0xf;
|
||||
_idView.localPosition = new(ex / 16f, 1 - ey / 16f, -1 / 200f);
|
||||
if (_idView) {
|
||||
_idView.gameObject.SetActive(true);
|
||||
byte e = SharedSettings.Instance.IdBytes[((index.X << 2) + index.Y) & 0x1f];
|
||||
int ex = e >> 4, ey = e & 0xf;
|
||||
_idView.localPosition = new(ex / 16f, 1 - ey / 16f, -1 / 200f);
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(Sprite sprite) {
|
||||
@@ -40,5 +42,9 @@ namespace Cryville.EEW.Unity.Map {
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetVisible(bool v) {
|
||||
_renderer.enabled = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Cryville.EEW.Unity.Map {
|
||||
|
||||
public MapTileBitmapHolder(MapTileIndex index, GameObject gameObject, Uri uri) : base(index) {
|
||||
_behaviour = gameObject.GetComponent<MapTileBitmapHolderBehaviour>();
|
||||
_behaviour.Index = index;
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
@@ -32,5 +33,17 @@ namespace Cryville.EEW.Unity.Map {
|
||||
public void Bind(MapTile tile) {
|
||||
_behaviour.Bind(tile);
|
||||
}
|
||||
|
||||
public void Unbind(MapTile tile) {
|
||||
_behaviour.Unbind(tile);
|
||||
}
|
||||
|
||||
public void AddChild(MapTileBitmapHolder bitmapHolder) {
|
||||
_behaviour.AddChild(bitmapHolder._behaviour);
|
||||
}
|
||||
|
||||
public void RemoveChild(MapTileBitmapHolder bitmapHolder) {
|
||||
_behaviour.RemoveChild(bitmapHolder._behaviour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,39 @@
|
||||
using Cryville.EEW.Core.Map;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Cryville.EEW.Unity.Map {
|
||||
sealed class MapTileBitmapHolderBehaviour : MonoBehaviour {
|
||||
Action<Sprite> _callback;
|
||||
public MapTileIndex Index { get; set; }
|
||||
|
||||
readonly List<MapTile> _tiles = new();
|
||||
public void Bind(MapTile tile) {
|
||||
if (_isDone)
|
||||
_tiles.Add(tile);
|
||||
if (_sprite) {
|
||||
tile.Set(_sprite);
|
||||
else
|
||||
_callback += tile.Set;
|
||||
}
|
||||
}
|
||||
public void Unbind(MapTile tile) {
|
||||
_tiles.Remove(tile);
|
||||
}
|
||||
|
||||
readonly List<MapTileBitmapHolderBehaviour> _children = new();
|
||||
public void AddChild(MapTileBitmapHolderBehaviour behaviour) {
|
||||
_children.Add(behaviour);
|
||||
foreach (var tile in _tiles) {
|
||||
tile.SetVisible(false);
|
||||
}
|
||||
SetChildSprite(behaviour);
|
||||
}
|
||||
public void RemoveChild(MapTileBitmapHolderBehaviour behaviour) {
|
||||
_children.Remove(behaviour);
|
||||
bool isActive = _children.Count == 0;
|
||||
foreach (var tile in _tiles) {
|
||||
tile.SetVisible(isActive);
|
||||
}
|
||||
}
|
||||
|
||||
UnityWebRequest _req;
|
||||
@@ -20,7 +43,6 @@ namespace Cryville.EEW.Unity.Map {
|
||||
|
||||
FileInfo _localFile;
|
||||
bool _isReady;
|
||||
bool _isDone;
|
||||
public void Load(FileInfo file) {
|
||||
_localFile = file;
|
||||
_isReady = true;
|
||||
@@ -40,7 +62,7 @@ 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;
|
||||
}
|
||||
@@ -48,19 +70,41 @@ namespace Cryville.EEW.Unity.Map {
|
||||
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);
|
||||
SetSprite(_tex, 0, 0, 0);
|
||||
}
|
||||
else {
|
||||
Debug.LogError(_texHandler.error);
|
||||
App.MainLogger.Log(4, "Map", null, "An error occurred when loading map tile {0}: {1}", _localFile, _texHandler.error);
|
||||
_localFile.Delete();
|
||||
}
|
||||
_req.Dispose();
|
||||
_texHandler.Dispose();
|
||||
_req = null;
|
||||
_callback?.Invoke(_sprite);
|
||||
_isDone = true;
|
||||
}
|
||||
|
||||
int _minDz = int.MaxValue;
|
||||
int _x, _y;
|
||||
void SetSprite(Texture2D tex, int dz, int x, int y) {
|
||||
if (dz >= 8) return;
|
||||
if (dz > _minDz) return;
|
||||
_tex = tex;
|
||||
_x = x; _y = y;
|
||||
_minDz = dz;
|
||||
if (_sprite) Destroy(_sprite);
|
||||
int sx = x << (8 - dz), sy = 256 - ((y + 1) << (8 - dz));
|
||||
_sprite = Sprite.Create(tex, new Rect(sx, sy, 1 << (8 - dz), 1 << (8 - dz)), Vector2.zero, 1 << (8 - dz), 0, SpriteMeshType.FullRect, Vector4.zero, false);
|
||||
foreach (var tile in _tiles)
|
||||
tile.Set(_sprite);
|
||||
foreach (var child in _children) {
|
||||
SetChildSprite(child);
|
||||
}
|
||||
}
|
||||
|
||||
void SetChildSprite(MapTileBitmapHolderBehaviour child) {
|
||||
if (!_tex) return;
|
||||
int cdz = child.Index.Z - Index.Z;
|
||||
int cx = child.Index.X % (1 << cdz) | (_x << cdz), cy = child.Index.Y % (1 << cdz) | (_y << cdz);
|
||||
child.SetSprite(_tex, cdz + _minDz, cx, cy);
|
||||
}
|
||||
|
||||
bool _isDestroyed;
|
||||
public void Destroy() {
|
||||
@@ -69,11 +113,15 @@ namespace Cryville.EEW.Unity.Map {
|
||||
void OnDestroy() {
|
||||
if (_req != null) {
|
||||
_req.Abort();
|
||||
if (_texHandler != null) {
|
||||
var tex = _texHandler.texture;
|
||||
if (tex) Destroy(tex);
|
||||
_texHandler.Dispose();
|
||||
}
|
||||
_req.Dispose();
|
||||
_texHandler.Dispose();
|
||||
}
|
||||
if (_sprite) Destroy(_sprite);
|
||||
if (_tex) Destroy(_tex);
|
||||
if (_tex && _minDz == 0) Destroy(_tex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Cryville.EEW.Core.Map;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
@@ -15,9 +16,9 @@ namespace Cryville.EEW.Unity.Map {
|
||||
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}")
|
||||
new($"https://services.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();
|
||||
@@ -26,16 +27,30 @@ namespace Cryville.EEW.Unity.Map {
|
||||
var gameObject = GameObject.Instantiate(PrefabTile, Parent, false);
|
||||
var uTile = gameObject.GetComponent<MapTile>();
|
||||
_map.Add(tile, uTile);
|
||||
uTile.Init(tile.Index);
|
||||
tile.BitmapHolder.Bind(uTile);
|
||||
var index = tile.Index;
|
||||
uTile.Init(index);
|
||||
var bitmapHolder = tile.BitmapHolder;
|
||||
bitmapHolder.Bind(uTile);
|
||||
|
||||
if (index.Z <= 0) return;
|
||||
var maybeTile = FindTile(index.ZoomToLevel(index.Z - 1, Math.Floor), false);
|
||||
if (maybeTile is not MapTile<MapTileBitmapHolder> parentTile) return;
|
||||
parentTile.BitmapHolder.AddChild(bitmapHolder);
|
||||
}
|
||||
|
||||
protected override void OnTileDestroyed(MapTile<MapTileBitmapHolder> tile) {
|
||||
base.OnTileDestroyed(tile);
|
||||
var bitmapHolder = tile.BitmapHolder;
|
||||
if (_map.TryGetValue(tile, out var uTile)) {
|
||||
uTile.Destroy();
|
||||
bitmapHolder.Unbind(uTile);
|
||||
_map.Remove(tile);
|
||||
}
|
||||
var index = tile.Index;
|
||||
if (index.Z <= 0) return;
|
||||
var maybeTile = FindTile(index.ZoomToLevel(index.Z - 1, Math.Floor), false);
|
||||
if (maybeTile is not MapTile<MapTileBitmapHolder> parentTile) return;
|
||||
parentTile.BitmapHolder.RemoveChild(bitmapHolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,13 @@ 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 TimeSpan NowcastWarningDelayTolerance => TimeSpan.FromMinutes(60); // TODO TTS
|
||||
public float HillshadeLayerOpacity { get; private set; } = 1;
|
||||
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() }; // TODO TTS
|
||||
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);
|
||||
@@ -41,6 +42,9 @@ namespace Cryville.EEW.Unity {
|
||||
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;
|
||||
public bool DoSwitchBackToHistory { get; private set; } = true;
|
||||
@@ -114,12 +118,21 @@ namespace Cryville.EEW.Unity {
|
||||
"SREV" => new DefaultTextColorScheme(Color.White, Color.FromArgb(28, 28, 28), 0.555f),
|
||||
_ => new DefaultTextColorScheme(Color.White, Color.Black),
|
||||
};
|
||||
HillshadeLayerOpacity = config.HillshadeLayerOpacity;
|
||||
_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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,3 +1,4 @@
|
||||
using SpeechLib;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
@@ -5,21 +6,48 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Cryville.EEW.Unity {
|
||||
class TTSWorker : Core.Audio.TTSWorker {
|
||||
public TTSWorker() : base(CreateSoundPlayer()) { }
|
||||
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 _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
37
Assets/Cryville.EEW.Unity/UI/Dialog.cs
Normal file
37
Assets/Cryville.EEW.Unity/UI/Dialog.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Cryville.Common.Unity;
|
||||
using Cryville.Common.Unity.UI;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Cryville.EEW.Unity.UI {
|
||||
public class Dialog : MonoBehaviour {
|
||||
public static Dialog Instance { get; private set; }
|
||||
|
||||
[SerializeField] CanvasGroup m_mask;
|
||||
PropertyTweener<float> _groupAlphaTweener;
|
||||
|
||||
[SerializeField] TMPLocalizedText m_title;
|
||||
[SerializeField] TMPLocalizedText m_message;
|
||||
|
||||
void Awake() {
|
||||
Instance = this;
|
||||
|
||||
m_mask.gameObject.SetActive(false);
|
||||
_groupAlphaTweener = new(() => m_mask.alpha, v => m_mask.alpha = v, Tweeners.Single);
|
||||
}
|
||||
|
||||
public void Show(string title, string message) {
|
||||
Show(SharedCultures.CurrentUICulture, title, message);
|
||||
}
|
||||
public void Show(CultureInfo culture, string title, string message) {
|
||||
m_title.SetText(title, culture);
|
||||
m_message.SetText(message, culture);
|
||||
m_mask.gameObject.SetActive(true);
|
||||
_groupAlphaTweener.Start(1, 0.2f);
|
||||
}
|
||||
|
||||
void Update() {
|
||||
_groupAlphaTweener.Advance(Time.deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Cryville.EEW.Unity/UI/Dialog.cs.meta
Normal file
11
Assets/Cryville.EEW.Unity/UI/Dialog.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1b4f209f34bc6e4c8e13aeb4dd5789d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -5
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -5,6 +5,10 @@ using Cryville.EEW.CWAOpenData;
|
||||
using Cryville.EEW.CWAOpenData.Model;
|
||||
using Cryville.EEW.CWAOpenData.TTS;
|
||||
using Cryville.EEW.EMSC;
|
||||
using Cryville.EEW.FANStudio;
|
||||
using Cryville.EEW.FANStudio.TTS;
|
||||
using Cryville.EEW.GeoNet;
|
||||
using Cryville.EEW.GeoNet.TTS;
|
||||
using Cryville.EEW.GlobalQuake;
|
||||
using Cryville.EEW.JMAAtom;
|
||||
using Cryville.EEW.JMAAtom.TTS;
|
||||
@@ -17,7 +21,6 @@ using Cryville.EEW.Unity.UI;
|
||||
using Cryville.EEW.UpdateChecker;
|
||||
using Cryville.EEW.USGS;
|
||||
using Cryville.EEW.Wolfx;
|
||||
using Cryville.EEW.Wolfx.Model;
|
||||
using Cryville.EEW.Wolfx.TTS;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
@@ -50,36 +53,52 @@ namespace Cryville.EEW.Unity {
|
||||
}
|
||||
Instance = this;
|
||||
|
||||
App.Init();
|
||||
try {
|
||||
App.Init();
|
||||
|
||||
_worker = new(new TTSWorker());
|
||||
_grouper = new ReportGrouper();
|
||||
_cancellationTokenSource = new();
|
||||
_worker = new(new TTSWorker());
|
||||
_grouper = new ReportGrouper();
|
||||
_cancellationTokenSource = new();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Dialog.Instance.Show("FATAL ERROR", ex.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void Start() {
|
||||
LocalizedResources.Init(new LocalizedResourcesManager());
|
||||
RegisterViewModelGenerators(_worker);
|
||||
RegisterTTSMessageGenerators(_worker);
|
||||
BuildWorkers();
|
||||
_worker.RVMGeneratorContext = SharedSettings.Instance;
|
||||
_worker.TTSMessageGeneratorContext = SharedSettings.Instance;
|
||||
_worker.RVMCulture = SharedSettings.Instance.RVMCulture;
|
||||
_ongoingReportManager.Changed += OnOngoingReported;
|
||||
_worker.Reported += OnReported;
|
||||
_grouper.GroupUpdated += OnGroupUpdated;
|
||||
_grouper.GroupRemoved += OnGroupRemoved;
|
||||
Task.Run(() => GatewayVerify(_cancellationTokenSource.Token)).ContinueWith(task => {
|
||||
if (task.IsFaulted) {
|
||||
OnReported(this, new() { Title = task.Exception.Message });
|
||||
return;
|
||||
}
|
||||
_verified = true;
|
||||
_uiActionQueue.Enqueue(() => m_connectingHint.SetActive(false));
|
||||
Task.Run(() => ScheduledGatewayVerify(_cancellationTokenSource, _cancellationTokenSource.Token));
|
||||
Task.Run(() => _worker.RunAsync(_cancellationTokenSource.Token));
|
||||
Task.Run(() => _ongoingReportManager.RunAsync(_cancellationTokenSource.Token));
|
||||
}, TaskScheduler.Current);
|
||||
try {
|
||||
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 });
|
||||
return;
|
||||
}
|
||||
_verified = true;
|
||||
_uiActionQueue.Enqueue(() => m_connectingHint.SetActive(false));
|
||||
Task.Run(() => ScheduledGatewayVerify(_cancellationTokenSource, _cancellationTokenSource.Token));
|
||||
Task.Run(() => _worker.RunAsync(_cancellationTokenSource.Token));
|
||||
Task.Run(() => _ongoingReportManager.RunAsync(_cancellationTokenSource.Token));
|
||||
}, TaskScheduler.Current);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Dialog.Instance.Show("FATAL ERROR", ex.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void OnDestroy() {
|
||||
@@ -91,41 +110,60 @@ namespace Cryville.EEW.Unity {
|
||||
CENCEarthquakeRVMGenerator _cencEarthquakeRVMGenerator;
|
||||
void RegisterViewModelGenerators(CoreWorker worker) {
|
||||
worker.RegisterViewModelGenerator(new BMKGEarthquakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new CEAEEWRVMGenerator());
|
||||
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 FANStudio.FujianEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new Wolfx.FujianEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GeoNetQuakeHistoryRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GeoNetQuakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GeoNetStrongRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new GlobalQuakeRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new ICLEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new JMAAtomRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new JMAEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new NOAAAtomRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new QuakeMLEventRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new SichuanEEWRVMGenerator());
|
||||
var quakemlEventRVMGenerator = new QuakeMLEventRVMGenerator();
|
||||
quakemlEventRVMGenerator.AddExtension(new USGSQuakeMLExtension());
|
||||
worker.RegisterViewModelGenerator(quakemlEventRVMGenerator);
|
||||
worker.RegisterViewModelGenerator(new FANStudio.SichuanEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new Wolfx.SichuanEEWRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new USGSContoursRVMGenerator());
|
||||
worker.RegisterViewModelGenerator(new VersionRVMGenerator());
|
||||
}
|
||||
CENCEarthquakeTTSMessageGenerator _cencEarthquakeTTSMessageGenerator;
|
||||
void RegisterTTSMessageGenerators(CoreWorker worker) {
|
||||
worker.RegisterTTSMessageGenerator(new BMKGEarthquakeTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new CEAEEWTTSMessageGenerator());
|
||||
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 FANStudio.TTS.FujianEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new Wolfx.TTS.FujianEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new GeoNetQuakeHistoryTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new GeoNetQuakeTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new GeoNetStrongTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new ICLEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new JMAAtomTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new JMAEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new NOAATTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new SichuanEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new FANStudio.TTS.SichuanEEWTTSMessageGenerator());
|
||||
worker.RegisterTTSMessageGenerator(new Wolfx.TTS.SichuanEEWTTSMessageGenerator());
|
||||
}
|
||||
|
||||
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")));
|
||||
_worker.AddWorker(new FANStudioWorker<FANStudio.Model.CEAEEW>(new("ws://localhost:9995/fan/cea")));
|
||||
_worker.AddWorker(new CWAReportWorker<Tsunami>(new Uri("http://localhost:9095/E-A0014-001.json"), "1"));
|
||||
_worker.AddWorker(new CWAReportWorker<Earthquake>(new Uri("http://localhost:9095/E-A0015-001.json"), "1"));
|
||||
_worker.AddWorker(new CWAReportWorker<Earthquake>(new Uri("http://localhost:9095/E-A0016-001.json"), "1"));
|
||||
@@ -137,25 +175,35 @@ namespace Cryville.EEW.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")),
|
||||
FANStudioEventSourceConfig fanStudio => fanStudio.Subtype switch {
|
||||
"cea" => new FANStudioWorker<FANStudio.Model.CEAEEW>(new("wss://ws.fanstudio.tech/cea")),
|
||||
"sichuan" => new FANStudioWorker<FANStudio.Model.SichuanEEW>(new("wss://ws.fanstudio.tech/sichuan")),
|
||||
"fujian" => new FANStudioWorker<FANStudio.Model.FujianEEW>(new("wss://ws.fanstudio.tech/fujian")),
|
||||
_ => throw new InvalidOperationException("Unknown FAN Studio sub-type."),
|
||||
},
|
||||
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),
|
||||
USGSEventSourceConfig usgs => BuildUSGSWorker(usgs.UseGeoJSONFeeds
|
||||
? new USGSGeoJSONWorker(new Uri("https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php"))
|
||||
: new USGSQuakeMLWorker(new Uri("https://earthquake.usgs.gov/earthquakes/feed/v1.0/quakeml.php"))
|
||||
, usgs),
|
||||
WolfxEventSourceConfig wolfx => BuildWolfxWorkerFilter(new WolfxWorker(new("wss://ws-api.wolfx.jp/all_eew")), wolfx),
|
||||
_ => throw new InvalidOperationException("Unknown event source type."),
|
||||
});
|
||||
}
|
||||
@@ -168,12 +216,12 @@ namespace Cryville.EEW.Unity {
|
||||
}
|
||||
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>),
|
||||
"cwa_eew" => typeof(CWAEEW),
|
||||
"fj_eew" => typeof(FujianEEW),
|
||||
"jma_eew" => typeof(JMAEEW),
|
||||
"sc_eew" => typeof(SichuanEEW),
|
||||
"cenc_eew" => typeof(Wolfx.Model.CENCEEW),
|
||||
"cenc_eqlist" => typeof(Wolfx.Model.WolfxEarthquakeList<Wolfx.Model.CENCEarthquake>),
|
||||
"cwa_eew" => typeof(Wolfx.Model.CWAEEW),
|
||||
"fj_eew" => typeof(Wolfx.Model.FujianEEW),
|
||||
"jma_eew" => typeof(Wolfx.Model.JMAEEW),
|
||||
"sc_eew" => typeof(Wolfx.Model.SichuanEEW),
|
||||
_ => throw new InvalidOperationException("Unknown Wolfx event type."),
|
||||
}));
|
||||
worker.IsFilterWhitelist = config.IsFilterWhitelist;
|
||||
@@ -188,8 +236,22 @@ namespace Cryville.EEW.Unity {
|
||||
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 USGSQuakeMLWorker BuildUSGSQuakeMLWorkerUri(USGSQuakeMLWorker worker, USGSQuakeMLEventSourceConfig config) {
|
||||
worker.SetFeedRelativeUri(new(string.Format(CultureInfo.InvariantCulture, "/earthquakes/feed/v1.0/summary/{0}.quakeml", config.Subtype), UriKind.Relative));
|
||||
static GeoNetWorker BuildGeoNetWorker(GeoNetWorker worker, GeoNetEventSourceConfig pref) {
|
||||
worker.MinimumMMI = pref.MinimumMMI;
|
||||
worker.DoGetFullHistory = pref.DoGetFullHistory;
|
||||
worker.DoGetStrongMotionInfo = pref.DoGetStrongMotionInfo;
|
||||
return worker;
|
||||
}
|
||||
static USGSWorker BuildUSGSWorker(USGSWorker worker, USGSEventSourceConfig config) {
|
||||
worker.SetFeedRelativeUri(new(string.Format(CultureInfo.InvariantCulture, "/earthquakes/feed/v1.0/summary/{0}{1}", config.Subtype, config.UseGeoJSONFeeds ? ".geojson" : ".quakeml"), UriKind.Relative));
|
||||
if (worker is USGSGeoJSONWorker geojsonWorker) {
|
||||
geojsonWorker.SetFilter(
|
||||
config.Products
|
||||
.Select(i => i.Split('/', 2))
|
||||
.GroupBy(i => i[0])
|
||||
.ToDictionary(g => g.Key, g => g.Select(i => i[1]))
|
||||
);
|
||||
}
|
||||
return worker;
|
||||
}
|
||||
|
||||
@@ -198,7 +260,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, "App", null, "Received an error from {0}: {1}", sender.GetType(), e.Model);
|
||||
_grouper.Report(e);
|
||||
_ongoingReportManager.Report(e);
|
||||
_uiActionQueue.Enqueue(() => {
|
||||
|
||||
2394
Assets/Main.unity
2394
Assets/Main.unity
File diff suppressed because it is too large
Load Diff
91
Assets/Materials/Multiply.mat
Normal file
91
Assets/Materials/Multiply.mat
Normal file
@@ -0,0 +1,91 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Multiply
|
||||
m_Shader: {fileID: 4800000, guid: 0637d3d4bac33b34ea1fb084d1aa83c5, type: 3}
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _AlphaTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- PixelSnap: 0
|
||||
- _BumpScale: 1
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _EnableExternalAlpha: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _UVSec: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _Flip: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _RendererColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -1,8 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4972abff193472e4bbef2dd0ec07b55e
|
||||
guid: e2b4779e0934e3b45978a57b79d75597
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
1315
Assets/Plugins/Cryville.Audio.xml
Normal file
1315
Assets/Plugins/Cryville.Audio.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ade62400bece1a4f9093a91ca22b276
|
||||
guid: 0444abb2bb6ae5c44a7f7ee60b312f0d
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
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:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user