Arabic Language support

This commit is contained in:
Ali Sharoz 2025-05-31 05:14:48 +05:00
parent 5a17d38946
commit adc1e94b00
138 changed files with 20740 additions and 767 deletions

View File

@ -135,7 +135,7 @@ AnimatorStateMachine:
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 5062769072093697653}
m_Position: {x: 210, y: 30, z: 0}
m_Position: {x: 260, y: 30, z: 0}
- serializedVersion: 1
m_State: {fileID: -9064094602924671568}
m_Position: {x: 530, y: 60, z: 0}

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: c3502cad44c429a4dab63b2e5b90ce7b
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: f8af0aaae6053264b91bfc1fb5efe624
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,972 @@
#region File Description
//-----------------------------------------------------------------------------
/// <summary>
/// This is an Open Source File Created by: Abdullah Konash (http://abdullahkonash.com/) Twitter: @konash
/// This File allow the users to use arabic text in XNA and Unity platform.
/// It flips the characters and replace them with the appropriate ones to connect the letters in the correct way.
/// </summary>
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
#endregion
namespace ArabicSupport
{
public class ArabicFixer
{
/// <summary>
/// Fix the specified string.
/// </summary>
/// <param name='str'>
/// String to be fixed.
/// </param>
public static string Fix(string str)
{
return Fix(str, false, true);
}
public static string Fix(string str, bool rtl)
{
if(rtl)
{
return Fix(str);
}
else
{
string[] words = str.Split(' ');
string result = "";
string arabicToIgnore = "";
foreach(string word in words)
{
if(char.IsLower(word.ToLower()[word.Length/2]))
{
result += Fix(arabicToIgnore) + word + " ";
arabicToIgnore = "";
}
else
{
arabicToIgnore += word + " ";
}
}
if(arabicToIgnore != "")
result += Fix(arabicToIgnore);
return result;
}
}
/// <summary>
/// Fix the specified string with customization options.
/// </summary>
/// <param name='str'>
/// String to be fixed.
/// </param>
/// <param name='showTashkeel'>
/// Show tashkeel.
/// </param>
/// <param name='useHinduNumbers'>
/// Use hindu numbers.
/// </param>
public static string Fix(string str, bool showTashkeel, bool useHinduNumbers)
{
ArabicFixerTool.showTashkeel = showTashkeel;
ArabicFixerTool.useHinduNumbers =useHinduNumbers;
if(str.Contains("\n"))
str = str.Replace("\n", Environment.NewLine);
if(str.Contains(Environment.NewLine))
{
string[] stringSeparators = new string[] {Environment.NewLine};
string[] strSplit = str.Split(stringSeparators, StringSplitOptions.None);
if(strSplit.Length == 0)
return ArabicFixerTool.FixLine(str);
else if(strSplit.Length == 1)
return ArabicFixerTool.FixLine(str);
else
{
string outputString = ArabicFixerTool.FixLine(strSplit[0]);
int iteration = 1;
if(strSplit.Length > 1)
{
while(iteration < strSplit.Length)
{
outputString += Environment.NewLine + ArabicFixerTool.FixLine(strSplit[iteration]);
iteration++;
}
}
return outputString;
}
}
else
{
return ArabicFixerTool.FixLine(str);
}
}
}
}
/// <summary>
/// Arabic Contextual forms General - Unicode
/// </summary>
internal enum IsolatedArabicLetters
{
Hamza = 0xFE80,
Alef = 0xFE8D,
AlefHamza = 0xFE83,
WawHamza = 0xFE85,
AlefMaksoor = 0xFE87,
AlefMaksora = 0xFBFC,
HamzaNabera = 0xFE89,
Ba = 0xFE8F,
Ta = 0xFE95,
Tha2 = 0xFE99,
Jeem = 0xFE9D,
H7aa = 0xFEA1,
Khaa2 = 0xFEA5,
Dal = 0xFEA9,
Thal = 0xFEAB,
Ra2 = 0xFEAD,
Zeen = 0xFEAF,
Seen = 0xFEB1,
Sheen = 0xFEB5,
S9a = 0xFEB9,
Dha = 0xFEBD,
T6a = 0xFEC1,
T6ha = 0xFEC5,
Ain = 0xFEC9,
Gain = 0xFECD,
Fa = 0xFED1,
Gaf = 0xFED5,
Kaf = 0xFED9,
Lam = 0xFEDD,
Meem = 0xFEE1,
Noon = 0xFEE5,
Ha = 0xFEE9,
Waw = 0xFEED,
Ya = 0xFEF1,
AlefMad = 0xFE81,
TaMarboota = 0xFE93,
PersianPe = 0xFB56, // Persian Letters;
PersianChe = 0xFB7A,
PersianZe = 0xFB8A,
PersianGaf = 0xFB92,
PersianGaf2 = 0xFB8E
}
/// <summary>
/// Arabic Contextual forms - Isolated
/// </summary>
internal enum GeneralArabicLetters
{
Hamza = 0x0621,
Alef = 0x0627,
AlefHamza = 0x0623,
WawHamza = 0x0624,
AlefMaksoor = 0x0625,
AlefMagsora = 0x0649,
HamzaNabera = 0x0626,
Ba = 0x0628,
Ta = 0x062A,
Tha2 = 0x062B,
Jeem = 0x062C,
H7aa = 0x062D,
Khaa2 = 0x062E,
Dal = 0x062F,
Thal = 0x0630,
Ra2 = 0x0631,
Zeen = 0x0632,
Seen = 0x0633,
Sheen = 0x0634,
S9a = 0x0635,
Dha = 0x0636,
T6a = 0x0637,
T6ha = 0x0638,
Ain = 0x0639,
Gain = 0x063A,
Fa = 0x0641,
Gaf = 0x0642,
Kaf = 0x0643,
Lam = 0x0644,
Meem = 0x0645,
Noon = 0x0646,
Ha = 0x0647,
Waw = 0x0648,
Ya = 0x064A,
AlefMad = 0x0622,
TaMarboota = 0x0629,
PersianPe = 0x067E, // Persian Letters;
PersianChe = 0x0686,
PersianZe = 0x0698,
PersianGaf = 0x06AF,
PersianGaf2 = 0x06A9
}
/// <summary>
/// Data Structure for conversion
/// </summary>
internal class ArabicMapping
{
public int from;
public int to;
public ArabicMapping(int from, int to)
{
this.from = from;
this.to = to;
}
}
/// <summary>
/// Sets up and creates the conversion table
/// </summary>
internal class ArabicTable
{
private static List<ArabicMapping> mapList;
private static ArabicTable arabicMapper;
/// <summary>
/// Setting up the conversion table
/// </summary>
private ArabicTable()
{
mapList = new List<ArabicMapping>();
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Hamza, (int)IsolatedArabicLetters.Hamza));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Alef, (int)IsolatedArabicLetters.Alef));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.AlefHamza, (int)IsolatedArabicLetters.AlefHamza));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.WawHamza, (int)IsolatedArabicLetters.WawHamza));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.AlefMaksoor, (int)IsolatedArabicLetters.AlefMaksoor));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.AlefMagsora, (int)IsolatedArabicLetters.AlefMaksora));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.HamzaNabera, (int)IsolatedArabicLetters.HamzaNabera));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Ba, (int)IsolatedArabicLetters.Ba));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Ta, (int)IsolatedArabicLetters.Ta));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Tha2, (int)IsolatedArabicLetters.Tha2));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Jeem, (int)IsolatedArabicLetters.Jeem));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.H7aa, (int)IsolatedArabicLetters.H7aa));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Khaa2, (int)IsolatedArabicLetters.Khaa2));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Dal, (int)IsolatedArabicLetters.Dal));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Thal, (int)IsolatedArabicLetters.Thal));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Ra2, (int)IsolatedArabicLetters.Ra2));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Zeen, (int)IsolatedArabicLetters.Zeen));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Seen, (int)IsolatedArabicLetters.Seen));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Sheen, (int)IsolatedArabicLetters.Sheen));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.S9a, (int)IsolatedArabicLetters.S9a));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Dha, (int)IsolatedArabicLetters.Dha));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.T6a, (int)IsolatedArabicLetters.T6a));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.T6ha, (int)IsolatedArabicLetters.T6ha));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Ain, (int)IsolatedArabicLetters.Ain));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Gain, (int)IsolatedArabicLetters.Gain));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Fa, (int)IsolatedArabicLetters.Fa));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Gaf, (int)IsolatedArabicLetters.Gaf));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Kaf, (int)IsolatedArabicLetters.Kaf));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Lam, (int)IsolatedArabicLetters.Lam));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Meem, (int)IsolatedArabicLetters.Meem));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Noon, (int)IsolatedArabicLetters.Noon));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Ha, (int)IsolatedArabicLetters.Ha));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Waw, (int)IsolatedArabicLetters.Waw));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.Ya, (int)IsolatedArabicLetters.Ya));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.AlefMad, (int)IsolatedArabicLetters.AlefMad));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.TaMarboota, (int)IsolatedArabicLetters.TaMarboota));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.PersianPe, (int)IsolatedArabicLetters.PersianPe)); // Persian Letters;
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.PersianChe, (int)IsolatedArabicLetters.PersianChe));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.PersianZe, (int)IsolatedArabicLetters.PersianZe));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.PersianGaf, (int)IsolatedArabicLetters.PersianGaf));
mapList.Add(new ArabicMapping((int)GeneralArabicLetters.PersianGaf2, (int)IsolatedArabicLetters.PersianGaf2));
//for (int i = 0; i < generalArabic.Length; i++)
// mapList.Add(new ArabicMapping((int)generalArabic.GetValue(i), (int)isolatedArabic.GetValue(i))); // I
}
/// <summary>
/// Singleton design pattern, Get the mapper. If it was not created before, create it.
/// </summary>
internal static ArabicTable ArabicMapper
{
get
{
if (arabicMapper == null)
arabicMapper = new ArabicTable();
return arabicMapper;
}
}
internal int Convert(int toBeConverted)
{
foreach (ArabicMapping arabicMap in mapList)
if (arabicMap.from == toBeConverted)
{
return arabicMap.to;
}
return toBeConverted;
}
}
internal class TashkeelLocation
{
public char tashkeel;
public int position;
public TashkeelLocation(char tashkeel, int position)
{
this.tashkeel = tashkeel;
this.position = position;
}
}
internal class ArabicFixerTool
{
internal static bool showTashkeel = true;
internal static bool useHinduNumbers = false;
internal static string RemoveTashkeel(string str, out List<TashkeelLocation> tashkeelLocation)
{
tashkeelLocation = new List<TashkeelLocation>();
char[] letters = str.ToCharArray();
int index = 0;
for (int i = 0; i < letters.Length; i++) {
if (letters [i] == (char)0x064B) { // Tanween Fatha
tashkeelLocation.Add (new TashkeelLocation ((char)0x064B, i));
index++;
} else if (letters [i] == (char)0x064C) { // DAMMATAN
tashkeelLocation.Add (new TashkeelLocation ((char)0x064C, i));
index++;
} else if (letters [i] == (char)0x064D){ // KASRATAN
tashkeelLocation.Add (new TashkeelLocation ((char)0x064D, i));
index++;
}else if (letters [i] == (char)0x064E) { // FATHA
if(index > 0)
{
if(tashkeelLocation[index-1].tashkeel == (char)0x0651 ) // SHADDA
{
tashkeelLocation [index - 1].tashkeel = (char)0xFC60; // Shadda With Fatha
continue;
}
}
tashkeelLocation.Add (new TashkeelLocation ((char)0x064E, i));
index++;
} else if (letters [i] == (char)0x064F) { // DAMMA
if (index > 0) {
if (tashkeelLocation [index - 1].tashkeel == (char)0x0651) { // SHADDA
tashkeelLocation [index - 1].tashkeel = (char)0xFC61; // Shadda With DAMMA
continue;
}
}
tashkeelLocation.Add (new TashkeelLocation ((char)0x064F, i));
index++;
} else if (letters [i] == (char)0x0650) { // KASRA
if (index > 0) {
if (tashkeelLocation [index - 1].tashkeel == (char)0x0651) { // SHADDA
tashkeelLocation [index - 1].tashkeel = (char)0xFC62; // Shadda With KASRA
continue;
}
}
tashkeelLocation.Add (new TashkeelLocation ((char)0x0650, i));
index++;
} else if (letters [i] == (char)0x0651) { // SHADDA
if(index > 0)
{
if(tashkeelLocation[index-1].tashkeel == (char)0x064E ) // FATHA
{
tashkeelLocation [index - 1].tashkeel = (char)0xFC60; // Shadda With Fatha
continue;
}
if(tashkeelLocation[index-1].tashkeel == (char)0x064F ) // DAMMA
{
tashkeelLocation [index - 1].tashkeel = (char)0xFC61; // Shadda With DAMMA
continue;
}
if(tashkeelLocation[index-1].tashkeel == (char)0x0650 ) // KASRA
{
tashkeelLocation [index - 1].tashkeel = (char)0xFC62; // Shadda With KASRA
continue;
}
}
tashkeelLocation.Add (new TashkeelLocation ((char)0x0651, i));
index++;
} else if (letters [i] == (char)0x0652) { // SUKUN
tashkeelLocation.Add (new TashkeelLocation ((char)0x0652, i));
index++;
} else if (letters [i] == (char)0x0653) { // MADDAH ABOVE
tashkeelLocation.Add (new TashkeelLocation ((char)0x0653, i));
index++;
}
}
string[] split = str.Split(new char[]{(char)0x064B,(char)0x064C,(char)0x064D,
(char)0x064E,(char)0x064F,(char)0x0650,
(char)0x0651,(char)0x0652,(char)0x0653,(char)0xFC60,(char)0xFC61,(char)0xFC62});
str = "";
foreach(string s in split)
{
str += s;
}
return str;
}
internal static char[] ReturnTashkeel(char[] letters, List<TashkeelLocation> tashkeelLocation)
{
char[] lettersWithTashkeel = new char[letters.Length + tashkeelLocation.Count];
int letterWithTashkeelTracker = 0;
for(int i = 0; i<letters.Length; i++)
{
lettersWithTashkeel[letterWithTashkeelTracker] = letters[i];
letterWithTashkeelTracker++;
foreach(TashkeelLocation hLocation in tashkeelLocation)
{
if(hLocation.position == letterWithTashkeelTracker)
{
lettersWithTashkeel[letterWithTashkeelTracker] = hLocation.tashkeel;
letterWithTashkeelTracker++;
}
}
}
return lettersWithTashkeel;
}
/// <summary>
/// Converts a string to a form in which the sting will be displayed correctly for arabic text.
/// </summary>
/// <param name="str">String to be converted. Example: "Aaa"</param>
/// <returns>Converted string. Example: "aa aaa A" without the spaces.</returns>
internal static string FixLine(string str)
{
string test = "";
List<TashkeelLocation> tashkeelLocation;
string originString = RemoveTashkeel(str, out tashkeelLocation);
char[] lettersOrigin = originString.ToCharArray();
char[] lettersFinal = originString.ToCharArray();
for (int i = 0; i < lettersOrigin.Length; i++)
{
lettersOrigin[i] = (char)ArabicTable.ArabicMapper.Convert(lettersOrigin[i]);
}
for (int i = 0; i < lettersOrigin.Length; i++)
{
bool skip = false;
//lettersOrigin[i] = (char)ArabicTable.ArabicMapper.Convert(lettersOrigin[i]);
// For special Lam Letter connections.
if (lettersOrigin[i] == (char)IsolatedArabicLetters.Lam)
{
if (i < lettersOrigin.Length - 1)
{
//lettersOrigin[i + 1] = (char)ArabicTable.ArabicMapper.Convert(lettersOrigin[i + 1]);
if ((lettersOrigin[i + 1] == (char)IsolatedArabicLetters.AlefMaksoor))
{
lettersOrigin[i] = (char)0xFEF7;
lettersFinal[i + 1] = (char)0xFFFF;
skip = true;
}
else if ((lettersOrigin[i + 1] == (char)IsolatedArabicLetters.Alef))
{
lettersOrigin[i] = (char)0xFEF9;
lettersFinal[i + 1] = (char)0xFFFF;
skip = true;
}
else if ((lettersOrigin[i + 1] == (char)IsolatedArabicLetters.AlefHamza))
{
lettersOrigin[i] = (char)0xFEF5;
lettersFinal[i + 1] = (char)0xFFFF;
skip = true;
}
else if ((lettersOrigin[i + 1] == (char)IsolatedArabicLetters.AlefMad))
{
lettersOrigin[i] = (char)0xFEF3;
lettersFinal[i + 1] = (char)0xFFFF;
skip = true;
}
}
}
if (!IsIgnoredCharacter(lettersOrigin[i]))
{
if (IsMiddleLetter(lettersOrigin, i))
lettersFinal[i] = (char)(lettersOrigin[i] + 3);
else if (IsFinishingLetter(lettersOrigin, i))
lettersFinal[i] = (char)(lettersOrigin[i] + 1);
else if (IsLeadingLetter(lettersOrigin, i))
lettersFinal[i] = (char)(lettersOrigin[i] + 2);
}
//string strOut = String.Format(@"\x{0:x4}", (ushort)lettersOrigin[i]);
//UnityEngine.Debug.Log(strOut);
//strOut = String.Format(@"\x{0:x4}", (ushort)lettersFinal[i]);
//UnityEngine.Debug.Log(strOut);
test += Convert.ToString((int)lettersOrigin[i], 16) + " ";
if (skip)
i++;
//chaning numbers to hindu
if(useHinduNumbers){
if(lettersOrigin[i] == (char)0x0030)
lettersFinal[i] = (char)0x0660;
else if(lettersOrigin[i] == (char)0x0031)
lettersFinal[i] = (char)0x0661;
else if(lettersOrigin[i] == (char)0x0032)
lettersFinal[i] = (char)0x0662;
else if(lettersOrigin[i] == (char)0x0033)
lettersFinal[i] = (char)0x0663;
else if(lettersOrigin[i] == (char)0x0034)
lettersFinal[i] = (char)0x0664;
else if(lettersOrigin[i] == (char)0x0035)
lettersFinal[i] = (char)0x0665;
else if(lettersOrigin[i] == (char)0x0036)
lettersFinal[i] = (char)0x0666;
else if(lettersOrigin[i] == (char)0x0037)
lettersFinal[i] = (char)0x0667;
else if(lettersOrigin[i] == (char)0x0038)
lettersFinal[i] = (char)0x0668;
else if(lettersOrigin[i] == (char)0x0039)
lettersFinal[i] = (char)0x0669;
}
}
//Return the Tashkeel to their places.
if(showTashkeel)
lettersFinal = ReturnTashkeel(lettersFinal, tashkeelLocation);
List<char> list = new List<char>();
List<char> numberList = new List<char>();
for (int i = lettersFinal.Length - 1; i >= 0; i--)
{
// if (lettersFinal[i] == '(')
// numberList.Add(')');
// else if (lettersFinal[i] == ')')
// numberList.Add('(');
// else if (lettersFinal[i] == '<')
// numberList.Add('>');
// else if (lettersFinal[i] == '>')
// numberList.Add('<');
// else
if (char.IsPunctuation(lettersFinal[i]) && i>0 && i < lettersFinal.Length-1 &&
(char.IsPunctuation(lettersFinal[i-1]) || char.IsPunctuation(lettersFinal[i+1])))
{
if (lettersFinal[i] == '(')
list.Add(')');
else if (lettersFinal[i] == ')')
list.Add('(');
else if (lettersFinal[i] == '<')
list.Add('>');
else if (lettersFinal[i] == '>')
list.Add('<');
else if (lettersFinal[i] == '[')
list.Add(']');
else if (lettersFinal[i] == ']')
list.Add('[');
else if (lettersFinal[i] != 0xFFFF)
list.Add(lettersFinal[i]);
}
// For cases where english words and arabic are mixed. This allows for using arabic, english and numbers in one sentence.
else if(lettersFinal[i] == ' ' && i > 0 && i < lettersFinal.Length-1 &&
(char.IsLower(lettersFinal[i-1]) || char.IsUpper(lettersFinal[i-1]) || char.IsNumber(lettersFinal[i-1])) &&
(char.IsLower(lettersFinal[i+1]) || char.IsUpper(lettersFinal[i+1]) ||char.IsNumber(lettersFinal[i+1])))
{
numberList.Add(lettersFinal[i]);
}
else if (char.IsNumber(lettersFinal[i]) || char.IsLower(lettersFinal[i]) ||
char.IsUpper(lettersFinal[i]) || char.IsSymbol(lettersFinal[i]) ||
char.IsPunctuation(lettersFinal[i]))// || lettersFinal[i] == '^') //)
{
if (lettersFinal[i] == '(')
numberList.Add(')');
else if (lettersFinal[i] == ')')
numberList.Add('(');
else if (lettersFinal[i] == '<')
numberList.Add('>');
else if (lettersFinal[i] == '>')
numberList.Add('<');
else if (lettersFinal[i] == '[')
list.Add(']');
else if (lettersFinal[i] == ']')
list.Add('[');
else
numberList.Add(lettersFinal[i]);
}
else if( (lettersFinal[i] >= (char)0xD800 && lettersFinal[i] <= (char)0xDBFF) ||
(lettersFinal[i] >= (char)0xDC00 && lettersFinal[i] <= (char)0xDFFF))
{
numberList.Add(lettersFinal[i]);
}
else
{
if (numberList.Count > 0)
{
for (int j = 0; j < numberList.Count; j++)
list.Add(numberList[numberList.Count - 1 - j]);
numberList.Clear();
}
if (lettersFinal[i] != 0xFFFF)
list.Add(lettersFinal[i]);
}
}
if (numberList.Count > 0)
{
for (int j = 0; j < numberList.Count; j++)
list.Add(numberList[numberList.Count - 1 - j]);
numberList.Clear();
}
// Moving letters from a list to an array.
lettersFinal = new char[list.Count];
for (int i = 0; i < lettersFinal.Length; i++)
lettersFinal[i] = list[i];
str = new string(lettersFinal);
return str;
}
/// <summary>
/// English letters, numbers and punctuation characters are ignored. This checks if the ch is an ignored character.
/// </summary>
/// <param name="ch">The character to be checked for skipping</param>
/// <returns>True if the character should be ignored, false if it should not be ignored.</returns>
internal static bool IsIgnoredCharacter(char ch)
{
bool isPunctuation = char.IsPunctuation(ch);
bool isNumber = char.IsNumber(ch);
bool isLower = char.IsLower(ch);
bool isUpper = char.IsUpper(ch);
bool isSymbol = char.IsSymbol(ch);
bool isPersianCharacter = ch == (char)0xFB56 || ch == (char)0xFB7A || ch == (char)0xFB8A || ch == (char)0xFB92 || ch == (char)0xFB8E;
bool isPresentationFormB = (ch <= (char)0xFEFF && ch >= (char)0xFE70);
bool isAcceptableCharacter = isPresentationFormB || isPersianCharacter || ch == (char)0xFBFC;
return isPunctuation ||
isNumber ||
isLower ||
isUpper ||
isSymbol ||
!isAcceptableCharacter ||
ch == 'a' || ch == '>' || ch == '<' || ch == (char)0x061B;
// return char.IsPunctuation(ch) || char.IsNumber(ch) || ch == 'a' || ch == '>' || ch == '<' ||
// char.IsLower(ch) || char.IsUpper(ch) || ch == (char)0x061B || char.IsSymbol(ch)
// || !(ch <= (char)0xFEFF && ch >= (char)0xFE70) // Presentation Form B
// || ch == (char)0xFB56 || ch == (char)0xFB7A || ch == (char)0xFB8A || ch == (char)0xFB92; // Persian Characters
// PersianPe = 0xFB56,
// PersianChe = 0xFB7A,
// PersianZe = 0xFB8A,
// PersianGaf = 0xFB92
//lettersOrigin[i] <= (char)0xFEFF && lettersOrigin[i] >= (char)0xFE70
}
/// <summary>
/// Checks if the letter at index value is a leading character in Arabic or not.
/// </summary>
/// <param name="letters">The whole word that contains the character to be checked</param>
/// <param name="index">The index of the character to be checked</param>
/// <returns>True if the character at index is a leading character, else, returns false</returns>
internal static bool IsLeadingLetter(char[] letters, int index)
{
bool lettersThatCannotBeBeforeALeadingLetter = index == 0
|| letters[index - 1] == ' '
|| letters[index - 1] == '*' // ??? Remove?
|| letters[index - 1] == 'A' // ??? Remove?
|| char.IsPunctuation(letters[index - 1])
|| letters[index - 1] == '>'
|| letters[index - 1] == '<'
|| letters[index - 1] == (int)IsolatedArabicLetters.Alef
|| letters[index - 1] == (int)IsolatedArabicLetters.Dal
|| letters[index - 1] == (int)IsolatedArabicLetters.Thal
|| letters[index - 1] == (int)IsolatedArabicLetters.Ra2
|| letters[index - 1] == (int)IsolatedArabicLetters.Zeen
|| letters[index - 1] == (int)IsolatedArabicLetters.PersianZe
//|| letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksora
|| letters[index - 1] == (int)IsolatedArabicLetters.Waw
|| letters[index - 1] == (int)IsolatedArabicLetters.AlefMad
|| letters[index - 1] == (int)IsolatedArabicLetters.AlefHamza
|| letters[index - 1] == (int)IsolatedArabicLetters.Hamza
|| letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksoor
|| letters[index - 1] == (int)IsolatedArabicLetters.WawHamza;
bool lettersThatCannotBeALeadingLetter = letters[index] != ' '
&& letters[index] != (int)IsolatedArabicLetters.Dal
&& letters[index] != (int)IsolatedArabicLetters.Thal
&& letters[index] != (int)IsolatedArabicLetters.Ra2
&& letters[index] != (int)IsolatedArabicLetters.Zeen
&& letters[index] != (int)IsolatedArabicLetters.PersianZe
&& letters[index] != (int)IsolatedArabicLetters.Alef
&& letters[index] != (int)IsolatedArabicLetters.AlefHamza
&& letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
&& letters[index] != (int)IsolatedArabicLetters.AlefMad
&& letters[index] != (int)IsolatedArabicLetters.WawHamza
&& letters[index] != (int)IsolatedArabicLetters.Waw
&& letters[index] != (int)IsolatedArabicLetters.Hamza;
bool lettersThatCannotBeAfterLeadingLetter = index < letters.Length - 1
&& letters[index + 1] != ' '
&& !char.IsPunctuation(letters[index + 1] )
&& !char.IsNumber(letters[index + 1])
&& !char.IsSymbol(letters[index + 1])
&& !char.IsLower(letters[index + 1])
&& !char.IsUpper(letters[index + 1])
&& letters[index + 1] != (int)IsolatedArabicLetters.Hamza;
if(lettersThatCannotBeBeforeALeadingLetter && lettersThatCannotBeALeadingLetter && lettersThatCannotBeAfterLeadingLetter)
// if ((index == 0 || letters[index - 1] == ' ' || letters[index - 1] == '*' || letters[index - 1] == 'A' || char.IsPunctuation(letters[index - 1])
// || letters[index - 1] == '>' || letters[index - 1] == '<'
// || letters[index - 1] == (int)IsolatedArabicLetters.Alef
// || letters[index - 1] == (int)IsolatedArabicLetters.Dal || letters[index - 1] == (int)IsolatedArabicLetters.Thal
// || letters[index - 1] == (int)IsolatedArabicLetters.Ra2
// || letters[index - 1] == (int)IsolatedArabicLetters.Zeen || letters[index - 1] == (int)IsolatedArabicLetters.PersianZe
// || letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksora || letters[index - 1] == (int)IsolatedArabicLetters.Waw
// || letters[index - 1] == (int)IsolatedArabicLetters.AlefMad || letters[index - 1] == (int)IsolatedArabicLetters.AlefHamza
// || letters[index - 1] == (int)IsolatedArabicLetters.AlefMaksoor || letters[index - 1] == (int)IsolatedArabicLetters.WawHamza)
// && letters[index] != ' ' && letters[index] != (int)IsolatedArabicLetters.Dal
// && letters[index] != (int)IsolatedArabicLetters.Thal
// && letters[index] != (int)IsolatedArabicLetters.Ra2
// && letters[index] != (int)IsolatedArabicLetters.Zeen && letters[index] != (int)IsolatedArabicLetters.PersianZe
// && letters[index] != (int)IsolatedArabicLetters.Alef && letters[index] != (int)IsolatedArabicLetters.AlefHamza
// && letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
// && letters[index] != (int)IsolatedArabicLetters.AlefMad
// && letters[index] != (int)IsolatedArabicLetters.WawHamza
// && letters[index] != (int)IsolatedArabicLetters.Waw
// && letters[index] != (int)IsolatedArabicLetters.Hamza
// && index < letters.Length - 1 && letters[index + 1] != ' ' && !char.IsPunctuation(letters[index + 1] ) && !char.IsNumber(letters[index + 1])
// && letters[index + 1] != (int)IsolatedArabicLetters.Hamza )
{
return true;
}
else
return false;
}
/// <summary>
/// Checks if the letter at index value is a finishing character in Arabic or not.
/// </summary>
/// <param name="letters">The whole word that contains the character to be checked</param>
/// <param name="index">The index of the character to be checked</param>
/// <returns>True if the character at index is a finishing character, else, returns false</returns>
internal static bool IsFinishingLetter(char[] letters, int index)
{
bool indexZero = index != 0;
bool lettersThatCannotBeBeforeAFinishingLetter = (index == 0) ? false :
letters[index - 1] != ' '
// && char.IsDigit(letters[index-1])
// && char.IsLower(letters[index-1])
// && char.IsUpper(letters[index-1])
// && char.IsNumber(letters[index-1])
// && char.IsWhiteSpace(letters[index-1])
// && char.IsPunctuation(letters[index-1])
// && char.IsSymbol(letters[index-1])
&& letters[index - 1] != (int)IsolatedArabicLetters.Dal
&& letters[index - 1] != (int)IsolatedArabicLetters.Thal
&& letters[index - 1] != (int)IsolatedArabicLetters.Ra2
&& letters[index - 1] != (int)IsolatedArabicLetters.Zeen
&& letters[index - 1] != (int)IsolatedArabicLetters.PersianZe
//&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora
&& letters[index - 1] != (int)IsolatedArabicLetters.Waw
&& letters[index - 1] != (int)IsolatedArabicLetters.Alef
&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
&& letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza
&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
&& letters[index - 1] != (int)IsolatedArabicLetters.WawHamza
&& letters[index - 1] != (int)IsolatedArabicLetters.Hamza
&& !char.IsPunctuation(letters[index - 1])
&& letters[index - 1] != '>'
&& letters[index - 1] != '<';
bool lettersThatCannotBeFinishingLetters = letters[index] != ' ' && letters[index] != (int)IsolatedArabicLetters.Hamza;
if(lettersThatCannotBeBeforeAFinishingLetter && lettersThatCannotBeFinishingLetters)
// if (index != 0 && letters[index - 1] != ' ' && letters[index - 1] != '*' && letters[index - 1] != 'A'
// && letters[index - 1] != (int)IsolatedArabicLetters.Dal && letters[index - 1] != (int)IsolatedArabicLetters.Thal
// && letters[index - 1] != (int)IsolatedArabicLetters.Ra2
// && letters[index - 1] != (int)IsolatedArabicLetters.Zeen && letters[index - 1] != (int)IsolatedArabicLetters.PersianZe
// && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora && letters[index - 1] != (int)IsolatedArabicLetters.Waw
// && letters[index - 1] != (int)IsolatedArabicLetters.Alef && letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
// && letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
// && letters[index - 1] != (int)IsolatedArabicLetters.WawHamza && letters[index - 1] != (int)IsolatedArabicLetters.Hamza
// && !char.IsPunctuation(letters[index - 1]) && letters[index - 1] != '>' && letters[index - 1] != '<'
// && letters[index] != ' ' && index < letters.Length
// && letters[index] != (int)IsolatedArabicLetters.Hamza)
{
//try
//{
// if (char.IsPunctuation(letters[index + 1]))
// return true;
// else
// return false;
//}
//catch (Exception e)
//{
// return false;
//}
return true;
}
//return true;
else
return false;
}
/// <summary>
/// Checks if the letter at index value is a middle character in Arabic or not.
/// </summary>
/// <param name="letters">The whole word that contains the character to be checked</param>
/// <param name="index">The index of the character to be checked</param>
/// <returns>True if the character at index is a middle character, else, returns false</returns>
internal static bool IsMiddleLetter(char[] letters, int index)
{
bool lettersThatCannotBeMiddleLetters = (index == 0) ? false :
letters[index] != (int)IsolatedArabicLetters.Alef
&& letters[index] != (int)IsolatedArabicLetters.Dal
&& letters[index] != (int)IsolatedArabicLetters.Thal
&& letters[index] != (int)IsolatedArabicLetters.Ra2
&& letters[index] != (int)IsolatedArabicLetters.Zeen
&& letters[index] != (int)IsolatedArabicLetters.PersianZe
//&& letters[index] != (int)IsolatedArabicLetters.AlefMaksora
&& letters[index] != (int)IsolatedArabicLetters.Waw
&& letters[index] != (int)IsolatedArabicLetters.AlefMad
&& letters[index] != (int)IsolatedArabicLetters.AlefHamza
&& letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
&& letters[index] != (int)IsolatedArabicLetters.WawHamza
&& letters[index] != (int)IsolatedArabicLetters.Hamza;
bool lettersThatCannotBeBeforeMiddleCharacters = (index == 0) ? false :
letters[index - 1] != (int)IsolatedArabicLetters.Alef
&& letters[index - 1] != (int)IsolatedArabicLetters.Dal
&& letters[index - 1] != (int)IsolatedArabicLetters.Thal
&& letters[index - 1] != (int)IsolatedArabicLetters.Ra2
&& letters[index - 1] != (int)IsolatedArabicLetters.Zeen
&& letters[index - 1] != (int)IsolatedArabicLetters.PersianZe
//&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora
&& letters[index - 1] != (int)IsolatedArabicLetters.Waw
&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
&& letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza
&& letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
&& letters[index - 1] != (int)IsolatedArabicLetters.WawHamza
&& letters[index - 1] != (int)IsolatedArabicLetters.Hamza
&& !char.IsPunctuation(letters[index - 1])
&& letters[index - 1] != '>'
&& letters[index - 1] != '<'
&& letters[index - 1] != ' '
&& letters[index - 1] != '*';
bool lettersThatCannotBeAfterMiddleCharacters = (index >= letters.Length - 1) ? false :
letters[index + 1] != ' '
&& letters[index + 1] != '\r'
&& letters[index + 1] != (int)IsolatedArabicLetters.Hamza
&& !char.IsNumber(letters[index + 1])
&& !char.IsSymbol(letters[index + 1])
&& !char.IsPunctuation(letters[index + 1]);
if(lettersThatCannotBeAfterMiddleCharacters && lettersThatCannotBeBeforeMiddleCharacters && lettersThatCannotBeMiddleLetters)
// if (index != 0 && letters[index] != ' '
// && letters[index] != (int)IsolatedArabicLetters.Alef && letters[index] != (int)IsolatedArabicLetters.Dal
// && letters[index] != (int)IsolatedArabicLetters.Thal && letters[index] != (int)IsolatedArabicLetters.Ra2
// && letters[index] != (int)IsolatedArabicLetters.Zeen && letters[index] != (int)IsolatedArabicLetters.PersianZe
// && letters[index] != (int)IsolatedArabicLetters.AlefMaksora
// && letters[index] != (int)IsolatedArabicLetters.Waw && letters[index] != (int)IsolatedArabicLetters.AlefMad
// && letters[index] != (int)IsolatedArabicLetters.AlefHamza && letters[index] != (int)IsolatedArabicLetters.AlefMaksoor
// && letters[index] != (int)IsolatedArabicLetters.WawHamza && letters[index] != (int)IsolatedArabicLetters.Hamza
// && letters[index - 1] != (int)IsolatedArabicLetters.Alef && letters[index - 1] != (int)IsolatedArabicLetters.Dal
// && letters[index - 1] != (int)IsolatedArabicLetters.Thal && letters[index - 1] != (int)IsolatedArabicLetters.Ra2
// && letters[index - 1] != (int)IsolatedArabicLetters.Zeen && letters[index - 1] != (int)IsolatedArabicLetters.PersianZe
// && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksora
// && letters[index - 1] != (int)IsolatedArabicLetters.Waw && letters[index - 1] != (int)IsolatedArabicLetters.AlefMad
// && letters[index - 1] != (int)IsolatedArabicLetters.AlefHamza && letters[index - 1] != (int)IsolatedArabicLetters.AlefMaksoor
// && letters[index - 1] != (int)IsolatedArabicLetters.WawHamza && letters[index - 1] != (int)IsolatedArabicLetters.Hamza
// && letters[index - 1] != '>' && letters[index - 1] != '<'
// && letters[index - 1] != ' ' && letters[index - 1] != '*' && !char.IsPunctuation(letters[index - 1])
// && index < letters.Length - 1 && letters[index + 1] != ' ' && letters[index + 1] != '\r' && letters[index + 1] != 'A'
// && letters[index + 1] != '>' && letters[index + 1] != '>' && letters[index + 1] != (int)IsolatedArabicLetters.Hamza
// )
{
try
{
if (char.IsPunctuation(letters[index + 1]))
return false;
else
return true;
}
catch
{
return false;
}
//return true;
}
else
return false;
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3be8d3a121eda4528aa029c9467af8ae
timeCreated: 1482729253
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 20d90232017bac94da80bd64bfbf8ab3
folderAsset: yes
timeCreated: 1483097412
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,50 @@
using ArabicSupport;
using UnityEditor;
using UnityEngine;
public class ArabicSupportTool : EditorWindow
{
string rawText;
string fixedText;
bool showTashkeel = true;
bool useHinduNumbers = true;
// Add menu item named "Arabic Support Tool" to the Tools menu
[MenuItem("Tools/Arabic Support Tool")]
public static void ShowWindow()
{
//Show existing window instance. If one doesn't exist, make one.
EditorWindow.GetWindow(typeof(ArabicSupportTool));
}
void OnGUI()
{
if (string.IsNullOrEmpty(rawText))
{
fixedText = "";
}
else
{
fixedText = ArabicFixer.Fix(rawText, showTashkeel, useHinduNumbers);
}
GUILayout.Label("Options:", EditorStyles.boldLabel);
showTashkeel = EditorGUILayout.Toggle("Use Tashkeel", showTashkeel);
useHinduNumbers = EditorGUILayout.Toggle("Use Hindu Numbers", useHinduNumbers);
GUILayout.Label("Input (Not Fixed)", EditorStyles.boldLabel);
rawText = EditorGUILayout.TextArea(rawText);
GUILayout.Label("Output (Fixed)", EditorStyles.boldLabel);
fixedText = EditorGUILayout.TextArea(fixedText);
if (GUILayout.Button("Copy")) {
var tempTextEditor = new TextEditor();
tempTextEditor.text = fixedText;
tempTextEditor.SelectAll();
tempTextEditor.Copy();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0ba46ac56c892f2459bc59b39edb3325
timeCreated: 1483096883
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,249 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 583e1073d75f2d3478c0f3cfb43fabaf, type: 3}
m_Name: LanguageDatabase
m_EditorClassIdentifier:
texts:
- key: newEmail
english: 1 New Email Received
arabic: "\u062A\u0645 \u0627\u0633\u062A\u0644\u0627\u0645 \u0628\u0631\u064A\u062F
\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A \u062C\u062F\u064A\u062F"
- key: hacked
english: SIMULATION FAILED - CREDENTIALS STOLEN
arabic: "\u0641\u0634\u0644 \u0627\u0644\u0645\u062D\u0627\u0643\u0627\u0629
\u2013 \u062A\u0645 \u0633\u0631\u0642\u0629 \u0628\u064A\u0627\u0646\u0627\u062A
\u0627\u0644\u0627\u0639\u062A\u0645\u0627\u062F"
- key: whyphishing
english: LET'S UNDERSTAND WHY THIS WAS PHISHING.
arabic: "\u062F\u0639\u0648\u0646\u0627 \u0646\u0641\u0647\u0645 \u0644\u0645\u0627\u0630\u0627
\u0643\u0627\u0646 \u0647\u0630\u0627 \u062A\u0635\u064A\u062F\u0627\u064B
\u0627\u062D\u062A\u064A\u0627\u0644\u064A\u0627\u064B"
- key: alwaysreport
english: ALWAYS REPORT. HERE'S WHY...
arabic: "\u0623\u0628\u0644\u063A \u062F\u0627\u0626\u0645\u0627\u064B. \u0625\u0644\u064A\u0643
\u0627\u0644\u0633\u0628\u0628..."
- key: notsuspicious
english: THIS WAS NOT A SUSPICIOUS EMAIL
arabic: "\u0647\u0630\u0627 \u0644\u0645 \u064A\u0643\u0646 \u0628\u0631\u064A\u062F\u0627\u064B
\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A\u0627\u064B \u0645\u0634\u0628\u0648\u0647\u0627\u064B"
- key: mail
english: Mail
arabic: "\u0627\u0644\u0628\u0631\u064A\u062F"
- key: inbox
english: Inbox
arabic: "\u0627\u0644\u0648\u0627\u0631\u062F"
- key: compose
english: Compose
arabic: "\u0625\u0646\u0634\u0627\u0621"
- key: starred
english: Starred
arabic: "\u0627\u0644\u0645\u0645\u064A\u0632\u0629 \u0628\u0646\u062C\u0645\u0629"
- key: sent
english: Sent
arabic: "\u0627\u0644\u0645\u0631\u0633\u0644\u0629"
- key: draft
english: Draft
arabic: "\u0627\u0644\u0645\u0633\u0648\u062F\u0627\u062A"
- key: more
english: More
arabic: "\u0627\u0644\u0645\u0632\u064A\u062F"
- key: search
english: Search
arabic: "\u0628\u062D\u062B"
- key: Today
english: Today
arabic: "\u0627\u0644\u064A\u0648\u0645"
- key: Yesterday
english: Yesterday
arabic: "\u0627\u0644\u0628\u0627\u0631\u062D\u0629"
- key: 1 hour ago
english: 1 hour ago
arabic: "\u0642\u0628\u0644 \u0633\u0627\u0639\u0629 \u0648\u0627\u062D\u062F\u0629"
- key: May 25
english: May 25
arabic: "\u0662\u0665 \u0645\u0627\u064A\u0648"
- key: May 24
english: May 24
arabic: "\u0662\u0664 \u0645\u0627\u064A\u0648"
- key: "ob1ink a update now \u2013 Avoid Suspension"
english: "ob1ink a update now \u2013 Avoid Suspension"
arabic: "\u0642\u064F\u0645 \u0628\u062A\u062D\u062F1\u062B \u0627\u0644\u0622\u0646
\u2013 \u0644\u062A\u062C\u0646\u0628 \u0627\u0644\u0625\u064A\u0642\u0627\u0641"
- key: "Suspicious Login \u2013 act1vate your profile urgently"
english: "Suspicious Login \u2013 act1vate your profile urgently"
arabic: "\u062A\u0633\u062C\u064A\u0644 \u062F\u062E\u0648\u0644 \u0645\u0634\u0628\u0648\u0647
\u2013 \u0641\u0639\u0651\u0644 \u0645\u0644\u0641\u0643 \u0627\u0644\u0634\u062E\u0635\u064A
\u0641\u0648\u0631\u0627\u064B"
- key: Verify stor-age account info to avoid suspens1on
english: Verify stor-age account info to avoid suspens1on
arabic: "\u062A\u062D\u0642\u0642 \u0645\u0646 \u0645\u0639\u0640\u0644\u0648\u0645\u0640\u0627\u062A
\u062D\u0633\u0640\u0627\u0628 \u0627\u0644\u062A\u062E\u0640\u0632\u064A\u0640\u0646
\u0644\u062A\u062C\u0646\u0628 \u0627\u0644\u0625\u064A\u0640\u0642\u0627\u0641"
- key: May HR Newsletter Available
english: May HR Newsletter Available
arabic: "\u0646\u0634\u0631\u0629 \u0627\u0644\u0645\u0648\u0627\u0631\u062F
\u0627\u0644\u0628\u0634\u0631\u064A\u0629 \u0644\u0634\u0647\u0631 \u0645\u0627\u064A\u0648
\u0645\u062A\u0648\u0641\u0631\u0629"
- key: "Reimbursement Processed \u2013 $124"
english: "Reimbursement Processed \u2013 $124"
arabic: "\u062A\u0645 \u0635\u0631\u0641 \u0627\u0644\u062A\u0639\u0648\u064A\u0636
\u2013 \u0661\u0662\u0664 \u062F\u0648\u0644\u0627\u0631"
- key: Scheduled Maintenance Notification
english: Scheduled Maintenance Notification
arabic: "\u0625\u0634\u0639\u0627\u0631 \u0628\u0627\u0644\u0635\u064A\u0627\u0646\u0629
\u0627\u0644\u0645\u062C\u062F\u0648\u0644\u0629"
- key: "Team Sync \u2013 Monday 10 AM"
english: "Team Sync \u2013 Monday 10 AM"
arabic: "\u062A\u0632\u0627\u0645\u0646 \u0627\u0644\u0641\u0631\u064A\u0642
\u2013 \u0627\u0644\u0627\u062B\u0646\u064A\u0646 \u0661\u0660 \u0635\u0628\u0627\u062D\u0627\u064B"
- key: TIMELINE OF ACTIONS
english: TIMELINE OF ACTIONS
arabic: "\u062A\u0633\u0644\u0633\u0644 \u0627\u0644\u0625\u062C\u0631\u0627\u0621\u0627\u062A
\u0627\u0644\u0632\u0645\u0646\u064A\u0629"
- key: What Were The Clues?
english: What Were The Clues?
arabic: "\u0645\u0627 \u0647\u064A \u0627\u0644\u0623\u062F\u0644\u0629\u061F"
- key: WHY ITS DANGEROUS!
english: WHY ITS DANGEROUS!
arabic: "\u0644\u0645\u0627\u0630\u0627 \u0647\u0648 \u062E\u0637\u064A\u0631!"
- key: How to be safe?
english: How to be safe?
arabic: "\u0643\u064A\u0641 \u062A\u0628\u0642\u0649 \u0622\u0645\u0646\u0627\u064B\u061F"
- key: Mini Quiz
english: Mini Quiz
arabic: "\u0627\u062E\u062A\u0628\u0627\u0631 \u0642\u0635\u064A\u0631"
- key: What was the biggest red flag in this phishing email?
english: What was the biggest red flag in this phishing email?
arabic: "\u0645\u0627 \u0647\u0648 \u0623\u0628\u0631\u0632 \u0645\u0624\u0634\u0631
\u062E\u0637\u0631 \u0641\u064A \u0647\u0630\u0627 \u0627\u0644\u0628\u0631\u064A\u062F
\u0627\u0644\u0627\u062D\u062A\u064A\u0627\u0644\u064A\u061F"
- key: Typos in the subject
english: Typos in the subject
arabic: "\u0623\u062E\u0637\u0627\u0621 \u0625\u0645\u0644\u0627\u0626\u064A\u0629
\u0641\u064A \u0627\u0644\u0639\u0646\u0648\u0627\u0646"
- key: Urgent Language
english: Urgent Language
arabic: "\u0644\u063A\u0629 \u0645\u0644\u062D\u0651\u0629"
- key: Mismatched Sender
english: Mismatched Sender
arabic: "\u0645\u0631\u0633\u0644 \u063A\u064A\u0631 \u0645\u062A\u0637\u0627\u0628\u0642"
- key: All of the above
english: All of the above
arabic: "\u0643\u0644 \u0645\u0627 \u0633\u0628\u0642"
- key: whatwerethecluessummary
english: "\U0001F4CC Typos & Spelling Errors The email had spelling mistakes
or odd grammar \u2014 a common phishing sign. \U0001F4CC Urgency & Pressure
It used urgent language to pressure you into acting quickly. \U0001F4CC Link
Inspection The link preview didn\u2019t match the real website \u2014 inspect
links before clicking. \U0001F4CC Unfamiliar or Unexpected Content The email
seemed unrelated to your work \u2014 phishing often comes out of nowhere.
\U0001F4CC Generic Greetings It used a generic greeting like Dear user instead
of your name. \U0001F4CC Unusual Requests It asked for sensitive info like
passwords \u2014 companies don\u2019t do this by email."
arabic: "\U0001F4CC \u0623\u062E\u0637\u0627\u0621 \u0625\u0645\u0644\u0627\u0626\u064A\u0629
\u0648\u0646\u062D\u0648\u064A\u0629 \u062A\u0636\u0645\u0651\u0646 \u0627\u0644\u0628\u0631\u064A\u062F
\u0623\u062E\u0637\u0627\u0621 \u0641\u064A \u0627\u0644\u062A\u0647\u062C\u0626\u0629
\u0623\u0648 \u0642\u0648\u0627\u0639\u062F \u0644\u063A\u0648\u064A\u0629
\u063A\u0631\u064A\u0628\u0629 \u2014 \u0648\u0647\u0630\u0627 \u0645\u0646
\u0639\u0644\u0627\u0645\u0627\u062A \u0627\u0644\u062A\u0635\u064A\u0651\u062F
\u0627\u0644\u0634\u0627\u0626\u0639\u0629. \U0001F4CC \u0627\u0644\u0627\u0633\u062A\u0639\u062C\u0627\u0644
\u0648\u0627\u0644\u0636\u063A\u0637 \u0627\u0633\u062A\u062E\u062F\u0645 \u0644\u063A\u0629
\u0645\u0644\u062D\u0651\u0629 \u0644\u0644\u0636\u063A\u0637 \u0639\u0644\u064A\u0643
\u0643\u064A \u062A\u062A\u0635\u0631\u0641 \u0628\u0633\u0631\u0639\u0629.
\U0001F4CC \u0641\u062D\u0635 \u0627\u0644\u0631\u0627\u0628\u0637 \u0644\u0645
\u064A\u062A\u0637\u0627\u0628\u0642 \u0645\u0639\u0627\u064A\u0646\u0629 \u0627\u0644\u0631\u0627\u0628\u0637
\u0645\u0639 \u0627\u0644\u0645\u0648\u0642\u0639 \u0627\u0644\u062D\u0642\u064A\u0642\u064A
\u2014 \u0627\u0641\u062D\u0635 \u0627\u0644\u0631\u0648\u0627\u0628\u0637
\u0642\u0628\u0644 \u0627\u0644\u0646\u0642\u0631 \u0639\u0644\u064A\u0647\u0627.
\U0001F4CC \u0645\u062D\u062A\u0648\u0649 \u063A\u064A\u0631 \u0645\u0623\u0644\u0648\u0641
\u0623\u0648 \u063A\u064A\u0631 \u0645\u062A\u0648\u0642\u0639 \u0628\u062F\u0627
\u0627\u0644\u0628\u0631\u064A\u062F \u063A\u064A\u0631 \u0645\u0631\u062A\u0628\u0637
\u0628\u0639\u0645\u0644\u0643 \u2014 \u0641\u0627\u0644\u062A\u0635\u064A\u0651\u062F
\u063A\u0627\u0644\u0628\u0627\u064B \u0645\u0627 \u064A\u0623\u062A\u064A
\u0645\u0646 \u0645\u0635\u062F\u0631 \u063A\u064A\u0631 \u0645\u062A\u0648\u0642\u0639.
\U0001F4CC \u062A\u062D\u064A\u0629 \u0639\u0627\u0645\u0629 \u0627\u0633\u062A\u062E\u062F\u0645
\u062A\u062D\u064A\u0629 \u0639\u0627\u0645\u0629 \u0645\u062B\u0644 \"\u0639\u0632\u064A\u0632\u064A
\u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\" \u0628\u062F\u0644\u0627\u064B
\u0645\u0646 \u0627\u0633\u0645\u0643 \u0627\u0644\u062D\u0642\u064A\u0642\u064A.
\U0001F4CC \u0637\u0644\u0628\u0627\u062A \u063A\u064A\u0631 \u0645\u0639\u062A\u0627\u062F\u0629
\u0637\u0644\u0628 \u0645\u0639\u0644\u0648\u0645\u0627\u062A \u062D\u0633\u0627\u0633\u0629
\u0645\u062B\u0644 \u0643\u0644\u0645\u0627\u062A \u0627\u0644\u0645\u0631\u0648\u0631
\u2014 \u0627\u0644\u0634\u0631\u0643\u0627\u062A \u0644\u0627 \u062A\u0637\u0644\u0628
\u0630\u0644\u0643 \u0639\u0628\u0631 \u0627\u0644\u0628\u0631\u064A\u062F
\u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A. "
- key: howtobesafesummary
english: "\u2022 <b>Verify the sender\u2019s email address carefully</b> Phishing
emails often use addresses that look legit but contain subtle misspellings.
Always check if the domain matches the official source. \u2022 <b>Report suspicious
emails instead of ignoring them</b> Don't delete sketchy emails \u2014 report
them to IT. This helps protect others from falling for the same trick. \u2022
<b>Be cautious of urgent or threatening messages</b> Scammers use pressure
tactics like account warnings to rush you. Always pause and think before clicking.
\u2022 <b>Never click on links without checking them first</b> Hover over links
to see where they lead. If the URL looks odd or unrelated, don't click. \u2022
<b>Avoid entering sensitive info through email links</b> Real companies won\u2019t
ask for passwords or private details via email. Go to the official website
instead. \u2022 <b>Look out for bad grammar or typos</b> Poor grammar, weird
formatting, or obvious typos can signal a phishing attempt.email."
arabic: "\u2022 <b>\u062A\u062D\u0642\u0642 \u0645\u0646 \u0639\u0646\u0648\u0627\u0646
\u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A
\u0644\u0644\u0645\u0631\u0633\u0644 \u0628\u0639\u0646\u0627\u064A\u0629</b>
\u063A\u0627\u0644\u0628\u064B\u0627 \u0645\u0627 \u062A\u0633\u062A\u062E\u062F\u0645
\u0631\u0633\u0627\u0626\u0644 \u0627\u0644\u062A\u0635\u064A\u0651\u062F \u0639\u0646\u0627\u0648\u064A\u0646
\u062A\u0628\u062F\u0648 \u0634\u0631\u0639\u064A\u0629 \u0644\u0643\u0646\u0647\u0627
\u062A\u062D\u062A\u0648\u064A \u0639\u0644\u0649 \u0623\u062E\u0637\u0627\u0621
\u0625\u0645\u0644\u0627\u0626\u064A\u0629 \u062E\u0641\u064A\u0629. \u062A\u062D\u0642\u0642
\u062F\u0627\u0626\u0645\u0627\u064B \u0645\u0645\u0627 \u0625\u0630\u0627
\u0643\u0627\u0646 \u0627\u0644\u0646\u0637\u0627\u0642 \u064A\u062A\u0637\u0627\u0628\u0642
\u0645\u0639 \u0627\u0644\u0645\u0635\u062F\u0631 \u0627\u0644\u0631\u0633\u0645\u064A.
\u2022 <b>\u0623\u0628\u0644\u063A \u0639\u0646 \u0627\u0644\u0631\u0633\u0627\u0626\u0644
\u0627\u0644\u0645\u0634\u0628\u0648\u0647\u0629 \u0628\u062F\u0644\u0627\u064B
\u0645\u0646 \u062A\u062C\u0627\u0647\u0644\u0647\u0627</b> \u0644\u0627 \u062A\u062D\u0630\u0641
\u0627\u0644\u0631\u0633\u0627\u0626\u0644 \u0627\u0644\u0645\u0631\u064A\u0628\u0629
\u2014 \u0623\u0628\u0644\u063A \u0639\u0646\u0647\u0627 \u0625\u0644\u0649
\u0642\u0633\u0645 \u062A\u0643\u0646\u0648\u0644\u0648\u062C\u064A\u0627 \u0627\u0644\u0645\u0639\u0644\u0648\u0645\u0627\u062A.
\u0647\u0630\u0627 \u064A\u0633\u0627\u0639\u062F \u0641\u064A \u062D\u0645\u0627\u064A\u0629
\u0627\u0644\u0622\u062E\u0631\u064A\u0646 \u0645\u0646 \u0627\u0644\u0648\u0642\u0648\u0639
\u0641\u064A \u0646\u0641\u0633 \u0627\u0644\u0641\u062E. \u2022 <b>\u0643\u0646
\u062D\u0630\u0631\u0627\u064B \u0645\u0646 \u0627\u0644\u0631\u0633\u0627\u0626\u0644
\u0627\u0644\u0645\u0633\u062A\u0639\u062C\u0644\u0629 \u0623\u0648 \u0627\u0644\u0645\u0647\u062F\u062F\u0629</b>
\u064A\u0633\u062A\u062E\u062F\u0645 \u0627\u0644\u0645\u062D\u062A\u0627\u0644\u0648\u0646
\u0623\u0633\u0627\u0644\u064A\u0628 \u0627\u0644\u0636\u063A\u0637 \u0645\u062B\u0644
\u062A\u062D\u0630\u064A\u0631\u0627\u062A \u0627\u0644\u062D\u0633\u0627\u0628
\u0644\u0625\u062C\u0628\u0627\u0631\u0643 \u0639\u0644\u0649 \u0627\u0644\u062A\u0635\u0631\u0651\u0641
\u0628\u0633\u0631\u0639\u0629. \u062E\u0630 \u0644\u062D\u0638\u0629 \u0644\u0644\u062A\u0641\u0643\u064A\u0631
\u0642\u0628\u0644 \u0627\u0644\u0646\u0642\u0631. \u2022 <b>\u0644\u0627
\u062A\u0646\u0642\u0631 \u0639\u0644\u0649 \u0627\u0644\u0631\u0648\u0627\u0628\u0637
\u062F\u0648\u0646 \u0627\u0644\u062A\u062D\u0642\u0642 \u0645\u0646\u0647\u0627
\u0623\u0648\u0644\u0627\u064B</b> \u0645\u0631\u0651\u0631 \u0627\u0644\u0645\u0624\u0634\u0631
\u0641\u0648\u0642 \u0627\u0644\u0631\u0648\u0627\u0628\u0637 \u0644\u0645\u0639\u0631\u0641\u0629
\u0648\u062C\u0647\u062A\u0647\u0627. \u0625\u0630\u0627 \u0628\u062F\u0627
\u0639\u0646\u0648\u0627\u0646 \u0627\u0644\u0631\u0627\u0628\u0637 \u063A\u0631\u064A\u0628\u064B\u0627
\u0623\u0648 \u063A\u064A\u0631 \u0645\u062A\u0639\u0644\u0642\u060C \u0641\u0644\u0627
\u062A\u0646\u0642\u0631 \u0639\u0644\u064A\u0647. \u2022 <b>\u062A\u062C\u0646\u0628
\u0625\u062F\u062E\u0627\u0644 \u0645\u0639\u0644\u0648\u0645\u0627\u062A \u062D\u0633\u0627\u0633\u0629
\u0645\u0646 \u062E\u0644\u0627\u0644 \u0631\u0648\u0627\u0628\u0637 \u0627\u0644\u0628\u0631\u064A\u062F
\u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A</b> \u0627\u0644\u0634\u0631\u0643\u0627\u062A
\u0627\u0644\u062D\u0642\u064A\u0642\u064A\u0629 \u0644\u0627 \u062A\u0637\u0644\u0628
\u0643\u0644\u0645\u0627\u062A \u0627\u0644\u0645\u0631\u0648\u0631 \u0623\u0648
\u0627\u0644\u062A\u0641\u0627\u0635\u064A\u0644 \u0627\u0644\u062E\u0627\u0635\u0629
\u0639\u0628\u0631 \u0627\u0644\u0628\u0631\u064A\u062F \u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A.
\u0627\u0646\u062A\u0642\u0644 \u0625\u0644\u0649 \u0627\u0644\u0645\u0648\u0642\u0639
\u0627\u0644\u0631\u0633\u0645\u064A \u0628\u062F\u0644\u0627\u064B \u0645\u0646
\u0630\u0644\u0643. \u2022 <b>\u0627\u0646\u062A\u0628\u0647 \u0644\u0644\u0623\u062E\u0637\u0627\u0621
\u0627\u0644\u0646\u062D\u0648\u064A\u0629 \u0623\u0648 \u0627\u0644\u0625\u0645\u0644\u0627\u0626\u064A\u0629</b>
\u0627\u0644\u0642\u0648\u0627\u0639\u062F \u0627\u0644\u0636\u0639\u064A\u0641\u0629
\u0623\u0648 \u0627\u0644\u062A\u0646\u0633\u064A\u0642 \u0627\u0644\u063A\u0631\u064A\u0628
\u0623\u0648 \u0627\u0644\u0623\u062E\u0637\u0627\u0621 \u0627\u0644\u0625\u0645\u0644\u0627\u0626\u064A\u0629
\u0627\u0644\u0648\u0627\u0636\u062D\u0629 \u064A\u0645\u0643\u0646 \u0623\u0646
\u062A\u0643\u0648\u0646 \u062F\u0644\u064A\u0644\u0627\u064B \u0639\u0644\u0649
\u0645\u062D\u0627\u0648\u0644\u0629 \u062A\u0635\u064A\u0651\u062F.\u0648\u0646\u064A. "

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a0995cee7b744cd49b66a13a828a98d1
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6dc170a4122f06a40a149225d39900fb
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: c3168bfa965d5c54baf38e48e6502699
TrueTypeFontImporter:
externalObjects: {}
serializedVersion: 4
fontSize: 16
forceTextureCase: -2
characterSpacing: 0
characterPadding: 1
includeFontData: 1
fontNames:
- Noto Sans Arabic
fallbackFontReferences: []
customCharacters:
fontRenderingMode: 0
ascentCalculationMode: 1
useLegacyBoundsCalculation: 0
shouldRoundAdvanceValue: 1
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a50043564713dd942a1d8ea59e213c7d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,51 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.2.2] - 2023-01-10
- Fix icon offset influence on other inspector entries
## [1.2.1] - 2022-04-24
- Fix detection for PlayerPrefs where the key contains '_h'
- Use unicode for windows registry lookups to support none ASCII chars in projects names
## [1.2.0] - 2022-01-01
### Added
- Enhanced search field to filter player preferences by key or value
- Add sorting functionality for Pref entries (none, ascending, descending)
### Removed
- Remove Unity 2017 support
- Remove Unity 2018 support
## [1.1.2] - 2021-07-01
- Fixed ImageManger icon detection
## [1.1.1] - 2021-05-23
- Add utf8 key encryption support for windows
## [1.1.0] - 2021-05-17
- Improve key validation with more characters
- Async output reading for MAC plist process
- Performance optimizations
## [1.0.4] - 2020-09-20
- Add handling for special characters in product/company name
- Improvement of plist read call on MAC
## [1.0.3] - 2020-09-20
- Fix text color on professional skin
## [1.0.2] - 2020-08-11
- Switch package author to 'BG Tools'
- Fix UPM documentation image path
## [1.0.1] - 2020-06-01
- Resizable column width for table layout
- Multiple UX improvements
- Add manual
## [1.0.0] - 2020-05-26
This is the first release of PlayerPrefs Editor

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 53e2fe1165389a84c8c415eed555029d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ac7740c4463611344b22ca368af84da1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fa4d09c10dec18841a67065c4ef628bf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@ -0,0 +1,92 @@
fileFormatVersion: 2
guid: 418213a0ca74fec47960ee53fbae1cad
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,92 @@
fileFormatVersion: 2
guid: 34408ed3bf23927459af6b3263c3b147
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 0
wrapV: 0
wrapW: 0
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,474 @@
<!DOCTYPE html>
<html>
<head>
<title>PlayerPrefsEditor-Manual</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"></meta>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style type="text/css">
body {
font-family: Helvetica, arial, sans-serif;
font-size: 14px;
line-height: 1.6;
padding-top: 10px;
padding-bottom: 10px;
background-color: white;
padding: 30px;
color: #333;
}
body &gt; *:first-child {
margin-top: 0 !important;
}
body &gt; *:last-child {
margin-bottom: 0 !important;
}
a {
color: #4183C4;
text-decoration: none;
}
a.absent {
color: #cc0000;
}
a.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative;
}
h2:first-child, h1:first-child, h1:first-child + h2, h3:first-child, h4:first-child, h5:first-child, h6:first-child {
margin-top: 0;
padding-top: 0;
}
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
text-decoration: none;
}
h1 tt, h1 code {
font-size: inherit;
}
h2 tt, h2 code {
font-size: inherit;
}
h3 tt, h3 code {
font-size: inherit;
}
h4 tt, h4 code {
font-size: inherit;
}
h5 tt, h5 code {
font-size: inherit;
}
h6 tt, h6 code {
font-size: inherit;
}
h1 {
font-size: 28px;
color: black;
}
h2 {
font-size: 24px;
border-bottom: 1px solid #cccccc;
color: black;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 16px;
}
h5 {
font-size: 14px;
}
h6 {
color: #777777;
font-size: 14px;
}
p, blockquote, ul, ol, dl, li, table, pre {
margin: 15px 0;
}
/*
hr {
border: 0 none;
color: #cccccc;
height: 4px;
padding: 0;
}
*/
body &gt; h2:first-child {
margin-top: 0;
padding-top: 0;
}
body &gt; h1:first-child {
margin-top: 0;
padding-top: 0;
}
body &gt; h1:first-child + h2 {
margin-top: 0;
padding-top: 0;
}
body &gt; h3:first-child, body &gt; h4:first-child, body &gt; h5:first-child, body &gt; h6:first-child {
margin-top: 0;
padding-top: 0;
}
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
margin-top: 0;
}
li p.first {
display: inline-block;
}
ul, ol {
padding-left: 30px;
}
ul :first-child, ol :first-child {
margin-top: 0;
}
ul :last-child, ol :last-child {
margin-bottom: 0;
}
dl {
padding: 0;
}
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}
dl dt:first-child {
padding: 0;
}
dl dt &gt; :first-child {
margin-top: 0;
}
dl dt &gt; :last-child {
margin-bottom: 0;
}
dl dd {
margin: 0 0 15px;
padding: 0 15px;
}
dl dd &gt; :first-child {
margin-top: 0;
}
dl dd &gt; :last-child {
margin-bottom: 0;
}
blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777;
}
blockquote &gt; :first-child {
margin-top: 0;
}
blockquote &gt; :last-child {
margin-bottom: 0;
}
table {
padding: 0;
}
table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0;
}
table tr:nth-child(2n) {
background-color: #f8f8f8;
}
table tr th {
font-weight: bold;
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px;
}
table tr td {
border: 1px solid #cccccc;
text-align: left;
margin: 0;
padding: 6px 13px;
}
table tr th :first-child, table tr td :first-child {
margin-top: 0;
}
table tr th :last-child, table tr td :last-child {
margin-bottom: 0;
}
img {
max-width: 100%;
}
span.frame {
display: block;
overflow: hidden;
}
span.frame &gt; span {
border: 1px solid #dddddd;
display: block;
float: left;
overflow: hidden;
margin: 13px 0 0;
padding: 7px;
width: auto;
}
span.frame span img {
display: block;
float: left;
}
span.frame span span {
clear: both;
color: #333333;
display: block;
padding: 5px 0 0;
}
span.align-center {
display: block;
overflow: hidden;
clear: both;
}
span.align-center &gt; span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: center;
}
span.align-center span img {
margin: 0 auto;
text-align: center;
}
span.align-right {
display: block;
overflow: hidden;
clear: both;
}
span.align-right &gt; span {
display: block;
overflow: hidden;
margin: 13px 0 0;
text-align: right;
}
span.align-right span img {
margin: 0;
text-align: right;
}
span.float-left {
display: block;
margin-right: 13px;
overflow: hidden;
float: left;
}
span.float-left span {
margin: 13px 0 0;
}
span.float-right {
display: block;
margin-left: 13px;
overflow: hidden;
float: right;
}
span.float-right &gt; span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: right;
}
code, tt {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}
pre code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}
.highlight pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}
pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}
pre code, pre tt {
background-color: transparent;
border: none;
}
</style>
</head>
<body style="">
<h1 id="0">PlayerPrefs Editor for Unity 3D</h1>
<p id="2">Tool extension for the Unity Editor that enables easy access to the player preferences over a simple UI. Allows to view, add, remove and modify entries on the development machine.</p>
<h2 id="4">Support</h2>
<p id="6"><a href="https://github.com/Dysman/bgTools-playerPrefsEditor">GitHub</a> | <a href="https://www.bgtools.de/post/playerprefseditor/">Website</a> | <a href="mailto:support@bgtools.de">Mail</a> | <a href="https://discord.gg/8rcPZrD">Discord</a></p>
<h2 id="8">Features</h2>
<ul id="10">
<li id="10">Add, remove and edit PlayerPrefs</li>
<li id="11">Intuitive visual editor</li>
<li id="12">Works with standard Unity PlayerPrefs</li>
<li id="13">Monitors changes from code</li>
<li id="14">Supports all editors (Windows, Linux, MacOS)</li>
<li id="15">Lightweight dockable for full integration in your workflow</li>
<li id="16">Supports both skins (Personal, Professional)</li>
</ul>
<h2 id="18">Usage</h2>
<p id="20">The PlayerPrefs Editor is located in the top menu at Tools/BG Tools/PlayerPrefs Editor. It's a standard dockable window, so place it wherever it helps to be productive.</p>
<p id="22"><img src="./Images/bgtools_ppe_manual_layout.png" width="100%" style="max-width:800px" alt="PlayerPrefs editor window layout" /></p>
<p id="24">The PlayerPrefs Editor window displays:</p>
<ul id="25">
<li id="25">(A) Filter field</li>
<li id="26">(B) Sort mode</li>
<li id="27">(C) Toggle 'System changes monitoring' behavior</li>
<li id="28">(D) Refresh data</li>
<li id="29">(E) Delete all data</li>
<li id="30">(F) Operating system and path to PlayerPrefs data</li>
<li id="31">(G) PlayerPrefs data list (Key, Type, Value)</li>
<li id="32">(H) Add/Remove a PlayerPrefs entry</li>
<li id="33">(I) Toggle visibility of system defined PlayerPrefs</li>
</ul>
<h3 id="35">Modify Entries</h3>
<p id="37">The PlayerPrefs Editor allow to add, remove and edit PlayerPrefs data.</p>
<p id="39"><strong>Add a new entry</strong></p>
<p id="41">Press the '+' button and select the type of the new PlayerPref entry. It's not possible to modify this type later. Add the key for the new entry in the upcoming dialog field. Additionally the dialog will provide feedback when it detected unintended overrides or invalid characters.</p>
<p id="43"><strong>Remove a existing entry</strong></p>
<p id="45">Select the entry from the list that you want to delete. Press the '-' button to remove this entry. Confirm the warning dialog to finish the operation.</p>
<p id="47"><strong>Modify a existing entry</strong></p>
<p id="49">To change a value of a existing entry do this directly in the value field in the PlayerPref list.</p>
<h3 id="51">Sort &amp; Filter</h3>
<p id="53"><strong>Sorting</strong></p>
<p id="55">Circle trought the sorting funtions by pressing the (B) button in the toolbar.</p>
<p id="57">Following sorting function are aviliable for the PlayerPref entries:</p>
<ul id="58">
<li id="58">None</li>
<li id="59">Ascending</li>
<li id="60">Descending</li>
</ul>
<p id="62"><strong>Filtering</strong></p>
<p id="64">Enter a text into the the search field (A) in the toolbar to filter the PlayerPrefs data list (G).</p>
<p id="66"><img src="./Images/bgtools_ppe_manual_filterModes.png" width="50%" style="max-width:350px" alt="PlayerPrefs editor searchfield modes" /></p>
<p id="68">Additionally select the mode for filtering by pressing on the magnifying glass icon in the search field. Choose between filtering the existing PlayPrefs by key or value. The current search target will be shown in the searchfield if no search string is present.</p>
<h3 id="70">Monitoring system changes</h3>
<p id="72">The plugin can monitor changes at runtime automatically and keep the view up-to-date. This detection is active by default, but it can be turned off over the (C) button in the toolbar.</p>
<h2 id="74">Samples</h2>
<p id="76">This package includes two samples for testing purposes:</p>
<p id="78"><strong>Test Value Menu</strong></p>
<blockquote id="79">
<p id="79">Adds new entries into the top menu Tools/BG Tools/PlayerPrefs Test Values. This allows easily to add text values to the PlayerPrefs of the current project.</p>
</blockquote>
<p id="81"><strong>Sample Scene</strong></p>
<blockquote id="82">
<p id="82">Simple UI that manipulates PlayerPrefs entries on runtime.</p>
</blockquote>
<h2 id="84">Technical details</h2>
<h3 id="85">Requirements</h3>
<p id="87">This version of PlayerPrefs Editor is compatible with the following versions of the Unity Editor:</p>
<blockquote id="89">
<p id="89">2019.4 and later (recommended)<br />
Windows, MacOS, Linux</p>
</blockquote>
<h3 id="92">Limitations MacOS</h3>
<p id="94">Due to technical on MacOS it take time to update the persistent file that stores the PlayerPrefs. To avoid inconsistent data the plugin will show a loading screen until the data can be fully refreshed. Sorry for the inconvenience.</p>
<p id="96">Keep in mind that it's possible to deactivate the automatic refresh in the settings.</p>
</body>
<html>

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 907d7ca800984c64d9b2116fdaf6681e
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 31c463d7ccf40cf4cab8c990a851231d
folderAsset: yes
timeCreated: 1500321077
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,224 @@
#if UNITY_EDITOR
using System;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace BgTools.Utils
{
public class ImageManager
{
// Keep this ID unique
private static readonly string ID = "[PlayerPrefsEditor] com.bgtools.playerprefseditor";
private static string imageManagerPath;
private static string GetAssetDir()
{
if (imageManagerPath != null)
{
return imageManagerPath;
}
foreach (string assetGuid in AssetDatabase.FindAssets("ImageManager"))
{
string assetPath = AssetDatabase.GUIDToAssetPath(assetGuid);
string fileName = Path.GetFileName(assetPath);
if (fileName.Equals("ImageManager.cs"))
{
// Check ID if it's the correct ImageManager
if (File.ReadLines(Path.GetFullPath(assetPath)).Any(line => line.Contains(ID)))
{
imageManagerPath = Path.GetDirectoryName(assetPath) + Path.DirectorySeparatorChar;
return imageManagerPath;
}
}
}
throw new Exception("Cannot find ImageManager.cs in the project. Are sure all the files in place?");
}
public static Texture2D GetOsIcon()
{
#if UNITY_EDITOR_WIN
return OsWinIcon;
#elif UNITY_EDITOR_OSX
return OsMacIcon;
#elif UNITY_EDITOR_LINUX
return OsLinuxIcon;
#endif
}
private static Texture2D osLinuxIcon;
public static Texture2D OsLinuxIcon
{
get
{
if (osLinuxIcon == null)
{
osLinuxIcon = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "os_linux_icon.png", typeof(Texture2D));
}
return osLinuxIcon;
}
}
private static Texture2D osWinIcon;
public static Texture2D OsWinIcon
{
get
{
if (osWinIcon == null)
{
osWinIcon = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "os_win_icon.png", typeof(Texture2D));
}
return osWinIcon;
}
}
private static Texture2D osMacIcon;
public static Texture2D OsMacIcon
{
get
{
if (osMacIcon == null)
{
osMacIcon = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "os_mac_icon.png", typeof(Texture2D));
}
return osMacIcon;
}
}
private static GUIContent[] spinWheelIcons;
public static GUIContent[] SpinWheelIcons
{
get
{
if(spinWheelIcons == null)
{
spinWheelIcons = new GUIContent[12];
for (int i = 0; i < 12; i++)
spinWheelIcons[i] = EditorGUIUtility.IconContent("WaitSpin" + i.ToString("00"));
}
return spinWheelIcons;
}
}
private static Texture2D refresh;
public static Texture2D Refresh
{
get
{
if (refresh == null)
{
refresh = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "refresh.png", typeof(Texture2D));
}
return refresh;
}
}
private static Texture2D trash;
public static Texture2D Trash
{
get
{
if (trash == null)
{
trash = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "trash.png", typeof(Texture2D));
}
return trash;
}
}
private static Texture2D exclamation;
public static Texture2D Exclamation
{
get
{
if(exclamation == null)
{
exclamation = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "exclamation.png", typeof(Texture2D));
}
return exclamation;
}
}
private static Texture2D info;
public static Texture2D Info
{
get
{
if (info == null)
{
info = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "info.png", typeof(Texture2D));
}
return info;
}
}
private static Texture2D watching;
public static Texture2D Watching
{
get
{
if(watching == null)
{
watching = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "watching.png", typeof(Texture2D));
}
return watching;
}
}
private static Texture2D notWatching;
public static Texture2D NotWatching
{
get
{
if (notWatching == null)
{
notWatching = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "not_watching.png", typeof(Texture2D));
}
return notWatching;
}
}
private static Texture2D sortDisabled;
public static Texture2D SortDisabled
{
get
{
if (sortDisabled == null)
{
sortDisabled = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "sort.png", typeof(Texture2D));
}
return sortDisabled;
}
}
private static Texture2D sortAsscending;
public static Texture2D SortAsscending
{
get
{
if (sortAsscending == null)
{
sortAsscending = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "sort_asc.png", typeof(Texture2D));
}
return sortAsscending;
}
}
private static Texture2D sortDescending;
public static Texture2D SortDescending
{
get
{
if (sortDescending == null)
{
sortDescending = (Texture2D)AssetDatabase.LoadAssetAtPath(GetAssetDir() + "sort_desc.png", typeof(Texture2D));
}
return sortDescending;
}
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ee68545419352384a950cc488e731084
timeCreated: 1500324006
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
{
"name": "Unity.PlayerPrefsEditor.EditorResources",
"references": [],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: bf6f54031c06d954889037da1389c752
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

View File

@ -0,0 +1,99 @@
fileFormatVersion: 2
guid: 058af12bb195cdc43a0f974953fc4afd
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

View File

@ -0,0 +1,99 @@
fileFormatVersion: 2
guid: babe6cc749d43c2469c6cb12a7a9d344
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 9
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 2
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- serializedVersion: 2
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
vertices: []
indices:
edges: []
weights: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

View File

@ -0,0 +1,86 @@
fileFormatVersion: 2
guid: 01600487ba432264983788be42b0b029
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

View File

@ -0,0 +1,100 @@
fileFormatVersion: 2
guid: c78f517c9f87bdf4e814d0d96e740793
timeCreated: 1500327620
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

View File

@ -0,0 +1,100 @@
fileFormatVersion: 2
guid: c94af9de33f2f524ca4141c5ea383090
timeCreated: 1500322442
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

View File

@ -0,0 +1,100 @@
fileFormatVersion: 2
guid: d40b23b11d3b85145af46d2c1316e057
timeCreated: 1500327620
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

View File

@ -0,0 +1,100 @@
fileFormatVersion: 2
guid: 7d9ae81a8b3252449820b277748395bc
timeCreated: 1500927179
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,122 @@
fileFormatVersion: 2
guid: 5d3ebd901d622c14a9653af004d172a0
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 3e86075fa207f0041b6111dbfaa3d66e
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,108 @@
fileFormatVersion: 2
guid: 73059e24567e2e647bb1d8280f28bf43
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

View File

@ -0,0 +1,106 @@
fileFormatVersion: 2
guid: cc312847c3bca82428ff672fea7385c7
timeCreated: 1502315347
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: iPhone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Android
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

View File

@ -0,0 +1,86 @@
fileFormatVersion: 2
guid: ed8c91adb8fc54f41aaff0986b083281
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 0
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -1
wrapU: 1
wrapV: 1
wrapW: -1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
- buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 7afdecdeaea3efc42b92ba335397568c
folderAsset: yes
timeCreated: 1496263422
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2c61139fc58134242bb4b9e6d9fabdc0
folderAsset: yes
timeCreated: 1502815237
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,139 @@
using BgTools.Extensions;
using BgTools.Utils;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace BgTools.Dialogs
{
public class TextFieldDialog : EditorWindow
{
[NonSerialized]
private string resultString = string.Empty;
[NonSerialized]
private Action<string> callback;
[NonSerialized]
private string description;
[NonSerialized]
private List<TextValidator> validatorList = new List<TextValidator>();
[NonSerialized]
private TextValidator errorValidator = null;
public static void OpenDialog(string title, string description, List<TextValidator> validatorList, Action<string> callback, EditorWindow targetWin = null)
{
TextFieldDialog window = ScriptableObject.CreateInstance<TextFieldDialog>();
window.name = "TextFieldDialog '" + title + "'";
window.titleContent = new GUIContent (title);
window.description = description;
window.callback = callback;
window.validatorList = validatorList;
window.position = new Rect(0, 0, 350, 140);
window.ShowUtility();
window.CenterOnWindow(targetWin);
window.Focus();
EditorWindow.FocusWindowIfItsOpen<TextFieldDialog>();
}
void OnGUI()
{
errorValidator = null;
Color defaultColor = GUI.contentColor;
GUILayout.Space(20);
EditorGUILayout.LabelField(description);
GUILayout.Space(20);
GUI.SetNextControlName(name+"_textInput");
resultString = EditorGUILayout.TextField(resultString, GUILayout.ExpandWidth(true));
// GUILayout.Space(20);
GUILayout.FlexibleSpace();
foreach(TextValidator val in validatorList)
{
if (!val.Validate(resultString))
{
errorValidator = val;
break;
}
}
bool lockOkButton = !(errorValidator != null && errorValidator.m_errorType == TextValidator.ErrorType.Error);
GUILayout.BeginHorizontal();
if(errorValidator != null)
{
switch (errorValidator.m_errorType)
{
case TextValidator.ErrorType.Info:
GUI.contentColor = Styles.Colors.Blue;
GUILayout.Box(new GUIContent(ImageManager.Info, errorValidator.m_failureMsg), Styles.icon);
break;
case TextValidator.ErrorType.Warning:
GUI.contentColor = Styles.Colors.Yellow;
GUILayout.Box(new GUIContent(ImageManager.Exclamation, errorValidator.m_failureMsg), Styles.icon);
break;
case TextValidator.ErrorType.Error:
GUI.contentColor = Styles.Colors.Red;
GUILayout.Box(new GUIContent(ImageManager.Exclamation, errorValidator.m_failureMsg), Styles.icon);
break;
}
GUI.contentColor = defaultColor;
}
GUILayout.FlexibleSpace();
if (GUILayout.Button("Cancel", GUILayout.Width(75.0f)))
this.Close();
GUI.enabled = lockOkButton;
if (GUILayout.Button("OK", GUILayout.Width(75.0f)))
{
callback(resultString);
Close();
}
GUI.enabled = true;
GUILayout.EndHorizontal();
GUILayout.Space(20);
// set focus only if element exist
try
{
EditorGUI.FocusTextInControl(name+"_textInput");
}
catch (MissingReferenceException)
{ }
if (Event.current != null && Event.current.isKey)
{
switch (Event.current.keyCode)
{
case KeyCode.Return:
if (lockOkButton)
{
callback(resultString);
Close();
}
break;
case KeyCode.Escape:
Close();
break;
}
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 380be3677d2e95144863ee00c051c1f2
timeCreated: 1500849296
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,64 @@
using System;
using System.Text.RegularExpressions;
namespace BgTools.Dialogs
{
public class TextValidator
{
public enum ErrorType
{
Invalid = -1,
Info = 0,
Warning = 1,
Error = 2
}
[NonSerialized]
public ErrorType m_errorType = ErrorType.Invalid;
[NonSerialized]
private string m_regEx = string.Empty;
[NonSerialized]
private Func<string, bool> m_validationFunction;
[NonSerialized]
public string m_failureMsg = string.Empty;
/// <summary>
/// Validator for TextFieldDialog based on regex.
/// </summary>
/// <param name="errorType">Categorie of the error.</param>
/// <param name="failureMsg">Message that described the reason why the validation fail.</param>
/// <param name="regEx">String with regular expression. It need to describe the valid state.</param>
public TextValidator(ErrorType errorType, string failureMsg, string regEx)
{
m_errorType = errorType;
m_failureMsg = failureMsg;
m_regEx = regEx;
}
/// <summary>
/// Validator for TextFieldDialog based on regex.
/// </summary>
/// <param name="errorType">Categorie of the error.</param>
/// <param name="failureMsg">Message that described the reason why the validation fail.</param>
/// <param name="validationFunction">Function that validate the input. Get the current input as string and need to return a bool. Nedd to return 'false' if the validation fails.</param>
public TextValidator(ErrorType errorType, string failureMsg, Func<string, bool> validationFunction)
{
m_errorType = errorType;
m_failureMsg = failureMsg;
m_validationFunction = validationFunction;
}
public bool Validate(string srcString)
{
if (m_regEx != string.Empty)
return Regex.IsMatch(srcString, m_regEx);
else if (m_validationFunction != null)
return m_validationFunction(srcString);
return false;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4202eaaf18e2e43438f2f3632b252393
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 5c7bb3ee5362c0a40a707ade01e79972
folderAsset: yes
timeCreated: 1502876479
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,90 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace BgTools.Extensions
{
public static class Extensions
{
private static Type[] GetAllDerivedTypes(this AppDomain aAppDomain, Type aType)
{
var result = new List<Type>();
var assemblies = aAppDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
var types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.IsSubclassOf(aType))
result.Add(type);
}
}
return result.ToArray();
}
public static Rect GetEditorMainWindowPos(EditorWindow relatedWin = null)
{
var containerWinType = AppDomain.CurrentDomain.GetAllDerivedTypes(typeof(ScriptableObject)).Where(t => t.Name == "ContainerWindow").FirstOrDefault();
if (containerWinType == null)
throw new MissingMemberException("Can't find internal type ContainerWindow. Maybe something has changed inside Unity");
var showModeField = containerWinType.GetField("m_ShowMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var positionProperty = containerWinType.GetProperty("position", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (showModeField == null || positionProperty == null)
throw new MissingFieldException("Can't find internal fields 'm_ShowMode' or 'position'. Maybe something has changed inside Unity");
var windows = Resources.FindObjectsOfTypeAll(containerWinType);
foreach (var win in windows)
{
var showmode = (int)showModeField.GetValue(win);
// Given window
//if (relatedWin != null && relatedWin.GetInstanceID() == win.GetInstanceID())
//{
// var pos = (Rect)positionProperty.GetValue(win, null);
// return pos;
//}
// Main window
if (showmode == 4)
{
var pos = (Rect)positionProperty.GetValue(win, null);
return pos;
}
}
throw new NotSupportedException("Can't find internal main window. Maybe something has changed inside Unity");
}
/// <summary>
/// Center the EditorWindow in front of the MainUnityWindow (support multi screens).
/// Kept the currend window sizes.
/// </summary>
public static void CenterOnMainWindow(this EditorWindow window)
{
CenterOnWindow(window, null);
}
/// <summary>
/// Center the EditorWindow in front of the given EditorWindow (support multi screens).
/// Kept the currend window sizes.
/// </summary>
/// <param name="relatedWin">Referance window for the positioning.</param>
public static void CenterOnWindow(this EditorWindow window, EditorWindow relatedWin)
{
var main = GetEditorMainWindowPos(relatedWin);
var pos = window.position;
float w = (main.width - pos.width) * 0.5f;
float h = (main.height - pos.height) * 0.5f;
pos.x = main.x + w;
pos.y = main.y + h;
window.position = pos;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 274db1862ad1a1b4c80a2ed6558e05ec
timeCreated: 1502876542
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: e93ef5c4e798b034bb024596113459cb
folderAsset: yes
timeCreated: 1505565882
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,36 @@
namespace BgTools.PlayerPrefsEditor
{
[System.Serializable]
public class PreferenceEntry
{
public enum PrefTypes
{
String = 0,
Int = 1,
Float = 2
}
public PrefTypes m_typeSelection;
public string m_key;
// Need diffrend ones for auto type selection of serilizedProerty
public string m_strValue;
public int m_intValue;
public float m_floatValue;
public string ValueAsString()
{
switch(m_typeSelection)
{
case PrefTypes.String:
return m_strValue;
case PrefTypes.Int:
return m_intValue.ToString();
case PrefTypes.Float:
return m_floatValue.ToString();
default:
return string.Empty;
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2ae9239fbddf12b4099b3cacc5301271
timeCreated: 1496684286
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,29 @@
using System.Collections.Generic;
using UnityEngine;
namespace BgTools.PlayerPrefsEditor
{
[System.Serializable]
public class PreferenceEntryHolder : ScriptableObject
{
public List<PreferenceEntry> userDefList;
public List<PreferenceEntry> unityDefList;
private void OnEnable()
{
hideFlags = HideFlags.DontSave;
if (userDefList == null)
userDefList = new List<PreferenceEntry>();
if (unityDefList == null)
unityDefList = new List<PreferenceEntry>();
}
public void ClearLists()
{
if (userDefList != null)
userDefList.Clear();
if (unityDefList != null)
unityDefList.Clear();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d5d94a5263d6af0478dde8fb08a3dcb7
timeCreated: 1500316993
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,272 @@
using System;
using System.Linq;
#if UNITY_EDITOR_WIN
using Microsoft.Win32;
using System.Text;
#elif UNITY_EDITOR_OSX
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
#elif UNITY_EDITOR_LINUX
using System.IO;
using System.Xml;
using System.Xml.Linq;
#endif
namespace BgTools.PlayerPrefsEditor
{
public abstract class PreferanceStorageAccessor
{
protected string prefPath;
protected string[] cachedData = new string[0];
protected abstract void FetchKeysFromSystem();
protected PreferanceStorageAccessor(string pathToPrefs)
{
prefPath = pathToPrefs;
}
public string[] GetKeys(bool reloadData = true)
{
if (reloadData || cachedData.Length == 0)
{
FetchKeysFromSystem();
}
return cachedData;
}
public Action PrefEntryChangedDelegate;
protected bool ignoreNextChange = false;
public void IgnoreNextChange()
{
ignoreNextChange = true;
}
protected virtual void OnPrefEntryChanged()
{
if (ignoreNextChange)
{
ignoreNextChange = false;
return;
}
PrefEntryChangedDelegate();
}
public Action StartLoadingDelegate;
public Action StopLoadingDelegate;
public abstract void StartMonitoring();
public abstract void StopMonitoring();
public abstract bool IsMonitoring();
}
#if UNITY_EDITOR_WIN
public class WindowsPrefStorage : PreferanceStorageAccessor
{
RegistryMonitor monitor;
public WindowsPrefStorage(string pathToPrefs) : base(pathToPrefs)
{
monitor = new RegistryMonitor(RegistryHive.CurrentUser, prefPath);
monitor.RegChanged += new EventHandler(OnRegChanged);
}
private void OnRegChanged(object sender, EventArgs e)
{
OnPrefEntryChanged();
}
protected override void FetchKeysFromSystem()
{
cachedData = new string[0];
using (RegistryKey rootKey = Registry.CurrentUser.OpenSubKey(prefPath))
{
if (rootKey != null)
{
cachedData = rootKey.GetValueNames();
rootKey.Close();
}
}
// Clean <key>_h3320113488 nameing
cachedData = cachedData.Select((key) => { return key.Substring(0, key.LastIndexOf("_h", StringComparison.Ordinal)); }).ToArray();
EncodeAnsiInPlace();
}
public override void StartMonitoring()
{
monitor.Start();
}
public override void StopMonitoring()
{
monitor.Stop();
}
public override bool IsMonitoring()
{
return monitor.IsMonitoring;
}
private void EncodeAnsiInPlace()
{
Encoding utf8 = Encoding.UTF8;
Encoding ansi = Encoding.GetEncoding(1252);
for (int i = 0; i < cachedData.Length; i++)
{
cachedData[i] = utf8.GetString(ansi.GetBytes(cachedData[i]));
}
}
}
#elif UNITY_EDITOR_LINUX
public class LinuxPrefStorage : PreferanceStorageAccessor
{
FileSystemWatcher fileWatcher;
public LinuxPrefStorage(string pathToPrefs) : base(Path.Combine(Environment.GetEnvironmentVariable("HOME"), pathToPrefs))
{
fileWatcher = new FileSystemWatcher();
fileWatcher.Path = Path.GetDirectoryName(prefPath);
fileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite;
fileWatcher.Filter = "prefs";
fileWatcher.Changed += OnWatchedFileChanged;
}
protected override void FetchKeysFromSystem()
{
cachedData = new string[0];
if (File.Exists(prefPath))
{
XmlReaderSettings settings = new XmlReaderSettings();
XmlReader reader = XmlReader.Create(prefPath, settings);
XDocument doc = XDocument.Load(reader);
cachedData = doc.Element("unity_prefs").Elements().Select((e) => e.Attribute("name").Value).ToArray();
}
}
public override void StartMonitoring()
{
fileWatcher.EnableRaisingEvents = true;
}
public override void StopMonitoring()
{
fileWatcher.EnableRaisingEvents = false;
}
public override bool IsMonitoring()
{
return fileWatcher.EnableRaisingEvents;
}
private void OnWatchedFileChanged(object source, FileSystemEventArgs e)
{
OnPrefEntryChanged();
}
}
#elif UNITY_EDITOR_OSX
public class MacPrefStorage : PreferanceStorageAccessor
{
private FileSystemWatcher fileWatcher;
private DirectoryInfo prefsDirInfo;
private String prefsFileNameWithoutExtension;
public MacPrefStorage(string pathToPrefs) : base(Path.Combine(Environment.GetEnvironmentVariable("HOME"), pathToPrefs))
{
prefsDirInfo = new DirectoryInfo(Path.GetDirectoryName(prefPath));
prefsFileNameWithoutExtension = Path.GetFileNameWithoutExtension(prefPath);
fileWatcher = new FileSystemWatcher();
fileWatcher.Path = Path.GetDirectoryName(prefPath);
fileWatcher.NotifyFilter = NotifyFilters.LastWrite;
fileWatcher.Filter = Path.GetFileName(prefPath);
// MAC delete the old and create a new file instead of updating
fileWatcher.Created += OnWatchedFileChanged;
}
protected override void FetchKeysFromSystem()
{
// Workaround to avoid incomplete tmp phase from MAC OS
foreach (FileInfo info in prefsDirInfo.GetFiles())
{
// Check if tmp PlayerPrefs file exist
if (info.FullName.Contains(prefsFileNameWithoutExtension) && !info.FullName.EndsWith(".plist"))
{
StartLoadingDelegate();
return;
}
}
StopLoadingDelegate();
cachedData = new string[0];
if (File.Exists(prefPath))
{
string fixedPrefsPath = prefPath.Replace("\"", "\\\"").Replace("'", "\\'").Replace("`", "\\`");
var cmdStr = string.Format(@"-p '{0}'", fixedPrefsPath);
string stdOut = String.Empty;
string errOut = String.Empty;
var process = new System.Diagnostics.Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = "plutil";
process.StartInfo.Arguments = cmdStr;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += new DataReceivedEventHandler((sender, evt) => { stdOut += evt.Data + "\n"; });
process.ErrorDataReceived += new DataReceivedEventHandler((sender, evt) => { errOut += evt.Data + "\n"; });
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
MatchCollection matches = Regex.Matches(stdOut, @"(?: "")(.*)(?:"" =>.*)");
cachedData = matches.Cast<Match>().Select((e) => e.Groups[1].Value).ToArray();
}
}
public override void StartMonitoring()
{
fileWatcher.EnableRaisingEvents = true;
}
public override void StopMonitoring()
{
fileWatcher.EnableRaisingEvents = false;
}
public override bool IsMonitoring()
{
return fileWatcher.EnableRaisingEvents;
}
private void OnWatchedFileChanged(object source, FileSystemEventArgs e)
{
OnPrefEntryChanged();
}
}
#endif
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f54241e622579a145a495df929a9330a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,700 @@
using UnityEngine;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEditorInternal;
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using BgTools.Utils;
using BgTools.Dialogs;
#if (UNITY_EDITOR_LINUX || UNITY_EDITOR_OSX)
using System.Text;
using System.Globalization;
#endif
namespace BgTools.PlayerPrefsEditor
{
public class PreferencesEditorWindow : EditorWindow
{
#region ErrorValues
private readonly int ERROR_VALUE_INT = int.MinValue;
private readonly string ERROR_VALUE_STR = "<bgTool_error_24072017>";
#endregion //ErrorValues
private enum PreferencesEntrySortOrder
{
None = 0,
Asscending = 1,
Descending = 2
}
private static string pathToPrefs = String.Empty;
private static string platformPathPrefix = @"~";
private string[] userDef;
private string[] unityDef;
private bool showSystemGroup = false;
private PreferencesEntrySortOrder sortOrder = PreferencesEntrySortOrder.None;
private SerializedObject serializedObject;
private ReorderableList userDefList;
private ReorderableList unityDefList;
private SerializedProperty[] userDefListCache = new SerializedProperty[0];
private PreferenceEntryHolder prefEntryHolder;
private Vector2 scrollPos;
private float relSpliterPos;
private bool moveSplitterPos = false;
private PreferanceStorageAccessor entryAccessor;
private MySearchField searchfield;
private string searchTxt;
private int loadingSpinnerFrame;
private bool updateView = false;
private bool monitoring = false;
private bool showLoadingIndicatorOverlay = false;
private readonly List<TextValidator> prefKeyValidatorList = new List<TextValidator>()
{
new TextValidator(TextValidator.ErrorType.Error, @"Invalid character detected. Only letters, numbers, space and ,.;:<>_|!§$%&/()=?*+~#-]+$ are allowed", @"(^$)|(^[a-zA-Z0-9 ,.;:<>_|!§$%&/()=?*+~#-]+$)"),
new TextValidator(TextValidator.ErrorType.Warning, @"The given key already exist. The existing entry would be overwritten!", (key) => { return !PlayerPrefs.HasKey(key); })
};
#if UNITY_EDITOR_LINUX
private readonly char[] invalidFilenameChars = { '"', '\\', '*', '/', ':', '<', '>', '?', '|' };
#elif UNITY_EDITOR_OSX
private readonly char[] invalidFilenameChars = { '$', '%', '&', '\\', '/', ':', '<', '>', '|', '~' };
#endif
[MenuItem("Tools/BG Tools/PlayerPrefs Editor", false, 1)]
static void ShowWindow()
{
PreferencesEditorWindow window = EditorWindow.GetWindow<PreferencesEditorWindow>(false, "Prefs Editor");
window.minSize = new Vector2(270.0f, 300.0f);
window.name = "Prefs Editor";
//window.titleContent = EditorGUIUtility.IconContent("SettingsIcon"); // Icon
window.Show();
}
private void OnEnable()
{
#if UNITY_EDITOR_WIN
pathToPrefs = @"SOFTWARE\Unity\UnityEditor\" + PlayerSettings.companyName + @"\" + PlayerSettings.productName;
platformPathPrefix = @"<CurrentUser>";
entryAccessor = new WindowsPrefStorage(pathToPrefs);
#elif UNITY_EDITOR_OSX
pathToPrefs = @"Library/Preferences/unity." + MakeValidFileName(PlayerSettings.companyName) + "." + MakeValidFileName(PlayerSettings.productName) + ".plist";
entryAccessor = new MacPrefStorage(pathToPrefs);
entryAccessor.StartLoadingDelegate = () => { showLoadingIndicatorOverlay = true; };
entryAccessor.StopLoadingDelegate = () => { showLoadingIndicatorOverlay = false; };
#elif UNITY_EDITOR_LINUX
pathToPrefs = @".config/unity3d/" + MakeValidFileName(PlayerSettings.companyName) + "/" + MakeValidFileName(PlayerSettings.productName) + "/prefs";
entryAccessor = new LinuxPrefStorage(pathToPrefs);
#endif
entryAccessor.PrefEntryChangedDelegate = () => { updateView = true; };
monitoring = EditorPrefs.GetBool("BGTools.PlayerPrefsEditor.WatchingForChanges", true);
if(monitoring)
entryAccessor.StartMonitoring();
sortOrder = (PreferencesEntrySortOrder) EditorPrefs.GetInt("BGTools.PlayerPrefsEditor.SortOrder", 0);
searchfield = new MySearchField();
searchfield.DropdownSelectionDelegate = () => { PrepareData(); };
// Fix for serialisation issue of static fields
if (userDefList == null)
{
InitReorderedList();
PrepareData();
}
}
// Handel view updates for monitored changes
// Necessary to avoid main thread access issue
private void Update()
{
if (showLoadingIndicatorOverlay)
{
loadingSpinnerFrame = (int)Mathf.Repeat(Time.realtimeSinceStartup * 10, 11.99f);
PrepareData();
Repaint();
}
if (updateView)
{
updateView = false;
PrepareData();
Repaint();
}
}
private void OnDisable()
{
entryAccessor.StopMonitoring();
}
private void InitReorderedList()
{
if (prefEntryHolder == null)
{
var tmp = Resources.FindObjectsOfTypeAll<PreferenceEntryHolder>();
if (tmp.Length > 0)
{
prefEntryHolder = tmp[0];
}
else
{
prefEntryHolder = ScriptableObject.CreateInstance<PreferenceEntryHolder>();
}
}
if (serializedObject == null)
{
serializedObject = new SerializedObject(prefEntryHolder);
}
userDefList = new ReorderableList(serializedObject, serializedObject.FindProperty("userDefList"), false, true, true, true);
unityDefList = new ReorderableList(serializedObject, serializedObject.FindProperty("unityDefList"), false, true, false, false);
relSpliterPos = EditorPrefs.GetFloat("BGTools.PlayerPrefsEditor.RelativeSpliterPosition", 100 / position.width);
userDefList.drawHeaderCallback = (Rect rect) =>
{
EditorGUI.LabelField(rect, "User defined");
};
userDefList.drawElementBackgroundCallback = OnDrawElementBackgroundCallback;
userDefList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
{
SerializedProperty element = GetUserDefListElementAtIndex(index, userDefList.serializedProperty);
SerializedProperty key = element.FindPropertyRelative("m_key");
SerializedProperty type = element.FindPropertyRelative("m_typeSelection");
SerializedProperty value;
// Load only necessary type
switch ((PreferenceEntry.PrefTypes)type.enumValueIndex)
{
case PreferenceEntry.PrefTypes.Float:
value = element.FindPropertyRelative("m_floatValue");
break;
case PreferenceEntry.PrefTypes.Int:
value = element.FindPropertyRelative("m_intValue");
break;
case PreferenceEntry.PrefTypes.String:
value = element.FindPropertyRelative("m_strValue");
break;
default:
value = element.FindPropertyRelative("This should never happen");
break;
}
float spliterPos = relSpliterPos * rect.width;
rect.y += 2;
EditorGUI.BeginChangeCheck();
string prefKeyName = key.stringValue;
EditorGUI.LabelField(new Rect(rect.x, rect.y, spliterPos - 1, EditorGUIUtility.singleLineHeight), new GUIContent(prefKeyName, prefKeyName));
GUI.enabled = false;
EditorGUI.EnumPopup(new Rect(rect.x + spliterPos + 1, rect.y, 60, EditorGUIUtility.singleLineHeight), (PreferenceEntry.PrefTypes)type.enumValueIndex);
GUI.enabled = !showLoadingIndicatorOverlay;
switch ((PreferenceEntry.PrefTypes)type.enumValueIndex)
{
case PreferenceEntry.PrefTypes.Float:
EditorGUI.DelayedFloatField(new Rect(rect.x + spliterPos + 62, rect.y, rect.width - spliterPos - 60, EditorGUIUtility.singleLineHeight), value, GUIContent.none);
break;
case PreferenceEntry.PrefTypes.Int:
EditorGUI.DelayedIntField(new Rect(rect.x + spliterPos + 62, rect.y, rect.width - spliterPos - 60, EditorGUIUtility.singleLineHeight), value, GUIContent.none);
break;
case PreferenceEntry.PrefTypes.String:
EditorGUI.DelayedTextField(new Rect(rect.x + spliterPos + 62, rect.y, rect.width - spliterPos - 60, EditorGUIUtility.singleLineHeight), value, GUIContent.none);
break;
}
if (EditorGUI.EndChangeCheck())
{
entryAccessor.IgnoreNextChange();
switch ((PreferenceEntry.PrefTypes)type.enumValueIndex)
{
case PreferenceEntry.PrefTypes.Float:
PlayerPrefs.SetFloat(key.stringValue, value.floatValue);
break;
case PreferenceEntry.PrefTypes.Int:
PlayerPrefs.SetInt(key.stringValue, value.intValue);
break;
case PreferenceEntry.PrefTypes.String:
PlayerPrefs.SetString(key.stringValue, value.stringValue);
break;
}
PlayerPrefs.Save();
}
};
userDefList.onRemoveCallback = (ReorderableList l) =>
{
userDefList.ReleaseKeyboardFocus();
unityDefList.ReleaseKeyboardFocus();
string prefKey = l.serializedProperty.GetArrayElementAtIndex(l.index).FindPropertyRelative("m_key").stringValue;
if (EditorUtility.DisplayDialog("Warning!", $"Are you sure you want to delete this entry from PlayerPrefs?\n\nEntry: {prefKey}", "Yes", "No"))
{
entryAccessor.IgnoreNextChange();
PlayerPrefs.DeleteKey(prefKey);
PlayerPrefs.Save();
ReorderableList.defaultBehaviours.DoRemoveButton(l);
PrepareData();
GUIUtility.ExitGUI();
}
};
userDefList.onAddDropdownCallback = (Rect buttonRect, ReorderableList l) =>
{
var menu = new GenericMenu();
foreach (PreferenceEntry.PrefTypes type in Enum.GetValues(typeof(PreferenceEntry.PrefTypes)))
{
menu.AddItem(new GUIContent(type.ToString()), false, () =>
{
TextFieldDialog.OpenDialog("Create new property", "Key for the new property:", prefKeyValidatorList, (key) => {
entryAccessor.IgnoreNextChange();
switch (type)
{
case PreferenceEntry.PrefTypes.Float:
PlayerPrefs.SetFloat(key, 0.0f);
break;
case PreferenceEntry.PrefTypes.Int:
PlayerPrefs.SetInt(key, 0);
break;
case PreferenceEntry.PrefTypes.String:
PlayerPrefs.SetString(key, string.Empty);
break;
}
PlayerPrefs.Save();
PrepareData();
Focus();
}, this);
});
}
menu.ShowAsContext();
};
unityDefList.drawElementBackgroundCallback = OnDrawElementBackgroundCallback;
unityDefList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
{
var element = unityDefList.serializedProperty.GetArrayElementAtIndex(index);
SerializedProperty key = element.FindPropertyRelative("m_key");
SerializedProperty type = element.FindPropertyRelative("m_typeSelection");
SerializedProperty value;
// Load only necessary type
switch ((PreferenceEntry.PrefTypes)type.enumValueIndex)
{
case PreferenceEntry.PrefTypes.Float:
value = element.FindPropertyRelative("m_floatValue");
break;
case PreferenceEntry.PrefTypes.Int:
value = element.FindPropertyRelative("m_intValue");
break;
case PreferenceEntry.PrefTypes.String:
value = element.FindPropertyRelative("m_strValue");
break;
default:
value = element.FindPropertyRelative("This should never happen");
break;
}
float spliterPos = relSpliterPos * rect.width;
rect.y += 2;
GUI.enabled = false;
string prefKeyName = key.stringValue;
EditorGUI.LabelField(new Rect(rect.x, rect.y, spliterPos - 1, EditorGUIUtility.singleLineHeight), new GUIContent(prefKeyName, prefKeyName));
EditorGUI.EnumPopup(new Rect(rect.x + spliterPos + 1, rect.y, 60, EditorGUIUtility.singleLineHeight), (PreferenceEntry.PrefTypes)type.enumValueIndex);
switch ((PreferenceEntry.PrefTypes)type.enumValueIndex)
{
case PreferenceEntry.PrefTypes.Float:
EditorGUI.DelayedFloatField(new Rect(rect.x + spliterPos + 62, rect.y, rect.width - spliterPos - 60, EditorGUIUtility.singleLineHeight), value, GUIContent.none);
break;
case PreferenceEntry.PrefTypes.Int:
EditorGUI.DelayedIntField(new Rect(rect.x + spliterPos + 62, rect.y, rect.width - spliterPos - 60, EditorGUIUtility.singleLineHeight), value, GUIContent.none);
break;
case PreferenceEntry.PrefTypes.String:
EditorGUI.DelayedTextField(new Rect(rect.x + spliterPos + 62, rect.y, rect.width - spliterPos - 60, EditorGUIUtility.singleLineHeight), value, GUIContent.none);
break;
}
GUI.enabled = !showLoadingIndicatorOverlay;
};
unityDefList.drawHeaderCallback = (Rect rect) =>
{
EditorGUI.LabelField(rect, "Unity defined");
};
}
private void OnDrawElementBackgroundCallback(Rect rect, int index, bool isActive, bool isFocused)
{
if (Event.current.type == EventType.Repaint)
{
ReorderableList.defaultBehaviours.elementBackground.Draw(rect, false, isActive, isActive, isFocused);
}
Rect spliterRect = new Rect(rect.x + relSpliterPos * rect.width, rect.y, 2, rect.height);
EditorGUIUtility.AddCursorRect(spliterRect, MouseCursor.ResizeHorizontal);
if (Event.current.type == EventType.MouseDown && spliterRect.Contains(Event.current.mousePosition))
{
moveSplitterPos = true;
}
if(moveSplitterPos)
{
if (Event.current.mousePosition.x > 100 && Event.current.mousePosition.x<rect.width - 120)
{
relSpliterPos = Event.current.mousePosition.x / rect.width;
Repaint();
}
}
if (Event.current.type == EventType.MouseUp)
{
moveSplitterPos = false;
EditorPrefs.SetFloat("BGTools.PlayerPrefsEditor.RelativeSpliterPosition", relSpliterPos);
}
}
void OnGUI()
{
// Need to catch 'Stack empty' error on linux
try
{
if (showLoadingIndicatorOverlay)
{
GUI.enabled = false;
}
Color defaultColor = GUI.contentColor;
if (!EditorGUIUtility.isProSkin)
{
GUI.contentColor = Styles.Colors.DarkGray;
}
GUILayout.BeginVertical();
GUILayout.BeginHorizontal(EditorStyles.toolbar);
EditorGUI.BeginChangeCheck();
searchTxt = searchfield.OnToolbarGUI(searchTxt);
if (EditorGUI.EndChangeCheck())
{
PrepareData(false);
}
GUILayout.FlexibleSpace();
EditorGUIUtility.SetIconSize(new Vector2(14.0f, 14.0f));
GUIContent sortOrderContent;
switch (sortOrder)
{
case PreferencesEntrySortOrder.Asscending:
sortOrderContent = new GUIContent(ImageManager.SortAsscending, "Ascending sorted");
break;
case PreferencesEntrySortOrder.Descending:
sortOrderContent = new GUIContent(ImageManager.SortDescending, "Descending sorted");
break;
case PreferencesEntrySortOrder.None:
default:
sortOrderContent = new GUIContent(ImageManager.SortDisabled, "Not sorted");
break;
}
if (GUILayout.Button(sortOrderContent, EditorStyles.toolbarButton))
{
sortOrder++;
if((int) sortOrder >= Enum.GetValues(typeof(PreferencesEntrySortOrder)).Length)
{
sortOrder = 0;
}
EditorPrefs.SetInt("BGTools.PlayerPrefsEditor.SortOrder", (int) sortOrder);
PrepareData(false);
}
GUIContent watcherContent = (entryAccessor.IsMonitoring()) ? new GUIContent(ImageManager.Watching, "Watching changes") : new GUIContent(ImageManager.NotWatching, "Not watching changes");
if (GUILayout.Button(watcherContent, EditorStyles.toolbarButton))
{
monitoring = !monitoring;
EditorPrefs.SetBool("BGTools.PlayerPrefsEditor.WatchingForChanges", monitoring);
if (monitoring)
entryAccessor.StartMonitoring();
else
entryAccessor.StopMonitoring();
Repaint();
}
if (GUILayout.Button(new GUIContent(ImageManager.Refresh, "Refresh"), EditorStyles.toolbarButton))
{
PlayerPrefs.Save();
PrepareData();
}
if (GUILayout.Button(new GUIContent(ImageManager.Trash, "Delete all"), EditorStyles.toolbarButton))
{
if (EditorUtility.DisplayDialog("Warning!", "Are you sure you want to delete ALL entries from PlayerPrefs?\n\nUse with caution! Unity defined keys are affected too.", "Yes", "No"))
{
PlayerPrefs.DeleteAll();
PrepareData();
GUIUtility.ExitGUI();
}
}
EditorGUIUtility.SetIconSize(new Vector2(0.0f, 0.0f));
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Box(ImageManager.GetOsIcon(), Styles.icon);
GUILayout.TextField(platformPathPrefix + Path.DirectorySeparatorChar + pathToPrefs, GUILayout.MinWidth(200));
GUILayout.EndHorizontal();
scrollPos = GUILayout.BeginScrollView(scrollPos);
serializedObject.Update();
userDefList.DoLayoutList();
serializedObject.ApplyModifiedProperties();
GUILayout.FlexibleSpace();
showSystemGroup = EditorGUILayout.Foldout(showSystemGroup, new GUIContent("Show System"));
if (showSystemGroup)
{
unityDefList.DoLayoutList();
}
GUILayout.EndScrollView();
GUILayout.EndVertical();
GUI.enabled = true;
if (showLoadingIndicatorOverlay)
{
GUILayout.BeginArea(new Rect(position.size.x * 0.5f - 30, position.size.y * 0.5f - 25, 60, 50), GUI.skin.box);
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.Box(ImageManager.SpinWheelIcons[loadingSpinnerFrame], Styles.icon);
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUILayout.Label("Loading");
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.FlexibleSpace();
GUILayout.EndArea();
}
GUI.contentColor = defaultColor;
}
catch (InvalidOperationException)
{ }
}
private void PrepareData(bool reloadKeys = true)
{
prefEntryHolder.ClearLists();
LoadKeys(out userDef, out unityDef, reloadKeys);
CreatePrefEntries(userDef, ref prefEntryHolder.userDefList);
CreatePrefEntries(unityDef, ref prefEntryHolder.unityDefList);
// Clear cache
userDefListCache = new SerializedProperty[prefEntryHolder.userDefList.Count];
}
private void CreatePrefEntries(string[] keySource, ref List<PreferenceEntry> listDest)
{
if (!string.IsNullOrEmpty(searchTxt) && searchfield.SearchMode == MySearchField.SearchModePreferencesEditorWindow.Key)
{
keySource = keySource.Where((keyEntry) => keyEntry.ToLower().Contains(searchTxt.ToLower())).ToArray();
}
foreach (string key in keySource)
{
var entry = new PreferenceEntry();
entry.m_key = key;
string s = PlayerPrefs.GetString(key, ERROR_VALUE_STR);
if (s != ERROR_VALUE_STR)
{
entry.m_strValue = s;
entry.m_typeSelection = PreferenceEntry.PrefTypes.String;
listDest.Add(entry);
continue;
}
float f = PlayerPrefs.GetFloat(key, float.NaN);
if (!float.IsNaN(f))
{
entry.m_floatValue = f;
entry.m_typeSelection = PreferenceEntry.PrefTypes.Float;
listDest.Add(entry);
continue;
}
int i = PlayerPrefs.GetInt(key, ERROR_VALUE_INT);
if (i != ERROR_VALUE_INT)
{
entry.m_intValue = i;
entry.m_typeSelection = PreferenceEntry.PrefTypes.Int;
listDest.Add(entry);
continue;
}
}
if (!string.IsNullOrEmpty(searchTxt) && searchfield.SearchMode == MySearchField.SearchModePreferencesEditorWindow.Value)
{
listDest = listDest.Where((preferenceEntry) => preferenceEntry.ValueAsString().ToLower().Contains(searchTxt.ToLower())).ToList<PreferenceEntry>();
}
switch(sortOrder)
{
case PreferencesEntrySortOrder.Asscending:
listDest.Sort((PreferenceEntry x, PreferenceEntry y) => { return x.m_key.CompareTo(y.m_key); });
break;
case PreferencesEntrySortOrder.Descending:
listDest.Sort((PreferenceEntry x, PreferenceEntry y) => { return y.m_key.CompareTo(x.m_key); });
break;
}
}
private void LoadKeys(out string[] userDef, out string[] unityDef, bool reloadKeys)
{
string[] keys = entryAccessor.GetKeys(reloadKeys);
//keys.ToList().ForEach( e => { Debug.Log(e); } );
// Seperate keys int unity defined and user defined
Dictionary<bool, List<string>> groups = keys
.GroupBy( (key) => key.StartsWith("unity.") || key.StartsWith("UnityGraphicsQuality") )
.ToDictionary( (g) => g.Key, (g) => g.ToList() );
unityDef = (groups.ContainsKey(true)) ? groups[true].ToArray() : new string[0];
userDef = (groups.ContainsKey(false)) ? groups[false].ToArray() : new string[0];
}
private SerializedProperty GetUserDefListElementAtIndex(int index, SerializedProperty ListProperty)
{
UnityEngine.Assertions.Assert.IsTrue(ListProperty.isArray, "Given 'ListProperts' is not type of array");
if (userDefListCache[index] == null)
{
userDefListCache[index] = ListProperty.GetArrayElementAtIndex(index);
}
return userDefListCache[index];
}
#if (UNITY_EDITOR_LINUX || UNITY_EDITOR_OSX)
private string MakeValidFileName(string unsafeFileName)
{
string normalizedFileName = unsafeFileName.Trim().Normalize(NormalizationForm.FormD);
StringBuilder stringBuilder = new StringBuilder();
// We need to use a TextElementEmumerator in order to support UTF16 characters that may take up more than one char(case 1169358)
TextElementEnumerator charEnum = StringInfo.GetTextElementEnumerator(normalizedFileName);
while (charEnum.MoveNext())
{
string c = charEnum.GetTextElement();
if (c.Length == 1 && invalidFilenameChars.Contains(c[0]))
{
stringBuilder.Append('_');
continue;
}
UnicodeCategory unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c, 0);
if (unicodeCategory != UnicodeCategory.NonSpacingMark)
stringBuilder.Append(c);
}
return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}
#endif
}
}
public class MySearchField : SearchField
{
public enum SearchModePreferencesEditorWindow { Key, Value }
public SearchModePreferencesEditorWindow SearchMode { get; private set; }
public Action DropdownSelectionDelegate;
public new string OnGUI(
Rect rect,
string text,
GUIStyle style,
GUIStyle cancelButtonStyle,
GUIStyle emptyCancelButtonStyle)
{
style.padding.left = 17;
Rect ContextMenuRect = new Rect(rect.x, rect.y, 10, rect.height);
// Add interactive area
EditorGUIUtility.AddCursorRect(ContextMenuRect, MouseCursor.Text);
if (Event.current.type == EventType.MouseDown && ContextMenuRect.Contains(Event.current.mousePosition))
{
void OnDropdownSelection(object parameter)
{
SearchMode = (SearchModePreferencesEditorWindow) Enum.Parse(typeof(SearchModePreferencesEditorWindow), parameter.ToString());
DropdownSelectionDelegate();
}
GenericMenu menu = new GenericMenu();
foreach(SearchModePreferencesEditorWindow EnumIt in Enum.GetValues(typeof(SearchModePreferencesEditorWindow)))
{
String EnumName = Enum.GetName(typeof(SearchModePreferencesEditorWindow), EnumIt);
menu.AddItem(new GUIContent(EnumName), SearchMode == EnumIt, OnDropdownSelection, EnumName);
}
menu.DropDown(rect);
}
// Render original search field
String result = base.OnGUI(rect, text, style, cancelButtonStyle, emptyCancelButtonStyle);
// Render additional images
GUIStyle ContexMenuOverlayStyle = GUIStyle.none;
ContexMenuOverlayStyle.contentOffset = new Vector2(9, 5);
GUI.Box(new Rect(rect.x, rect.y, 5, 5), EditorGUIUtility.IconContent("d_ProfilerTimelineDigDownArrow@2x"), ContexMenuOverlayStyle);
if (!HasFocus() && String.IsNullOrEmpty(text))
{
GUI.enabled = false;
GUI.Label(new Rect(rect.x + 14, rect.y, 40, rect.height), Enum.GetName(typeof(SearchModePreferencesEditorWindow), SearchMode));
GUI.enabled = true;
}
ContexMenuOverlayStyle.contentOffset = new Vector2();
return result;
}
public new string OnToolbarGUI(string text, params GUILayoutOption[] options) => this.OnToolbarGUI(GUILayoutUtility.GetRect(29f, 200f, 18f, 18f, EditorStyles.toolbarSearchField, options), text);
public new string OnToolbarGUI(Rect rect, string text) => this.OnGUI(rect, text, EditorStyles.toolbarSearchField, EditorStyles.toolbarButton, EditorStyles.toolbarButton);
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 13c94fa190e7e6f4690cadc347a312aa
timeCreated: 1496263475
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,364 @@
/*
* Thanks to gr0ss for the inspiration.
*
* https://github.com/gr0ss/RegistryMonitor
*
* 11/08/2019
*/
using System;
using System.ComponentModel;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace BgTools.PlayerPrefsEditor
{
public class RegistryMonitor : IDisposable
{
#region P/Invoke
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int RegOpenKeyEx(IntPtr hKey, string subKey, uint options, int samDesired, out IntPtr phkResult);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegNotifyChangeKeyValue(IntPtr hKey, bool bWatchSubtree, RegChangeNotifyFilter dwNotifyFilter, IntPtr hEvent, bool fAsynchronous);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegCloseKey(IntPtr hKey);
private const int KEY_QUERY_VALUE = 0x0001;
private const int KEY_NOTIFY = 0x0010;
private const int STANDARD_RIGHTS_READ = 0x00020000;
private static readonly IntPtr HKEY_CLASSES_ROOT = new IntPtr(unchecked((int)0x80000000));
private static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int)0x80000001));
private static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002));
private static readonly IntPtr HKEY_USERS = new IntPtr(unchecked((int)0x80000003));
private static readonly IntPtr HKEY_PERFORMANCE_DATA = new IntPtr(unchecked((int)0x80000004));
private static readonly IntPtr HKEY_CURRENT_CONFIG = new IntPtr(unchecked((int)0x80000005));
private static readonly IntPtr HKEY_DYN_DATA = new IntPtr(unchecked((int)0x80000006));
#endregion
#region Event handling
/// <summary>
/// Occurs when the specified registry key has changed.
/// </summary>
public event EventHandler RegChanged;
/// <summary>
/// Raises the <see cref="RegChanged"/> event.
/// </summary>
/// <remarks>
/// <p>
/// <b>OnRegChanged</b> is called when the specified registry key has changed.
/// </p>
/// <note type="inheritinfo">
/// When overriding <see cref="OnRegChanged"/> in a derived class, be sure to call
/// the base class's <see cref="OnRegChanged"/> method.
/// </note>
/// </remarks>
protected virtual void OnRegChanged()
{
EventHandler handler = RegChanged;
if (handler != null)
handler(this, null);
}
/// <summary>
/// Occurs when the access to the registry fails.
/// </summary>
public event ErrorEventHandler Error;
/// <summary>
/// Raises the <see cref="Error"/> event.
/// </summary>
/// <param name="e">The <see cref="Exception"/> which occured while watching the registry.</param>
/// <remarks>
/// <p>
/// <b>OnError</b> is called when an exception occurs while watching the registry.
/// </p>
/// <note type="inheritinfo">
/// When overriding <see cref="OnError"/> in a derived class, be sure to call
/// the base class's <see cref="OnError"/> method.
/// </note>
/// </remarks>
protected virtual void OnError(Exception e)
{
ErrorEventHandler handler = Error;
if (handler != null)
handler(this, new ErrorEventArgs(e));
}
#endregion
#region Private member variables
private IntPtr _registryHive;
private string _registrySubName;
private object _threadLock = new object();
private Thread _thread;
private bool _disposed = false;
private ManualResetEvent _eventTerminate = new ManualResetEvent(false);
private RegChangeNotifyFilter _regFilter = RegChangeNotifyFilter.Key | RegChangeNotifyFilter.Attribute | RegChangeNotifyFilter.Value | RegChangeNotifyFilter.Security;
#endregion
/// <summary>
/// Initializes a new instance of the <see cref="RegistryMonitor"/> class.
/// </summary>
/// <param name="registryKey">The registry key to monitor.</param>
public RegistryMonitor(RegistryKey registryKey)
{
InitRegistryKey(registryKey.Name);
}
/// <summary>
/// Initializes a new instance of the <see cref="RegistryMonitor"/> class.
/// </summary>
/// <param name="name">The name.</param>
public RegistryMonitor(string name)
{
if (name == null || name.Length == 0)
throw new ArgumentNullException("name");
InitRegistryKey(name);
}
/// <summary>
/// Initializes a new instance of the <see cref="RegistryMonitor"/> class.
/// </summary>
/// <param name="registryHive">The registry hive.</param>
/// <param name="subKey">The sub key.</param>
public RegistryMonitor(RegistryHive registryHive, string subKey)
{
InitRegistryKey(registryHive, subKey);
}
/// <summary>
/// Disposes this object.
/// </summary>
public void Dispose()
{
Stop();
_disposed = true;
GC.SuppressFinalize(this);
}
/// <summary>
/// Gets or sets the <see cref="RegChangeNotifyFilter">RegChangeNotifyFilter</see>.
/// </summary>
public RegChangeNotifyFilter RegChangeNotifyFilter
{
get { return _regFilter; }
set
{
lock (_threadLock)
{
if (IsMonitoring)
throw new InvalidOperationException("Monitoring thread is already running");
_regFilter = value;
}
}
}
#region Initialization
private void InitRegistryKey(RegistryHive hive, string name)
{
switch (hive)
{
case RegistryHive.ClassesRoot:
_registryHive = HKEY_CLASSES_ROOT;
break;
case RegistryHive.CurrentConfig:
_registryHive = HKEY_CURRENT_CONFIG;
break;
case RegistryHive.CurrentUser:
_registryHive = HKEY_CURRENT_USER;
break;
case RegistryHive.DynData:
_registryHive = HKEY_DYN_DATA;
break;
case RegistryHive.LocalMachine:
_registryHive = HKEY_LOCAL_MACHINE;
break;
case RegistryHive.PerformanceData:
_registryHive = HKEY_PERFORMANCE_DATA;
break;
case RegistryHive.Users:
_registryHive = HKEY_USERS;
break;
default:
throw new InvalidEnumArgumentException("hive", (int)hive, typeof(RegistryHive));
}
_registrySubName = name;
}
private void InitRegistryKey(string name)
{
string[] nameParts = name.Split('\\');
switch (nameParts[0])
{
case "HKEY_CLASSES_ROOT":
case "HKCR":
_registryHive = HKEY_CLASSES_ROOT;
break;
case "HKEY_CURRENT_USER":
case "HKCU":
_registryHive = HKEY_CURRENT_USER;
break;
case "HKEY_LOCAL_MACHINE":
case "HKLM":
_registryHive = HKEY_LOCAL_MACHINE;
break;
case "HKEY_USERS":
_registryHive = HKEY_USERS;
break;
case "HKEY_CURRENT_CONFIG":
_registryHive = HKEY_CURRENT_CONFIG;
break;
default:
_registryHive = IntPtr.Zero;
throw new ArgumentException("The registry hive '" + nameParts[0] + "' is not supported", "value");
}
_registrySubName = String.Join("\\", nameParts, 1, nameParts.Length - 1);
}
#endregion
/// <summary>
/// <b>true</b> if this <see cref="RegistryMonitor"/> object is currently monitoring;
/// otherwise, <b>false</b>.
/// </summary>
public bool IsMonitoring
{
get { return _thread != null; }
}
/// <summary>
/// Start monitoring.
/// </summary>
public void Start()
{
if (_disposed)
throw new ObjectDisposedException(null, "This instance is already disposed");
lock (_threadLock)
{
if (!IsMonitoring)
{
_eventTerminate.Reset();
_thread = new Thread(new ThreadStart(MonitorThread)) { IsBackground = true };
_thread.Start();
}
}
}
/// <summary>
/// Stops the monitoring thread.
/// </summary>
public void Stop()
{
if (_disposed)
throw new ObjectDisposedException(null, "This instance is already disposed");
lock (_threadLock)
{
Thread thread = _thread;
if (thread != null)
{
_eventTerminate.Set();
thread.Join();
}
}
}
private void MonitorThread()
{
try
{
ThreadLoop();
}
catch (Exception e)
{
OnError(e);
}
_thread = null;
}
private void ThreadLoop()
{
IntPtr registryKey;
int result = RegOpenKeyEx(_registryHive, _registrySubName, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_NOTIFY, out registryKey);
if (result != 0)
{
throw new Win32Exception(result);
}
try
{
AutoResetEvent _eventNotify = new AutoResetEvent(false);
WaitHandle[] waitHandles = new WaitHandle[] { _eventNotify, _eventTerminate };
while (!_eventTerminate.WaitOne(0, true))
{
result = RegNotifyChangeKeyValue(registryKey, true, _regFilter, _eventNotify.SafeWaitHandle.DangerousGetHandle(), true);
if (result != 0)
{
throw new Win32Exception(result);
}
if (WaitHandle.WaitAny(waitHandles) == 0)
{
OnRegChanged();
}
}
}
finally
{
if (registryKey != IntPtr.Zero)
{
RegCloseKey(registryKey);
}
}
}
}
/// <summary>
/// Filter for notifications reported by <see cref="RegistryMonitor"/>.
/// </summary>
[Flags]
public enum RegChangeNotifyFilter
{
/// <summary>Notify the caller if a subkey is added or deleted.</summary>
Key = 1,
/// <summary>Notify the caller of changes to the attributes of the key,
/// such as the security descriptor information.</summary>
Attribute = 2,
/// <summary>Notify the caller of changes to a value of the key. This can
/// include adding or deleting a value, or changing an existing value.</summary>
Value = 4,
/// <summary>Notify the caller of changes to the security descriptor
/// of the key.</summary>
Security = 8,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c38f17e357d98d4296b689ae716240b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,109 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace BgTools.Utils
{
public class Styles
{
#region Colors
public class Colors {
public static Color DarkGray = new Color(0.09f, 0.09f, 0.09f);
public static Color LightGray = new Color(0.65f, 0.65f, 0.65f);
public static Color Red = new Color(1.00f, 0.00f, 0.00f);
public static Color Yellow = new Color(1.00f, 1.00f, 0.00f);
public static Color Blue = new Color(0.00f, 0.63f, 0.99f);
}
#endregion // Colors
#region Texture manager
static Dictionary<long, Texture2D> mTextures = new Dictionary<long, Texture2D>();
public static Texture2D GetTexture(long pColorRGBA)
{
if (mTextures.ContainsKey(pColorRGBA) && mTextures[pColorRGBA] != null)
return mTextures[pColorRGBA];
Color32 c = GetColor(pColorRGBA);
var texture = new Texture2D(4, 4);
for (int x = 0; x < 4; x++)
for (int y = 0; y < 4; y++)
texture.SetPixel(x, y, c);
texture.Apply();
texture.Compress(true);
mTextures[pColorRGBA] = texture;
return texture;
}
private static Color32 GetColor(long pColorRGBA)
{
byte r = (byte)((pColorRGBA & 0xff000000) >> 24);
byte g = (byte)((pColorRGBA & 0xff0000) >> 16);
byte b = (byte)((pColorRGBA & 0xff00) >> 8);
byte a = (byte)((pColorRGBA & 0xff));
Color32 c = new Color32(r, g, b, a);
return c;
}
#endregion Texture manager
static GUIStyle mHSeparator;
private static GUIStyle hSeparator
{
get
{
if (mHSeparator == null)
{
mHSeparator = new GUIStyle();
mHSeparator.alignment = TextAnchor.MiddleCenter;
mHSeparator.stretchWidth = true;
mHSeparator.fixedHeight = 1;
mHSeparator.margin = new RectOffset(20, 20, 5, 5);
mHSeparator.normal.background = (EditorGUIUtility.isProSkin) ? GetTexture(0xb5b5b5ff) : GetTexture(0x000000ff);
}
return mHSeparator;
}
}
public static void HorizontalSeparator()
{
GUILayout.Label("", hSeparator);
}
static GUIStyle Icon;
public static GUIStyle icon
{
get
{
if (Icon == null)
{
Icon = new GUIStyle();
Icon.fixedWidth = 15.0f;
Icon.fixedHeight = 15.0f;
Icon.margin = new RectOffset(2, 2, 2, 2);
}
return Icon;
}
}
static GUIStyle MiniButton;
public static GUIStyle miniButton
{
get
{
if (MiniButton == null)
{
MiniButton = new GUIStyle(GUI.skin.button);
MiniButton.fixedWidth = 15.0f;
MiniButton.fixedHeight = 15.0f;
MiniButton.margin = new RectOffset(2, 2, 2, 2);
MiniButton.padding = new RectOffset(2, 2, 2, 2);
}
return MiniButton;
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: be53f59c705f7434a9d6581d0746990f
timeCreated: 1496670894
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,16 @@
{
"name": "Unity.PlayerPrefsEditor.Editor",
"references": [
"Unity.PlayerPrefsEditor.EditorResources"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 516df2812c38a7348b10d202b71bf483
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,71 @@
# PlayerPrefs Editor for Unity 3D
[![Minimal unity editor version](https://img.shields.io/badge/UnityEditor-2019.4%20or%20later-blue.svg)](https://unity3d.com/de/get-unity/download/archive)
[![CI](https://github.com/Dysman/bgTools-playerPrefsEditor/workflows/CI/badge.svg)](https://github.com/Dysman/bgTools-playerPrefsEditor/actions)&nbsp;&nbsp;
[![Release](https://img.shields.io/github/v/release/Dysman/bgTools-playerPrefsEditor?include_prereleases&label=Release)](https://github.com/Dysman/bgTools-playerPrefsEditor/releases)
[![GitHub package.json version (branch)](https://img.shields.io/github/package-json/v/dysman/bgTools-playerPrefsEditor/upm?label=GitURL-UPM)](https://github.com/Dysman/bgTools-playerPrefsEditor/tree/upm)
[![openupm](https://img.shields.io/npm/v/com.bgtools.playerprefseditor?label=OpenUPM&registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.bgtools.playerprefseditor)
[![AssetStore](https://img.shields.io/badge/dynamic/xml?url=http://u3d.as/1RLa&label=UnityAssetStore&query=//*[contains(@class,%20%27product-version%27)]/div[2]&prefix=v)](http://u3d.as/1RLa)
[![Flattr this git repo](https://img.shields.io/badge/_-Flattr-green?logo=flattr&style=flat)](https://flattr.com/@dysman)&nbsp;
[![Buy me a coffee](https://img.shields.io/badge/-Buy%20Me%20A%20Coffee-yellow?logo=BuyMeACoffee&style=flat&logoColor=white)](https://www.buymeacoffee.com/dysman)
[<img align="right" src="https://img.shields.io/discord/431522155814191116?logo=Discord&logoColor=white&style=flat&label=Discord&labelColor=5865F2">](https://discord.gg/8rcPZrD)
Tool extension for the Unity Editor that enables easy access to the player preferences over a simple UI. Allows to view, add, remove and modify entries on the development machine.
![Preference editor window](https://www.bgranzow.de/downloads/PlayerPrefsEditorV1_2_0.png)
## Features
* Add, remove and edit PlayerPrefs
* Intuitive visual editor
* Works with standard Unity PlayerPrefs
* Monitors changes from code
* Supports all editors (Windows, Linux, MacOS)
* Lightweight dockable for full integration in your workflow
* Supports both skins (Personal, Professional)
## Requirements
Unity Version: 2019.4 (LTS) or higher
Editor Version: Windows, MacOS, Linux
## Installation
The plugin provides *manual* and *UPM* installation.
Additionally it's available on the [Unity Asset Store](http://u3d.as/1RLa).
### Manual
Place the PlayerPrefsEditor folder somewhere in your project. It's not relevant where it's located, the plugin will find all of its files by itself.
### Unity Package Manager (UPM)
**Via Git URL**
Through the Unity Plugin Manager it's possible to install the plugin direct from this git repository.
The UPM need a specific structure what will be provided into the *upm* branch.
Use following direct URL for the configuration:
```
https://github.com/Dysman/bgTools-playerPrefsEditor.git#upm
```
See official Unity documentation for more informations: [UI](https://docs.unity3d.com/Manual/upm-ui-giturl.html) or [manifest.json](https://docs.unity3d.com/Manual/upm-git.html)
**Via OpenUPM**
The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
```
openupm add com.bgtools.playerprefseditor
```
## Usage
The entry to open the _PlayerPrefs Editor_ is located in the top menu at Tools/BG Tools/PlayerPrefs Editor. It's a standard dockable window, so place it wherever it helps to be productive.
A more detailed manual can be fund in following locations:
* GitHub (Manual)- [Manual page](Packages/PlayerPrefsEditor/Documentation~/PlayerPrefsEditor.md)
* GitHub (UPM) - Press the _Documentation_ link on the UPM description.
* Unity Asset Store Package - [MANUAL.html](Documentation/MANUAL.html)

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3b2e0e2a0041b58458afaba08099fba4
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 70d87455559ee7d4d9abd1153e42ed4f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 16180e12a1ec47a4fb2cc753af98d39e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,53 @@
using UnityEngine;
public class PlayerPrefsController : MonoBehaviour
{
#region Add
public void AddTestStrings()
{
PlayerPrefs.SetString("Runtime_String", "boing");
PlayerPrefs.SetString("Runtime_String2", "foo");
PlayerPrefs.Save();
}
public void AddTestInt()
{
PlayerPrefs.SetInt("Runtime_Int", 1234);
PlayerPrefs.Save();
}
public void AddTestFloat()
{
PlayerPrefs.SetFloat("Runtime_Float", 3.14f);
PlayerPrefs.Save();
}
#endregion
#region Remove
public void RemoveTestStrings()
{
PlayerPrefs.DeleteKey("Runtime_String");
PlayerPrefs.DeleteKey("Runtime_String2");
PlayerPrefs.Save();
}
public void RemoveTestInt()
{
PlayerPrefs.DeleteKey("Runtime_Int");
PlayerPrefs.Save();
}
public void RemoveTestFloat()
{
PlayerPrefs.DeleteKey("Runtime_Float");
PlayerPrefs.Save();
}
public void DeleteAll()
{
PlayerPrefs.DeleteAll();
PlayerPrefs.Save();
}
#endregion
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4004328c339a7cb4fb509e2e5f789688
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fba661fc32606eb498ae23fd271867b4
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,12 @@
{
"name": "Unity.PlayerPrefsEditor.Samples.SampleScene",
"references": [],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7bb1abbf070c8e248939f8fd7910665f
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -551,8 +551,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: -0.000000059604645, y: 0.0017561307}
m_SizeDelta: {x: 0.07884375, y: 0.023220634}
m_AnchoredPosition: {x: -0.012199998, y: 0.000010974}
m_SizeDelta: {x: 0.1071, y: 0.055959}
m_Pivot: {x: 1, y: 0.5}
--- !u!222 &4375764189645613010
CanvasRenderer:
@ -613,10 +613,10 @@ MonoBehaviour:
m_fontSizeBase: 24
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 0.013
m_fontSizeMax: 72
m_fontSizeMin: 0
m_fontSizeMax: 0.013
m_fontStyle: 0
m_HorizontalAlignment: 2
m_HorizontalAlignment: 4
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0

View File

@ -30,7 +30,8 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Children:
- {fileID: 4733192165402058877}
m_Father: {fileID: 2882185551071933227}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
@ -66,7 +67,7 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: cf0c940affaed0343addeb27cfe40f18, type: 3}
m_Sprite: {fileID: 21300000, guid: 6eddef3eb7af0b6448a33bb6cc9f3ce7, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
@ -196,6 +197,140 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &628336878074005513
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4733192165402058877}
- component: {fileID: 2479592549992414541}
- component: {fileID: 6267404306144524776}
m_Layer: 0
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4733192165402058877
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 628336878074005513}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3922095184631678752}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0.000016406178, y: -0.00000035390258}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2479592549992414541
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 628336878074005513}
m_CullTransparentMesh: 1
--- !u!114 &6267404306144524776
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 628336878074005513}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Report
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 9f7cb4b53799717478f208258f1af701, type: 2}
m_sharedMaterial: {fileID: -7900421164380424285, guid: 9f7cb4b53799717478f208258f1af701, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 0.02
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 0.02
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &3101398570080196502
GameObject:
m_ObjectHideFlags: 0
@ -620,6 +755,140 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 5e486cfb8f5242f4bb3541192679bd01, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &5457314699651149857
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2314724864024842285}
- component: {fileID: 5896535499790842280}
- component: {fileID: 7111021026495527410}
m_Layer: 0
m_Name: Text (TMP) (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2314724864024842285
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5457314699651149857}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 3673808098535714965}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0.000024020672, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5896535499790842280
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5457314699651149857}
m_CullTransparentMesh: 1
--- !u!114 &7111021026495527410
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5457314699651149857}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Ignore
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 9f7cb4b53799717478f208258f1af701, type: 2}
m_sharedMaterial: {fileID: -7900421164380424285, guid: 9f7cb4b53799717478f208258f1af701, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 0.02
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 1
m_fontSizeMin: 0.02
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &5764583576712336997
GameObject:
m_ObjectHideFlags: 0
@ -1004,7 +1273,8 @@ RectTransform:
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Children:
- {fileID: 2314724864024842285}
m_Father: {fileID: 2882185551071933227}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0}
@ -1040,7 +1310,7 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 7d963cec70ccd274fb5ae9af8c7f3f64, type: 3}
m_Sprite: {fileID: 21300000, guid: 6eddef3eb7af0b6448a33bb6cc9f3ce7, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,9 @@ MonoBehaviour:
senderName: HR Department
senderEmail: hr@yourcompany.com
subject: May HR Newsletter Available
subjectAr: "\u0646\u0634\u0631\u0629 \u0627\u0644\u0645\u0648\u0627\u0631\u062F
\u0627\u0644\u0628\u0634\u0631\u064A\u0629 \u0644\u0634\u0647\u0631 \u0645\u0627\u064A\u0648
\u0645\u062A\u0648\u0641\u0631\u0629"
fullBodyText: "Hello Everyone,\n\nWe\u2019re excited to bring you the May edition
of our HR Newsletter! This month\u2019s issue includes wellness challenges to
help you stay active, updates on remote work policy extensions, employee spotlight
@ -23,7 +26,36 @@ MonoBehaviour:
review the newly updated policy on hybrid attendance and submit your feedback
by next week. The first 50 employees to complete the Wellness Bingo will receive
a surprise reward!\n\n\u2013 HR Team"
fullBodyTextAr: "\u0645\u0631\u062D\u0628\u0627\u064B \u0628\u0627\u0644\u062C\u0645\u064A\u0639\u060C\n\n\u064A\u0633\u0639\u062F\u0646\u0627
\u0623\u0646 \u0646\u0642\u062F\u0645 \u0644\u0643\u0645 \u0625\u0635\u062F\u0627\u0631
\u0634\u0647\u0631 \u0645\u0627\u064A\u0648 \u0645\u0646 \u0646\u0634\u0631\u062A\u0646\u0627
\u0627\u0644\u0625\u062E\u0628\u0627\u0631\u064A\u0629 \u0644\u0644\u0645\u0648\u0627\u0631\u062F
\u0627\u0644\u0628\u0634\u0631\u064A\u0629! \u064A\u062A\u0636\u0645\u0646 \u0639\u062F\u062F
\u0647\u0630\u0627 \u0627\u0644\u0634\u0647\u0631 \u062A\u062D\u062F\u064A\u0627\u062A
\u0635\u062D\u064A\u0629 \u0644\u0645\u0633\u0627\u0639\u062F\u062A\u0643\u0645
\u0639\u0644\u0649 \u0627\u0644\u0628\u0642\u0627\u0621 \u0646\u0634\u064A\u0637\u064A\u0646\u060C
\u0648\u062A\u062D\u062F\u064A\u062B\u0627\u062A \u0628\u0634\u0623\u0646 \u062A\u0645\u062F\u064A\u062F
\u0633\u064A\u0627\u0633\u0629 \u0627\u0644\u0639\u0645\u0644 \u0639\u0646 \u0628\u064F\u0639\u062F\u060C
\u0648\u0642\u0635\u0635 \u062A\u0633\u0644\u0637 \u0627\u0644\u0636\u0648\u0621
\u0639\u0644\u0649 \u0628\u0639\u0636 \u0627\u0644\u0645\u0648\u0638\u0641\u064A\u0646\u060C
\u0648\u0623\u0646\u0634\u0637\u0629 \u0642\u0627\u062F\u0645\u0629 \u0644\u0628\u0646\u0627\u0621
\u0631\u0648\u062D \u0627\u0644\u0641\u0631\u064A\u0642. \u062A\u0623\u0643\u062F\u0648\u0627
\u0645\u0646 \u0632\u064A\u0627\u0631\u0629 \u0628\u0648\u0627\u0628\u0629 \u0627\u0644\u0645\u0648\u0627\u0631\u062F
\u0627\u0644\u0628\u0634\u0631\u064A\u0629 \u0644\u0645\u0639\u0631\u0641\u0629
\u0645\u0646 \u064A\u062D\u062A\u0641\u0644 \u0628\u0630\u0643\u0631\u0649 \u0639\u0645\u0644\u0647
\u0623\u0648 \u0639\u064A\u062F \u0645\u064A\u0644\u0627\u062F\u0647 \u0647\u0630\u0627
\u0627\u0644\u0634\u0647\u0631.\n\n\u064A\u0631\u062C\u0649 \u0623\u064A\u0636\u0627\u064B
\u0645\u0631\u0627\u062C\u0639\u0629 \u0627\u0644\u0633\u064A\u0627\u0633\u0629
\u0627\u0644\u0645\u062D\u062F\u062B\u0629 \u0644\u0644\u062D\u0636\u0648\u0631
\u0627\u0644\u0647\u062C\u064A\u0646 \u0648\u062A\u0642\u062F\u064A\u0645 \u0645\u0644\u0627\u062D\u0638\u0627\u062A\u0643\u0645
\u0628\u062D\u0644\u0648\u0644 \u0627\u0644\u0623\u0633\u0628\u0648\u0639 \u0627\u0644\u0645\u0642\u0628\u0644.
\u0623\u0648\u0644 \u0665\u0660 \u0645\u0648\u0638\u0641\u0627\u064B \u064A\u064F\u0643\u0645\u0644\u0648\u0646
\u062A\u062D\u062F\u064A \"\u0628\u0646\u063A\u0648 \u0627\u0644\u0639\u0627\u0641\u064A\u0629\"
\u0633\u064A\u062D\u0635\u0644\u0648\u0646 \u0639\u0644\u0649 \u0645\u0643\u0627\u0641\u0623\u0629
\u0645\u0641\u0627\u062C\u0626\u0629!\n\n\u2013 \u0641\u0631\u064A\u0642 \u0627\u0644\u0645\u0648\u0627\u0631\u062F
\u0627\u0644\u0628\u0634\u0631\u064A\u0629\n\n"
linkPreview:
hasAttachment: 0
isPhishing: 0
timeOrDate: Yesterday
timeOrDateAr: "\u0627\u0644\u0628\u0627\u0631\u062D\u0629"

View File

@ -15,6 +15,8 @@ MonoBehaviour:
senderName: Finance Team
senderEmail: finance@yourcompany.com
subject: "Reimbursement Processed \u2013 $124"
subjectAr: "\u062A\u0645 \u0635\u0631\u0641 \u0627\u0644\u062A\u0639\u0648\u064A\u0636
\u2013 \u0661\u0662\u0664 \u062F\u0648\u0644\u0627\u0631"
fullBodyText: "Hi Alex,\n\nYour expense reimbursement request for the business
lunch on May 20th has been successfully processed. A total of $124.00 has been
approved and scheduled for transfer to your designated account. The amount should
@ -23,7 +25,32 @@ MonoBehaviour:
of this and future reimbursements in the Finance Portal.\n\nIf there are any
discrepancies, please don\u2019t hesitate to contact us at finance@yourcompany.com.\n\n\u2013
Finance Department"
fullBodyTextAr: "\u0645\u0631\u062D\u0628\u0627\u064B \u0623\u0644\u064A\u0643\u0633\u060C\n\n\u062A\u0645\u062A
\u0645\u0639\u0627\u0644\u062C\u0629 \u0637\u0644\u0628 \u062A\u0639\u0648\u064A\u0636
\u0627\u0644\u0646\u0641\u0642\u0627\u062A \u0627\u0644\u062E\u0627\u0635 \u0628\u0643
\u0628\u0646\u062C\u0627\u062D \u0628\u062E\u0635\u0648\u0635 \u063A\u062F\u0627\u0621
\u0627\u0644\u0639\u0645\u0644 \u0628\u062A\u0627\u0631\u064A\u062E \u0662\u0660
\u0645\u0627\u064A\u0648. \u062A\u0645\u062A \u0627\u0644\u0645\u0648\u0627\u0641\u0642\u0629
\u0639\u0644\u0649 \u0645\u0628\u0644\u063A \u0642\u062F\u0631\u0647 \u0661\u0662\u0664\u066B\u0660\u0660
\u062F\u0648\u0644\u0627\u0631\u060C \u0648\u062A\u0645\u062A \u062C\u062F\u0648\u0644\u062A\u0647
\u0644\u0644\u062A\u062D\u0648\u064A\u0644 \u0625\u0644\u0649 \u062D\u0633\u0627\u0628\u0643
\u0627\u0644\u0645\u064F\u0639\u062A\u0645\u062F. \u0645\u0646 \u0627\u0644\u0645\u062A\u0648\u0642\u0639
\u0623\u0646 \u064A\u0638\u0647\u0631 \u0627\u0644\u0645\u0628\u0644\u063A \u0641\u064A
\u0643\u0634\u0641 \u062D\u0633\u0627\u0628\u0643 \u0627\u0644\u0628\u0646\u0643\u064A
\u062E\u0644\u0627\u0644 \u0662\u2013\u0663 \u0623\u064A\u0627\u0645 \u0639\u0645\u0644.\n\n\u0644\u0623\u063A\u0631\u0627\u0636
\u0627\u0644\u0634\u0641\u0627\u0641\u064A\u0629\u060C \u062A\u0645 \u062A\u0646\u0641\u064A\u0630
\u0627\u0644\u062A\u0639\u0648\u064A\u0636 \u062A\u062D\u062A \u0631\u0642\u0645
\u0627\u0644\u0637\u0644\u0628 #R30492. \u064A\u0645\u0643\u0646\u0643 \u0645\u062A\u0627\u0628\u0639\u0629
\u062D\u0627\u0644\u0629 \u0647\u0630\u0627 \u0627\u0644\u062A\u0639\u0648\u064A\u0636
\u0648\u0623\u064A \u062A\u0639\u0648\u064A\u0636\u0627\u062A \u0645\u0633\u062A\u0642\u0628\u0644\u064A\u0629
\u0645\u0646 \u062E\u0644\u0627\u0644 \u0628\u0648\u0627\u0628\u0629 \u0627\u0644\u0645\u0627\u0644\u064A\u0629.\n\n\u0625\u0630\u0627
\u0644\u0627\u062D\u0638\u062A \u0623\u064A \u062A\u0646\u0627\u0642\u0636\u0627\u062A\u060C
\u0644\u0627 \u062A\u062A\u0631\u062F\u062F \u0641\u064A \u0627\u0644\u062A\u0648\u0627\u0635\u0644
\u0645\u0639\u0646\u0627 \u0639\u0628\u0631 \u0627\u0644\u0628\u0631\u064A\u062F
\u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A:\nfinance@yourcompany.com\n\n\u2013
\u0642\u0633\u0645 \u0627\u0644\u0645\u0627\u0644\u064A\u0629\n\n"
linkPreview:
hasAttachment: 0
isPhishing: 0
timeOrDate: May 24
timeOrDateAr: "\u0662\u0664 \u0645\u0627\u064A\u0648"

View File

@ -15,6 +15,8 @@ MonoBehaviour:
senderName: IT Support
senderEmail: it.support@yourcompany.com
subject: Scheduled Maintenance Notification
subjectAr: "\u0625\u0634\u0639\u0627\u0631 \u0628\u0627\u0644\u0635\u064A\u0627\u0646\u0629
\u0627\u0644\u0645\u062C\u062F\u0648\u0644\u0629"
fullBodyText: "Dear Team,\n\nWe would like to inform you about a scheduled system
maintenance that will take place this Friday, starting at 10:00 PM and continuing
until approximately 2:00 AM. During this window, access to internal tools, shared
@ -24,7 +26,37 @@ MonoBehaviour:
prevent any data loss or corruption. If you encounter any issues after the maintenance
period, feel free to contact our helpdesk.\n\nThank you for your cooperation.\n\u2013
IT Support"
fullBodyTextAr: "\u0641\u0631\u064A\u0642\u0646\u0627 \u0627\u0644\u0639\u0632\u064A\u0632\u060C\n\n\u0646\u0648\u062F
\u0625\u0628\u0644\u0627\u063A\u0643\u0645 \u0628\u0623\u0646\u0647 \u0633\u064A\u062A\u0645
\u0625\u062C\u0631\u0627\u0621 \u0635\u064A\u0627\u0646\u0629 \u0645\u062C\u062F\u0648\u0644\u0629
\u0644\u0644\u0646\u0638\u0627\u0645 \u0647\u0630\u0627 \u0627\u0644\u062C\u0645\u0639\u0629\u060C
\u062A\u0628\u062F\u0623 \u0641\u064A \u0627\u0644\u0633\u0627\u0639\u0629 \u0661\u0660:\u0660\u0660
\u0645\u0633\u0627\u0621\u064B \u0648\u062A\u0633\u062A\u0645\u0631 \u062D\u062A\u0649
\u062D\u0648\u0627\u0644\u064A \u0627\u0644\u0633\u0627\u0639\u0629 \u0662:\u0660\u0660
\u0635\u0628\u0627\u062D\u0627\u064B. \u062E\u0644\u0627\u0644 \u0647\u0630\u0647
\u0627\u0644\u0641\u062A\u0631\u0629\u060C \u0642\u062F \u064A\u0643\u0648\u0646
\u0627\u0644\u0648\u0635\u0648\u0644 \u0625\u0644\u0649 \u0627\u0644\u0623\u062F\u0648\u0627\u062A
\u0627\u0644\u062F\u0627\u062E\u0644\u064A\u0629\u060C \u0648\u0627\u0644\u0623\u0642\u0631\u0627\u0635
\u0627\u0644\u0645\u0634\u062A\u0631\u0643\u0629\u060C \u0648\u0634\u0628\u0643\u0629
\u0627\u0644\u0625\u0646\u062A\u0631\u0627\u0646\u062A \u063A\u064A\u0631 \u0645\u062A\u0627\u062D
\u0645\u0624\u0642\u062A\u0627\u064B. \u0647\u0630\u0647 \u0627\u0644\u0635\u064A\u0627\u0646\u0629
\u0636\u0631\u0648\u0631\u064A\u0629 \u0644\u062A\u0637\u0628\u064A\u0642 \u062A\u062D\u062F\u064A\u062B\u0627\u062A
\u0623\u0645\u0646\u064A\u0629 \u0647\u0627\u0645\u0629 \u0648\u062A\u062D\u0633\u064A\u0646
\u0623\u062F\u0627\u0621 \u0627\u0644\u0646\u0638\u0627\u0645.\n\n\u064A\u0631\u062C\u0649
\u0627\u0644\u062A\u0623\u0643\u062F \u0645\u0646 \u062D\u0641\u0638 \u062C\u0645\u064A\u0639
\u0623\u0639\u0645\u0627\u0644\u0643\u0645 \u0648\u062A\u0633\u062C\u064A\u0644
\u0627\u0644\u062E\u0631\u0648\u062C \u0645\u0646 \u0623\u062C\u0647\u0632\u062A\u0643\u0645
\u0642\u0628\u0644 \u0627\u0644\u0633\u0627\u0639\u0629 \u0669:\u0664\u0665 \u0645\u0633\u0627\u0621\u064B
\u0644\u062A\u062C\u0646\u0628 \u0641\u0642\u062F\u0627\u0646 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A
\u0623\u0648 \u062A\u0644\u0641\u0647\u0627. \u0641\u064A \u062D\u0627\u0644
\u0648\u0627\u062C\u0647\u062A\u0645 \u0623\u064A\u0629 \u0645\u0634\u0643\u0644\u0627\u062A
\u0628\u0639\u062F \u0641\u062A\u0631\u0629 \u0627\u0644\u0635\u064A\u0627\u0646\u0629\u060C
\u0644\u0627 \u062A\u062A\u0631\u062F\u062F\u0648\u0627 \u0641\u064A \u0627\u0644\u062A\u0648\u0627\u0635\u0644
\u0645\u0639 \u0645\u0643\u062A\u0628 \u0627\u0644\u062F\u0639\u0645 \u0627\u0644\u0641\u0646\u064A.\n\n\u0634\u0643\u0631\u064B\u0627
\u0644\u062A\u0639\u0627\u0648\u0646\u0643\u0645.\n\u2013 \u0641\u0631\u064A\u0642
\u0627\u0644\u062F\u0639\u0645 \u0627\u0644\u062A\u0642\u0646\u064A"
linkPreview:
hasAttachment: 0
isPhishing: 0
timeOrDate: Today
timeOrDateAr: "\u0627\u0644\u064A\u0648\u0645"

View File

@ -15,6 +15,8 @@ MonoBehaviour:
senderName: Sarah Thompson
senderEmail: sarah.thompson@yourcompany.com
subject: "Team Sync \u2013 Monday 10 AM"
subjectAr: "\u062A\u0632\u0627\u0645\u0646 \u0627\u0644\u0641\u0631\u064A\u0642
\u2013 \u0627\u0644\u0627\u062B\u0646\u064A\u0646 \u0661\u0660 \u0635\u0628\u0627\u062D\u0627\u064B"
fullBodyText: "Hi team,\n\nJust a quick reminder that our weekly sync is scheduled
for Monday at 10:00 AM. We\u2019ll meet in Conference Room B or via Zoom for
remote team members. Please come prepared with updates on your current sprint
@ -22,7 +24,32 @@ MonoBehaviour:
escalation.\n\nWe\u2019ll also spend a few minutes discussing this month\u2019s
product feedback summary and suggestions for improving sprint velocity. Let me
know if there\u2019s anything you\u2019d like to add to the agenda.\n\nBest,\nSarah"
fullBodyTextAr: "\u0645\u0631\u062D\u0628\u0627\u064B \u0628\u0627\u0644\u0641\u0631\u064A\u0642\u060C\n\n\u062A\u0630\u0643\u064A\u0631
\u0633\u0631\u064A\u0639 \u0628\u0623\u0646 \u0627\u062C\u062A\u0645\u0627\u0639
\u0627\u0644\u0645\u0632\u0627\u0645\u0646\u0629 \u0627\u0644\u0623\u0633\u0628\u0648\u0639\u064A
\u0644\u062F\u064A\u0646\u0627 \u0645\u0642\u0631\u0631 \u064A\u0648\u0645 \u0627\u0644\u0625\u062B\u0646\u064A\u0646
\u0641\u064A \u0627\u0644\u0633\u0627\u0639\u0629 \u0661\u0660:\u0660\u0660 \u0635\u0628\u0627\u062D\u0627\u064B.
\u0633\u0646\u062C\u062A\u0645\u0639 \u0641\u064A \u063A\u0631\u0641\u0629 \u0627\u0644\u0627\u062C\u062A\u0645\u0627\u0639\u0627\u062A
\"B\" \u0623\u0648 \u0639\u0628\u0631 Zoom \u0644\u0623\u0639\u0636\u0627\u0621
\u0627\u0644\u0641\u0631\u064A\u0642 \u0639\u0646 \u0628\u064F\u0639\u062F. \u064A\u0631\u062C\u0649
\u0627\u0644\u062D\u0636\u0648\u0631 \u0645\u0639 \u062A\u062D\u062F\u064A\u062B\u0627\u062A
\u062D\u0648\u0644 \u0645\u0647\u0627\u0645 \u0627\u0644\u0633\u0628\u0631\u0646\u062A
\u0627\u0644\u062D\u0627\u0644\u064A\u0629\u060C \u0648\u0627\u0644\u0645\u0639\u0648\u0651\u0642\u0627\u062A
\u0627\u0644\u062A\u064A \u0648\u0627\u062C\u0647\u062A\u0645\u0648\u0647\u0627\u060C
\u0648\u0623\u064A \u062A\u0628\u0639\u064A\u0627\u062A \u0628\u064A\u0646 \u0627\u0644\u0641\u0631\u0642
\u062A\u062D\u062A\u0627\u062C \u0625\u0644\u0649 \u062A\u0635\u0639\u064A\u062F.\n\n\u0633\u0646\u062E\u0635\u0635
\u0623\u064A\u0636\u0627\u064B \u0628\u0636\u0639 \u062F\u0642\u0627\u0626\u0642
\u0644\u0645\u0646\u0627\u0642\u0634\u0629 \u0645\u0644\u062E\u0635 \u0645\u0644\u0627\u062D\u0638\u0627\u062A
\u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\u064A\u0646 \u0644\u0647\u0630\u0627
\u0627\u0644\u0634\u0647\u0631 \u0648\u0627\u0642\u062A\u0631\u0627\u062D\u0627\u062A
\u062A\u062D\u0633\u064A\u0646 \u0633\u0631\u0639\u0629 \u0627\u0644\u0625\u0646\u062C\u0627\u0632
\u0641\u064A \u0627\u0644\u0633\u0628\u0631\u0646\u062A. \u0623\u062E\u0628\u0631\u0648\u0646\u064A
\u0625\u0630\u0627 \u0643\u0627\u0646 \u0647\u0646\u0627\u0643 \u0634\u064A\u0621
\u062A\u0648\u062F\u0648\u0646 \u0625\u0636\u0627\u0641\u062A\u0647 \u0625\u0644\u0649
\u062C\u062F\u0648\u0644 \u0627\u0644\u0623\u0639\u0645\u0627\u0644.\n\n\u0645\u0639
\u0623\u0637\u064A\u0628 \u0627\u0644\u062A\u062D\u064A\u0627\u062A\u060C\n\u0633\u0627\u0631\u0629"
linkPreview:
hasAttachment: 0
isPhishing: 0
timeOrDate: May 25
timeOrDateAr: "\u0662\u0665 \u0645\u0627\u064A\u0648"

View File

@ -15,6 +15,9 @@ MonoBehaviour:
senderName: Microsoft Security
senderEmail: alert@m1crosoft-security.com
subject: "Suspicious Login \u2013 act1vate your profile urgently"
subjectAr: "\u062A\u0633\u062C\u064A\u0644 \u062F\u062E\u0648\u0644 \u0645\u0634\u0628\u0648\u0647
\u2013 \u0641\u0639\u0651\u0644 \u0645\u0644\u0641\u0643 \u0627\u0644\u0634\u062E\u0635\u064A
\u0641\u0648\u0631\u0627\u064B"
fullBodyText: 'Dear User,
@ -33,7 +36,19 @@ MonoBehaviour:
Microsoft
Account Protection Team'
fullBodyTextAr: "\u0639\u0632\u064A\u0632\u064A \u0627\u0644\u0645\u0633\u062A\u062E\u062F\u0645\u060C\n\n\u0644\u0642\u062F
\u0627\u0643\u062A\u0634\u0641\u0646\u0627 \u0645\u062D\u0627\u0648\u0644\u0629
\u062A\u0633\u062C\u064A\u0644 \u062F\u062E\u0648\u0644 \u0645\u0646 \u0645\u0648\u0642\u0639
\u063A\u064A\u0631 \u0645\u0639\u0631\u0648\u0641. \u0644\u062D\u0645\u0627\u064A\u0629
\u062D\u0633\u0627\u0628\u0643\u060C \u062A\u062D\u062A\u0627\u062C \u0625\u0644\u0649
act1vate \u062A\u062D\u062F\u064A\u062B \u0645\u0644\u0641\u0643 \u0627\u0644\u0634\u062E\u0635\u064A
\u0641\u0648\u0631\u0627\u064B. \u062A\u062C\u0627\u0647\u0644 \u0647\u0630\u0627
\u0627\u0644\u0637\u0644\u0628 \u0642\u062F \u064A\u0624\u062F\u064A \u0625\u0644\u0649
\u0642\u0641\u0644 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0634\u062E\u0635\u064A.\n\n\u0627\u0646\u0642\u0631
\u0639\u0644\u0649 \u0627\u0644\u0631\u0627\u0628\u0637 \u0644\u0644\u062A\u062D\u0642\u0642:\n<link=\"http://m1crosoft-security.com/actnow\"><color=#0000EE><u>http://m1crosoft-security.com/actnow</u></color></link>\n\n\u0634\u0643\u0631\u064B\u0627\u060C\n\u0641\u0631\u064A\u0642
\u062D\u0645\u0627\u064A\u0629 \u062D\u0633\u0627\u0628 Microsoft\n\n"
linkPreview: http://m1crosoft-security.com/actnow
hasAttachment: 0
isPhishing: 1
timeOrDate: 1 hour ago
timeOrDateAr: "\u0642\u0628\u0644 \u0633\u0627\u0639\u0629 \u0648\u0627\u062D\u062F\u0629"

View File

@ -15,11 +15,28 @@ MonoBehaviour:
senderName: CloudStorage
senderEmail: alerts@stor-cloud-updates.com
subject: Verify stor-age account info to avoid suspens1on
subjectAr: "\u062A\u062D\u0642\u0642 \u0645\u0646 \u0645\u0639\u0640\u0644\u0648\u0645\u0640\u0627\u062A
\u062D\u0633\u0640\u0627\u0628 \u0627\u0644\u062A\u062E\u0640\u0632\u064A\u0640\u0646
\u0644\u062A\u062C\u0646\u0628 \u0627\u0644\u0625\u064A\u0640\u0642\u0627\u0641"
fullBodyText: "Hello,\n\nWe were unable to sync your latest files due to a mismatch
in account info. To avoid suspens1on of your cloud services, please verify your
account information now.\n\nConfirm here:\n<link=\"http://stor-cloud-updates.com/verify\"><color=#0000EE><u>http://stor-cloud-updates.com/verify</u></color></link>\n\nThis
issue must be resolved within 3 hours.\n\n\u2013 CloudStorage Notification Center"
fullBodyTextAr: "\u0645\u0631\u062D\u0628\u0627\u064B\u060C\n\n\u0644\u0645 \u0646\u062A\u0645\u0643\u0646
\u0645\u0646 \u0645\u0632\u0627\u0645\u0646\u0629 \u0645\u0644\u0641\u0627\u062A\u0643
\u0627\u0644\u0623\u062E\u064A\u0631\u0629 \u0628\u0633\u0628\u0628 \u0639\u062F\u0645
\u062A\u0637\u0627\u0628\u0642 \u0641\u064A \u0645\u0639\u0644\u0648\u0645\u0627\u062A
\u0627\u0644\u062D\u0633\u0627\u0628. \u0644\u062A\u062C\u0646\u0628 suspens1on
\u062E\u062F\u0645\u0627\u062A \u0627\u0644\u0633\u062D\u0627\u0628\u0629 \u0627\u0644\u062E\u0627\u0635\u0629
\u0628\u0643\u060C \u064A\u0631\u062C\u0649 \u0627\u0644\u062A\u062D\u0642\u0642
\u0645\u0646 \u0645\u0639\u0644\u0648\u0645\u0627\u062A \u062D\u0633\u0627\u0628\u0643
\u0627\u0644\u0622\u0646.\n\n\u0642\u0645 \u0628\u0627\u0644\u062A\u0623\u0643\u064A\u062F
\u0647\u0646\u0627:\n<link=\"http://stor-cloud-updates.com/verify\"><color=#0000EE><u>http://stor-cloud-updates.com/verify</u></color></link>\n\n\u064A\u062C\u0628
\u062D\u0644 \u0647\u0630\u0647 \u0627\u0644\u0645\u0634\u0643\u0644\u0629 \u062E\u0644\u0627\u0644
\u0663 \u0633\u0627\u0639\u0627\u062A.\n\n\u2013 \u0645\u0631\u0643\u0632 \u0625\u0634\u0639\u0627\u0631\u0627\u062A
CloudStorage\n\n"
linkPreview: http://stor-cloud-updates.com/verify
hasAttachment: 0
isPhishing: 1
timeOrDate: Today
timeOrDateAr: "\u0627\u0644\u064A\u0648\u0645"

View File

@ -15,12 +15,30 @@ MonoBehaviour:
senderName: Accure Bank
senderEmail: support@accure-bank-ank.com
subject: "ob1ink a update now \u2013 Avoid Suspension"
subjectAr: "\u0642\u064F\u0645 \u0628\u062A\u062D\u062F1\u062B \u0627\u0644\u0622\u0646
\u2013 \u0644\u062A\u062C\u0646\u0628 \u0627\u0644\u0625\u064A\u0642\u0627\u0641"
fullBodyText: "Dear Customer,\n\nOur system has detected unusual activity in your
account. You must ob1ink a update immediately to prevent restriction. If no action
is taken within 2 hours, your account will be permanently locked.\n\nVisit the
secure link below:\n<link=\"http://accure-bank-ank.com/verify\"><color=#0000EE><u>http://accure-bank-ank.com/verify</u></color></link>\n\nThis
is an automated message. Please do not reply.\n\n\u2013 Accure Bank Online Security"
fullBodyTextAr: "\u0639\u0632\u064A\u0632\u064A \u0627\u0644\u0639\u0645\u064A\u0644\u060C\n\n\u0644\u0642\u062F
\u0627\u0643\u062A\u0634\u0641 \u0646\u0638\u0627\u0645\u0646\u0627 \u0646\u0634\u0627\u0637\u0627\u064B
\u063A\u064A\u0631 \u0645\u0639\u062A\u0627\u062F \u0641\u064A \u062D\u0633\u0627\u0628\u0643.
\u064A\u062C\u0628 \u0639\u0644\u064A\u0643 ob1ink \u062A\u062D\u062F\u064A\u062B\u0627\u064B
\u0641\u0648\u0631\u064A\u0627\u064B \u0644\u062A\u062C\u0646\u0628 \u062A\u0642\u064A\u064A\u062F
\u0627\u0644\u062D\u0633\u0627\u0628. \u0625\u0630\u0627 \u0644\u0645 \u064A\u062A\u0645
\u0627\u062A\u062E\u0627\u0630 \u0625\u062C\u0631\u0627\u0621 \u062E\u0644\u0627\u0644
\u0633\u0627\u0639\u062A\u064A\u0646\u060C \u0641\u0633\u064A\u062A\u0645 \u0642\u0641\u0644
\u062D\u0633\u0627\u0628\u0643 \u0646\u0647\u0627\u0626\u064A\u0627\u064B.\n\n\u064A\u0631\u062C\u0649
\u0632\u064A\u0627\u0631\u0629 \u0627\u0644\u0631\u0627\u0628\u0637 \u0627\u0644\u0622\u0645\u0646
\u0623\u062F\u0646\u0627\u0647:\n<link=\"http://accure-bank-ank.com/verify\"><color=#0000EE><u>http://accure-bank-ank.com/verify</u></color></link>\n\n\u0647\u0630\u0647
\u0631\u0633\u0627\u0644\u0629 \u062A\u0644\u0642\u0627\u0626\u064A\u0629. \u064A\u0631\u062C\u0649
\u0639\u062F\u0645 \u0627\u0644\u0631\u062F.\n\n\u2013 \u0642\u0633\u0645 \u0627\u0644\u0623\u0645\u0627\u0646
\u0627\u0644\u0625\u0644\u0643\u062A\u0631\u0648\u0646\u064A \u0641\u064A \u0628\u0646\u0643
Accure"
linkPreview: http://accure-bank-ank.com/verify
hasAttachment: 0
isPhishing: 1
timeOrDate: Today
timeOrDateAr: "\u0627\u0644\u064A\u0648\u0645"

View File

@ -26,7 +26,7 @@ public class CharacterMovement : MonoBehaviour
private bool animStarted = false;
private bool cameraTransitionStarted = false;
private Quaternion targetSitRotation;
bool isStarted = false;
void Start()
{
if (waypoints == null || waypoints.Length == 0)
@ -49,28 +49,35 @@ public class CharacterMovement : MonoBehaviour
}
animator.applyRootMotion = false;
animator.SetTrigger("StartWalking");
}
public void AnimationStarter()
{
animator.SetTrigger("StartWalking");
isStarted = true;
}
void Update()
{
switch (state)
if (isStarted)
{
case MovementState.Walking:
MoveToWaypoint();
break;
switch (state)
{
case MovementState.Walking:
MoveToWaypoint();
break;
case MovementState.RotatingToSit:
RotateToSit();
break;
case MovementState.RotatingToSit:
RotateToSit();
break;
case MovementState.PlayingAnimation:
WaitForAnimationToEnd();
break;
case MovementState.PlayingAnimation:
WaitForAnimationToEnd();
break;
case MovementState.Finished:
break;
case MovementState.Finished:
break;
}
}
}
void MoveToWaypoint()
@ -150,7 +157,7 @@ public class CharacterMovement : MonoBehaviour
cameraTransitionStarted = true;
// Move and rotate camera to final cinematic zoom position
mainCamera.GetComponent<LookAtConstraint>().constraintActive = false;
mainCamera.GetComponent<LookAtConstraint>().constraintActive = false;
mainCamera.DOMove(cameraSitTarget.position, 1f);
mainCamera.DORotate(cameraSitTarget.eulerAngles, 1f)
.OnComplete(() =>

View File

@ -1,4 +1,3 @@
using UnityEngine;
[CreateAssetMenu(fileName = "EmailData", menuName = "Inbox/Email Data", order = 1)]
@ -7,9 +6,15 @@ public class EmailData : ScriptableObject
public string senderName;
public string senderEmail;
public string subject;
public string subjectAr;
[TextArea(5, 20)] public string fullBodyText;
[TextArea(5, 20)] public string fullBodyTextAr;
public string linkPreview;
public bool hasAttachment;
public bool isPhishing;
public string timeOrDate;
public string timeOrDateAr;
}

Some files were not shown because too many files have changed in this diff Show More