气泡组件和配置项
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AibisDream
|
||||
namespace AibisDream.Utility
|
||||
{
|
||||
public class CommonUtil
|
||||
public static class CommonUtil
|
||||
{
|
||||
private const float Epsilon = 1e-5f;
|
||||
|
||||
|
||||
@@ -0,0 +1,366 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace AibisDream
|
||||
{
|
||||
public class CsvUtil
|
||||
{
|
||||
// 默认编码
|
||||
private static readonly Encoding DefaultEncode = Encoding.UTF8;
|
||||
|
||||
// 默认分隔符
|
||||
private const char FieldSeparator = ',';
|
||||
|
||||
public static List<string[]> Read(string filePath)
|
||||
{
|
||||
List<string[]> dataList = new List<string[]>();
|
||||
StreamReader reader;
|
||||
try
|
||||
{
|
||||
using (reader = new StreamReader(filePath, DefaultEncode))
|
||||
{
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string line = reader.ReadLine();
|
||||
if (line == null) break;
|
||||
string[] data = line.Split(FieldSeparator);
|
||||
dataList.Add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
foreach (Process process in Process.GetProcesses())
|
||||
{
|
||||
if (process.ProcessName.ToUpper().Equals("EXCEL"))
|
||||
process.Kill();
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
Thread.Sleep(50);
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
using (reader = new StreamReader(filePath, DefaultEncode))
|
||||
{
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string line = reader.ReadLine();
|
||||
if (line == null) break;
|
||||
string[] data = line.Split(FieldSeparator);
|
||||
dataList.Add(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
return dataList;
|
||||
}
|
||||
|
||||
public static void WriteCsv(string filePath, List<string[]> dataList)
|
||||
{
|
||||
StreamWriter writer = new StreamWriter(filePath, false, DefaultEncode);
|
||||
foreach (string[] data in dataList)
|
||||
{
|
||||
writer.WriteLine(string.Join(FieldSeparator, data));
|
||||
}
|
||||
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
public static List<T> ReadAsBean<T>(string filePath) where T : class
|
||||
{
|
||||
// 反射部分
|
||||
var targetType = typeof(T);
|
||||
var props = targetType.GetProperties();
|
||||
|
||||
// 读取CSV
|
||||
using var reader = new StreamReader(filePath, DefaultEncode);
|
||||
|
||||
// 第一行是注释
|
||||
reader.ReadLine();
|
||||
// 第二行作为title
|
||||
var titles = reader.ReadLine()?.Split(FieldSeparator);
|
||||
if (titles == null)
|
||||
{
|
||||
Debug.WriteLine("csv无标题");
|
||||
throw new Exception("csv无标题");
|
||||
}
|
||||
|
||||
var res = new List<T>();
|
||||
// 第二行开始读配置内容
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string newLine = reader.ReadLine();
|
||||
if (string.IsNullOrEmpty(newLine)) break;
|
||||
|
||||
string[] rowData = newLine.Split(FieldSeparator);
|
||||
if (rowData == null || rowData.Length == 0) continue;
|
||||
|
||||
// 转为Bean
|
||||
var obj = Activator.CreateInstance(targetType);
|
||||
foreach (var prop in props)
|
||||
{
|
||||
string name = prop.Name;
|
||||
if (!titles.Contains(prop.Name))
|
||||
continue;
|
||||
|
||||
int idx = Array.IndexOf(titles, prop.Name);
|
||||
prop.SetValue(obj, GetDefaultValue(prop, rowData[idx]));
|
||||
}
|
||||
|
||||
res.Add(obj as T);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static bool ReadAsDataTable(ref DataTable myCsvDt, string filepath)
|
||||
{
|
||||
var strPath = filepath; //csv文件的路径
|
||||
|
||||
try
|
||||
{
|
||||
bool blnFlag = true;
|
||||
|
||||
StreamReader reader = new StreamReader(strPath, DefaultEncode);
|
||||
myCsvDt = new DataTable();
|
||||
while (reader.ReadLine() is { } strLine)
|
||||
{
|
||||
var aryLine = strLine.Split(FieldSeparator);
|
||||
//第一行是列的名字,给datatable加上列名,
|
||||
if (blnFlag)
|
||||
{
|
||||
blnFlag = false;
|
||||
var intColCount = aryLine.Length;
|
||||
|
||||
#region 序号作为列头
|
||||
|
||||
//int col = 0;
|
||||
//for (int i = 0; i < intColCount; i++)
|
||||
//{
|
||||
// col = i + 1;
|
||||
// mydc = new DataColumn(col.ToString());
|
||||
// mycsvdt.Columns.Add(mydc);
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 第一行作为列头
|
||||
|
||||
for (int i = 0; i < intColCount; i++)
|
||||
{
|
||||
myCsvDt.Columns.Add(new DataColumn(aryLine[i]));
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
//填充数据并加入到datatable中
|
||||
myCsvDt.Rows.Add(aryLine);
|
||||
}
|
||||
|
||||
reader.Close();
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExportAsCsv(DataTable dt, string savaPath, string strName)
|
||||
{
|
||||
string strPath = savaPath + "\\" + strName; //保存到指定目录下
|
||||
|
||||
if (File.Exists(strPath))
|
||||
{
|
||||
File.Delete(strPath);
|
||||
}
|
||||
|
||||
//先打印标头
|
||||
StringBuilder strColu = new StringBuilder();
|
||||
StringBuilder strValue = new StringBuilder();
|
||||
StreamWriter sw = new StreamWriter(new FileStream(strPath, FileMode.CreateNew), DefaultEncode);
|
||||
try
|
||||
{
|
||||
for (var i = 0; i <= dt.Columns.Count - 1; i++)
|
||||
{
|
||||
strColu.Append(dt.Columns[i].ColumnName);
|
||||
strColu.Append(FieldSeparator);
|
||||
}
|
||||
|
||||
strColu.Remove(strColu.Length - 1, 1); //移出掉最后一个,字符
|
||||
sw.WriteLine(strColu);
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
{
|
||||
strValue.Remove(0, strValue.Length); //移出
|
||||
for (var i = 0; i <= dt.Columns.Count - 1; i++)
|
||||
{
|
||||
strValue.Append(dr[i]);
|
||||
strValue.Append(FieldSeparator);
|
||||
}
|
||||
|
||||
strValue.Remove(strValue.Length - 1, 1); //移出掉最后一个,字符
|
||||
sw.WriteLine(strValue);
|
||||
}
|
||||
|
||||
sw.Close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.Message);
|
||||
sw.Close();
|
||||
}
|
||||
}
|
||||
|
||||
#region 类型转换
|
||||
|
||||
private static object GetDefaultValue(PropertyInfo prop, string value)
|
||||
{
|
||||
return prop.PropertyType.Name switch
|
||||
{
|
||||
"String" => ToNormalString(value),
|
||||
"Int32" => ToInt32(value),
|
||||
"Decimal" => ToDecimal(value),
|
||||
"Single" => ToFloat(value),
|
||||
"Boolean" => ToBoolean(value),
|
||||
"DateTime" => ToDateTime(value),
|
||||
"Double" => ToDouble(value),
|
||||
_ => ToEnum(value, prop)
|
||||
};
|
||||
}
|
||||
|
||||
private static object ToEnum(string value, PropertyInfo prop)
|
||||
{
|
||||
return prop.PropertyType.BaseType == typeof(Enum) ? Enum.Parse(prop.PropertyType, value) : null;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// 转换为Int32
|
||||
/// </summary>
|
||||
private static int ToInt32(string obj)
|
||||
{
|
||||
if (string.IsNullOrEmpty(obj)) return 0;
|
||||
try
|
||||
{
|
||||
if (obj.Contains("."))
|
||||
return (int)Convert.ToSingle(obj);
|
||||
if (int.TryParse(obj, out var tmp))
|
||||
return tmp;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 转换为字符串
|
||||
/// </summary>
|
||||
private static string ToNormalString(string obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return string.Empty;
|
||||
try
|
||||
{
|
||||
return Convert.ToString(obj);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// 转换为日期
|
||||
/// </summary>
|
||||
private static DateTime ToDateTime(string obj)
|
||||
{
|
||||
if (string.IsNullOrEmpty(obj))
|
||||
{
|
||||
return Convert.ToDateTime("1970-01-01 00:00:00");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Convert.ToDateTime(obj);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Convert.ToDateTime("1970-01-01 00:00:00");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为布尔型
|
||||
/// </summary>
|
||||
private static bool ToBoolean(string obj)
|
||||
{
|
||||
if (obj == null) return false;
|
||||
|
||||
return obj.ToLower() == "true" || obj == "1";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为十进制数值
|
||||
/// </summary>
|
||||
private static Decimal ToDecimal(string obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return 0M;
|
||||
}
|
||||
|
||||
var resultString = Regex.Replace(obj, "[^0-9.]", "");
|
||||
var result = resultString.Length == 0 ? 0M : decimal.Parse(resultString);
|
||||
if (obj.StartsWith("-"))
|
||||
{
|
||||
result *= -1M;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// 转换为双精度.
|
||||
/// </summary>
|
||||
private static double ToDouble(string obj)
|
||||
{
|
||||
if (double.TryParse(obj, out var num))
|
||||
return num;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为单精度.
|
||||
/// </summary>
|
||||
private static float ToFloat(string value)
|
||||
{
|
||||
var normalStr = ToNormalString(value);
|
||||
if (string.IsNullOrEmpty(normalStr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (float.TryParse(normalStr, out var result))
|
||||
return result;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5beb292d61f8e134284d2e928fb77d0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -28,5 +28,4 @@ namespace AibisDream
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c23e36c3bf88034e98063d0c27ba935
|
||||
guid: 214dbdcae17401d4e94285d5e416ce66
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace AibisDream.Utility
|
||||
{
|
||||
public abstract class SingletonBase<T> where T : SingletonBase<T>
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance != null) return _instance;
|
||||
// 先获取所有非public的构造方法
|
||||
var ctors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
// 从ctors中获取无参的构造方法
|
||||
var ctor = Array.Find(ctors, c => c.GetParameters().Length == 0);
|
||||
if (ctor == null)
|
||||
throw new Exception("Non-public ctor() not found!");
|
||||
// 调用构造方法
|
||||
_instance = ctor.Invoke(null) as T;
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e06ce6997ac4a14fa439ac9c3747fe9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,11 +1,12 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using AibisDream.Config;
|
||||
using Yarn;
|
||||
using Yarn.Markup;
|
||||
using Yarn.Unity;
|
||||
|
||||
namespace AibisDream
|
||||
namespace AibisDream.Utility
|
||||
{
|
||||
public static class YarnUtil
|
||||
{
|
||||
@@ -14,6 +15,8 @@ namespace AibisDream
|
||||
private const string OptionAttr = "options";
|
||||
|
||||
private const string CommandProp = "name";
|
||||
|
||||
private const string AutoNext = "auto_next";
|
||||
|
||||
public static bool HasCommandAttr(this MarkupParseResult text)
|
||||
{
|
||||
@@ -37,5 +40,93 @@ namespace AibisDream
|
||||
{
|
||||
runner.Dialogue.CommandHandler += onCommand;
|
||||
}
|
||||
|
||||
#region 处理行信息
|
||||
|
||||
/// <summary>
|
||||
/// 当前行是否应该自动跳过
|
||||
/// </summary>
|
||||
/// <param name="line">当前行</param>
|
||||
/// <returns>是否应该自动跳过</returns>
|
||||
public static bool IsAutoSkipLine(this LocalizedLine line)
|
||||
{
|
||||
return line.Metadata != null && line.Metadata.Contains(AutoNext);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从line中获取角色vo定义
|
||||
/// </summary>
|
||||
/// <param name="line">行数据</param>
|
||||
/// <returns>结果</returns>
|
||||
public static CharacterVo GetCharacterVo(this LocalizedLine line)
|
||||
{
|
||||
if (line.Text.TryGetAttributeWithName("character", out var characterAttribute))
|
||||
{
|
||||
// 直接写就使用配置选项
|
||||
if (characterAttribute.Properties.TryGetValue("name", out var nameValue))
|
||||
{
|
||||
return GetCharacterVoByKey(nameValue.StringValue);
|
||||
}
|
||||
|
||||
// 带key就说明可能有自定义属性
|
||||
if (characterAttribute.Properties.TryGetValue("key", out var keyValue))
|
||||
{
|
||||
// 先从配置文件找
|
||||
var charVo = GetCharacterVoByKey(keyValue.StringValue);
|
||||
// 再用自定义填充
|
||||
return FullCharVoWithProps(charVo, characterAttribute.Properties);
|
||||
}
|
||||
|
||||
// 找不到Name和Key
|
||||
return new CharacterVo();
|
||||
}
|
||||
|
||||
// 没有Character就直接返回空
|
||||
return new CharacterVo();
|
||||
}
|
||||
|
||||
private static CharacterVo GetCharacterVoByKey(string charKey)
|
||||
{
|
||||
if (ConfigUtil.Instance.TryGetCharacter(charKey, out var character))
|
||||
{
|
||||
return character.GetStructVo();
|
||||
}
|
||||
|
||||
return new CharacterVo
|
||||
{
|
||||
key = charKey,
|
||||
cn = charKey,
|
||||
role = ActorRole.Aside
|
||||
};
|
||||
}
|
||||
|
||||
private static CharacterVo FullCharVoWithProps(CharacterVo vo, IReadOnlyDictionary<string, MarkupValue> props)
|
||||
{
|
||||
foreach (var pair in props)
|
||||
{
|
||||
switch (pair.Key)
|
||||
{
|
||||
case "cn":
|
||||
vo.cn = pair.Value.StringValue;
|
||||
break;
|
||||
case "nameColor":
|
||||
vo.nameColor = pair.Value.StringValue;
|
||||
break;
|
||||
case "headPicPath":
|
||||
vo.headPicPath = pair.Value.StringValue;
|
||||
break;
|
||||
case "voicePath":
|
||||
vo.voicePath = pair.Value.StringValue;
|
||||
break;
|
||||
case "role":
|
||||
vo.role = Enum.TryParse<ActorRole>(pair.Value.StringValue, out var type) ? type : ActorRole.Aside;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user