This commit is contained in:
2020-07-04 14:41:25 +08:00
parent 70c346d2c1
commit a8f02e4da5
3748 changed files with 587372 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
using Mopsicus.Plugins;
using UnityEngine;
using UnityEngine.UI;
public class Demo : MonoBehaviour {
public MobileInputField InputText;
void Start () {
MobileInput.OnPrepareKeyboard += OnPrepareKeyboard;
MobileInput.OnShowKeyboard += OnShowKeyboard;
}
public void OnReturn () {
Debug.Log ("OnReturn action");
}
public void OnEdit (string text) {
Debug.LogFormat ("OnEdit action. Text: {0}", text);
}
public void OnEndEdit (string text) {
Debug.LogFormat ("OnEdit action. Text: {0}", text);
}
public void SetTextData () {
InputText.Text = "Text by script";
}
void OnPrepareKeyboard () {
Debug.LogFormat ("Keyboad will show");
}
void OnShowKeyboard (bool isShow, int height) {
Debug.LogFormat ("Keyboad action, show = {0}, height = {1}", isShow, height);
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 053f12a21060a4074af5416ef1101ff4
timeCreated: 1522834416
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,956 @@
/*
NiceJson 1.3.1 (2017-07-26)
MIT License
===========
Copyright (C) 2015 Ángel Quiroga Mendoza <me@angelqm.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Appreciation Contributions:
Rayco Sánchez García <raycosanchezgarcia@gmail.com>
*/
using System;
using System.Collections.Generic;
using System.Collections;
using System.Globalization;
using System.Text;
namespace NiceJson
{
[Serializable]
public abstract class JsonNode
{
protected const char PP_IDENT_CHAR = '\t'; //Modify this to spaces or whatever char you want to be the ident one
protected const int PP_IDENT_COUNT = 1; //Modify this to be the numbers of IDENT_CHAR x identation
protected const bool ESCAPE_SOLIDUS = false; //If you are going to to embed this json in html, you can turn this on ref: http://andowebsit.es/blog/noteslog.com/post/the-solidus-issue/
protected const char CHAR_CURLY_OPEN = '{';
protected const char CHAR_CURLY_CLOSED = '}';
protected const char CHAR_SQUARED_OPEN = '[';
protected const char CHAR_SQUARED_CLOSED = ']';
protected const char CHAR_COLON = ':';
protected const char CHAR_COMMA = ',';
protected const char CHAR_QUOTE = '"';
protected const char CHAR_NULL_LITERAL = 'n';
protected const char CHAR_TRUE_LITERAL = 't';
protected const char CHAR_FALSE_LITERAL = 'f';
protected const char CHAR_SPACE = ' ';
protected const char CHAR_BS = '\b';
protected const char CHAR_FF = '\f';
protected const char CHAR_RF = '\r';
protected const char CHAR_NL = '\n';
protected const char CHAR_HT = '\t';
protected const char CHAR_ESCAPE = '\\';
protected const char CHAR_SOLIDUS = '/';
protected const char CHAR_ESCAPED_QUOTE = '\"';
protected const char CHAR_N = 'n';
protected const char CHAR_R = 'r';
protected const char CHAR_B = 'b';
protected const char CHAR_T = 't';
protected const char CHAR_F = 'f';
protected const char CHAR_U = 'u';
protected const string STRING_ESCAPED_BS = "\\b";
protected const string STRING_ESCAPED_FF = "\\f";
protected const string STRING_ESCAPED_RF = "\\r";
protected const string STRING_ESCAPED_NL = "\\n";
protected const string STRING_ESCAPED_TAB = "\\t";
protected const string STRING_ESCAPED_ESCAPE = "\\\\";
protected const string STRING_ESCAPED_SOLIDUS = "\\/";
protected const string STRING_ESCAPED_ESCAPED_QUOTE = "\\\"";
protected const string STRING_SPACE = " ";
protected const string STRING_LITERAL_NULL = "null";
protected const string STRING_LITERAL_TRUE = "true";
protected const string STRING_LITERAL_FALSE = "false";
protected const string STRING_ESCAPED_UNICODE_INIT = "\\u00";
//Indexers and accesors
public JsonNode this[string key]
{
get
{
if (this is JsonObject)
{
return ((JsonObject)this)[key];
}
else
{
return null;
}
}
set
{
if (this is JsonObject)
{
((JsonObject)this)[key] = value;
}
}
}
public JsonNode this[int index]
{
get
{
if (this is JsonArray)
{
return ((JsonArray)this)[index];
}
else
{
return null;
}
}
set
{
if (this is JsonArray)
{
((JsonArray)this)[index] = value;
}
}
}
public bool ContainsKey (string key)
{
if (this is JsonObject)
{
return ((JsonObject)this).ContainsKey(key);
}
else
{
return false;
}
}
//escaping logic
//Escaping/Unescaping logic
protected static string EscapeString(string s)
{
StringBuilder result = new StringBuilder();
foreach (char c in s)
{
switch (c)
{
case CHAR_ESCAPE:
{
result.Append(STRING_ESCAPED_ESCAPE);
}
break;
case CHAR_SOLIDUS:
{
#pragma warning disable
if (ESCAPE_SOLIDUS)
{
result.Append(STRING_ESCAPED_SOLIDUS);
}
else
{
result.Append(c);
}
#pragma warning restore
}
break;
case CHAR_ESCAPED_QUOTE:
{
result.Append (STRING_ESCAPED_ESCAPED_QUOTE);
}
break;
case CHAR_NL:
{
result.Append (STRING_ESCAPED_NL);
}
break;
case CHAR_RF:
{
result.Append (STRING_ESCAPED_RF);
}
break;
case CHAR_HT:
{
result.Append (STRING_ESCAPED_TAB);
}
break;
case CHAR_BS:
{
result.Append (STRING_ESCAPED_BS);
}
break;
case CHAR_FF:
{
result.Append (STRING_ESCAPED_FF);
}
break;
default:
if (c < CHAR_SPACE)
{
result.Append (STRING_ESCAPED_UNICODE_INIT + Convert.ToByte(c).ToString("x2").ToUpper());
}
else
{
result.Append(c);
}
break;
}
}
return result.ToString();
}
protected static string UnescapeString(string s)
{
StringBuilder result = new StringBuilder(s.Length);
for (int i=0;i<s.Length;i++)
{
if (s[i] == CHAR_ESCAPE)
{
i++;
switch(s[i])
{
case CHAR_ESCAPE:
{
result.Append(s[i]);
}
break;
case CHAR_SOLIDUS:
{
result.Append(s[i]);
}
break;
case CHAR_ESCAPED_QUOTE:
{
result.Append(s[i]);
}
break;
case CHAR_N:
{
result.Append(CHAR_NL);
}
break;
case CHAR_R:
{
result.Append(CHAR_RF);
}
break;
case CHAR_T:
{
result.Append(CHAR_HT);
}
break;
case CHAR_B:
{
result.Append(CHAR_BS);
}
break;
case CHAR_F:
{
result.Append(CHAR_FF);
}
break;
case CHAR_U:
{
result.Append((char) int.Parse(s.Substring(i+1,4),NumberStyles.AllowHexSpecifier));
i = i + 4;
}
break;
default:
{
result.Append(s[i]);
}
break;
}
}
else
{
result.Append(s[i]);
}
}
return result.ToString();
}
//setter implicit casting
public static implicit operator JsonNode(string value)
{
return new JsonBasic(value);
}
public static implicit operator JsonNode(int value)
{
return new JsonBasic(value);
}
public static implicit operator JsonNode(long value)
{
return new JsonBasic(value);
}
public static implicit operator JsonNode(float value)
{
return new JsonBasic(value);
}
public static implicit operator JsonNode(double value)
{
return new JsonBasic(value);
}
public static implicit operator JsonNode(decimal value)
{
return new JsonBasic(value);
}
public static implicit operator JsonNode(bool value)
{
return new JsonBasic(value);
}
//getter implicit casting
public static implicit operator string(JsonNode value)
{
if (value != null)
{
return value.ToString();
}
else
{
return null;
}
}
public static implicit operator int(JsonNode value)
{
return (int) Convert.ChangeType(((JsonBasic)value).ValueObject,typeof(int));
}
public static implicit operator long (JsonNode value)
{
return (long) Convert.ChangeType(((JsonBasic)value).ValueObject, typeof(long));
}
public static implicit operator float(JsonNode value)
{
return (float) Convert.ChangeType(((JsonBasic)value).ValueObject, typeof(float));
}
public static implicit operator double(JsonNode value)
{
return (double) Convert.ChangeType(((JsonBasic)value).ValueObject, typeof(double));
}
public static implicit operator decimal (JsonNode value)
{
return (decimal) Convert.ChangeType(((JsonBasic)value).ValueObject, typeof(decimal));
}
public static implicit operator bool(JsonNode value)
{
return (bool) Convert.ChangeType(((JsonBasic)value).ValueObject, typeof(bool));
}
//Parsing logic
public static JsonNode ParseJsonString(string jsonString)
{
return ParseJsonPart(RemoveNonTokenChars(jsonString));
}
private static JsonNode ParseJsonPart(string jsonPart)
{
JsonNode jsonPartValue = null;
if (jsonPart.Length == 0)
{
return jsonPartValue;
}
switch (jsonPart[0])
{
case JsonNode.CHAR_CURLY_OPEN:
{
JsonObject jsonObject = new JsonObject();
List<string> splittedParts = SplitJsonParts(jsonPart.Substring(1, jsonPart.Length - 2));
string[] keyValueParts = new string[2];
foreach (string keyValuePart in splittedParts)
{
keyValueParts = SplitKeyValuePart (keyValuePart);
if (keyValueParts [0] != null)
{
jsonObject [JsonNode.UnescapeString (keyValueParts [0])] = ParseJsonPart (keyValueParts [1]);
}
}
jsonPartValue = jsonObject;
}
break;
case JsonNode.CHAR_SQUARED_OPEN:
{
JsonArray jsonArray = new JsonArray();
List<string> splittedParts = SplitJsonParts(jsonPart.Substring(1, jsonPart.Length - 2));
foreach (string part in splittedParts)
{
if (part.Length > 0)
{
jsonArray.Add (ParseJsonPart (part));
}
}
jsonPartValue = jsonArray;
}
break;
case JsonNode.CHAR_QUOTE:
{
jsonPartValue = new JsonBasic(JsonNode.UnescapeString(jsonPart.Substring(1, jsonPart.Length - 2)));
}
break;
case JsonNode.CHAR_FALSE_LITERAL://false
{
jsonPartValue = new JsonBasic(false);
}
break;
case JsonNode.CHAR_TRUE_LITERAL://true
{
jsonPartValue = new JsonBasic(true);
}
break;
case JsonNode.CHAR_NULL_LITERAL://null
{
jsonPartValue = null;
}
break;
default://it must be a number or it will fail
{
long longValue = 0;
if (long.TryParse(jsonPart, NumberStyles.Any, CultureInfo.InvariantCulture, out longValue))
{
if (longValue > int.MaxValue || longValue < int.MinValue)
{
jsonPartValue = new JsonBasic(longValue);
}
else
{
jsonPartValue = new JsonBasic((int)longValue);
}
}
else
{
decimal decimalValue = 0;
if (decimal.TryParse(jsonPart, NumberStyles.Any, CultureInfo.InvariantCulture, out decimalValue))
{
jsonPartValue = new JsonBasic(decimalValue);
}
}
}
break;
}
return jsonPartValue;
}
private static List<string> SplitJsonParts(string json)
{
List<string> jsonParts = new List<string>();
int identLevel = 0;
int lastPartChar = 0;
bool inString = false;
for (int i = 0; i < json.Length; i++)
{
switch (json[i])
{
case JsonNode.CHAR_COMMA:
{
if (!inString && identLevel == 0)
{
jsonParts.Add(json.Substring(lastPartChar, i - lastPartChar));
lastPartChar = i + 1;
}
}
break;
case JsonNode.CHAR_QUOTE:
{
if (i == 0 || (json[i - 1] != JsonNode.CHAR_ESCAPE))
{
inString = !inString;
}
}
break;
case JsonNode.CHAR_CURLY_OPEN:
case JsonNode.CHAR_SQUARED_OPEN:
{
if (!inString)
{
identLevel++;
}
}
break;
case JsonNode.CHAR_CURLY_CLOSED:
case JsonNode.CHAR_SQUARED_CLOSED:
{
if (!inString)
{
identLevel--;
}
}
break;
}
}
jsonParts.Add(json.Substring(lastPartChar));
return jsonParts;
}
private static string[] SplitKeyValuePart(string json)
{
string[] parts = new string[2];
bool inString = false;
bool found = false;
int index = 0;
while (index < json.Length && !found)
{
if (json[index] == JsonNode.CHAR_QUOTE && (index == 0 || (json[index - 1] != JsonNode.CHAR_ESCAPE)))
{
if (!inString)
{
inString = true;
index++;
}
else
{
parts[0] = json.Substring(1, index - 1);
parts[1] = json.Substring(index + 2);//+2 because of the :
found = true;
}
}
else
{
index++;
}
}
return parts;
}
private static string RemoveNonTokenChars(string s)
{
int len = s.Length;
char[] s2 = new char[len];
int currentPos = 0;
bool outString = true;
for (int i = 0; i < len; i++)
{
char c = s[i];
if (c == JsonNode.CHAR_QUOTE)
{
if (i == 0 || (s[i - 1] != JsonNode.CHAR_ESCAPE))
{
outString = !outString;
}
}
if (!outString || (
(c != JsonNode.CHAR_SPACE) &&
(c != JsonNode.CHAR_RF) &&
(c != JsonNode.CHAR_NL) &&
(c != JsonNode.CHAR_HT) &&
(c != JsonNode.CHAR_BS) &&
(c != JsonNode.CHAR_FF)
))
{
s2[currentPos++] = c;
}
}
return new String(s2, 0, currentPos);
}
//Object logic
public abstract string ToJsonString();
public string ToJsonPrettyPrintString()
{
string jsonString = this.ToJsonString();
string identStep = string.Empty;
for (int i = 0; i < PP_IDENT_COUNT; i++)
{
identStep += PP_IDENT_CHAR;
}
bool inString = false;
string currentIdent = string.Empty;
for (int i = 0; i < jsonString.Length; i++)
{
switch (jsonString[i])
{
case CHAR_COLON:
{
if (!inString)
{
jsonString = jsonString.Insert(i + 1, STRING_SPACE);
}
}
break;
case CHAR_QUOTE:
{
if (i == 0 || (jsonString[i - 1] != CHAR_ESCAPE))
{
inString = !inString;
}
}
break;
case CHAR_COMMA:
{
if (!inString)
{
jsonString = jsonString.Insert(i + 1, CHAR_NL + currentIdent);
}
}
break;
case CHAR_CURLY_OPEN:
case CHAR_SQUARED_OPEN:
{
if (!inString)
{
currentIdent += identStep;
jsonString = jsonString.Insert(i + 1, CHAR_NL + currentIdent);
}
}
break;
case CHAR_CURLY_CLOSED:
case CHAR_SQUARED_CLOSED:
{
if (!inString)
{
currentIdent = currentIdent.Substring(0, currentIdent.Length - identStep.Length);
jsonString = jsonString.Insert(i, CHAR_NL + currentIdent);
i += currentIdent.Length + 1;
}
}
break;
}
}
return jsonString;
}
}
[Serializable]
public class JsonBasic : JsonNode
{
public object ValueObject
{
get
{
return m_value;
}
}
private object m_value;
public JsonBasic(object value)
{
m_value = value;
}
public override string ToString()
{
return m_value.ToString();
}
public override string ToJsonString ()
{
if (m_value == null)
{
return STRING_LITERAL_NULL;
}
else if (m_value is string)
{
return CHAR_QUOTE + EscapeString(m_value.ToString()) + CHAR_QUOTE;
}
else if (m_value is bool)
{
if ((bool) m_value)
{
return STRING_LITERAL_TRUE;
}
else
{
return STRING_LITERAL_FALSE;
}
}
else
{
return m_value.ToString();
}
}
}
[Serializable]
public class JsonObject : JsonNode, IEnumerable
{
private Dictionary<string,JsonNode> m_dictionary = new Dictionary<string, JsonNode>();
public Dictionary<string,JsonNode>.KeyCollection Keys
{
get
{
return m_dictionary.Keys;
}
}
public Dictionary<string, JsonNode>.ValueCollection Values
{
get
{
return m_dictionary.Values;
}
}
public new JsonNode this[string key]
{
get
{
return m_dictionary[key];
}
set
{
m_dictionary[key] = value;
}
}
public void Add(string key, JsonNode value)
{
m_dictionary.Add(key, value);
}
public bool Remove(string key)
{
return m_dictionary.Remove(key);
}
public new bool ContainsKey(string key)
{
return m_dictionary.ContainsKey(key);
}
public bool ContainsValue(JsonNode value)
{
return m_dictionary.ContainsValue(value);
}
public void Clear()
{
m_dictionary.Clear();
}
public int Count
{
get
{
return m_dictionary.Count;
}
}
public IEnumerator GetEnumerator()
{
foreach (KeyValuePair<string, JsonNode> jsonKeyValue in m_dictionary)
{
yield return jsonKeyValue;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override string ToJsonString ()
{
if (m_dictionary == null)
{
return STRING_LITERAL_NULL;
}
else
{
StringBuilder jsonString = new StringBuilder();
jsonString.Append(CHAR_CURLY_OPEN);
foreach (string key in m_dictionary.Keys)
{
jsonString.Append(CHAR_QUOTE);
jsonString.Append(EscapeString(key));
jsonString.Append(CHAR_QUOTE);
jsonString.Append(CHAR_COLON);
if (m_dictionary[key] != null)
{
jsonString.Append(m_dictionary[key].ToJsonString());
}
else
{
jsonString.Append(STRING_LITERAL_NULL);
}
jsonString.Append(CHAR_COMMA);
}
if (jsonString[jsonString.Length -1] == CHAR_COMMA)
{
jsonString.Remove(jsonString.Length -1,1);
}
jsonString.Append(CHAR_CURLY_CLOSED);
return jsonString.ToString();
}
}
}
[Serializable]
public class JsonArray : JsonNode, IEnumerable<JsonNode>
{
private List<JsonNode> m_list = new List<JsonNode>();
public int Count
{
get
{
return m_list.Count;
}
}
public new JsonNode this[int index]
{
get
{
return m_list[index];
}
set
{
m_list[index] = value;
}
}
public IEnumerator<JsonNode> GetEnumerator()
{
foreach (JsonNode value in m_list)
{
yield return value;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
//expose some methods of list extends with needs
public void Add(JsonNode item)
{
m_list.Add(item);
}
public void AddRange(IEnumerable<JsonNode> collection)
{
m_list.AddRange(collection);
}
public void Insert(int index,JsonNode item)
{
m_list.Insert(index,item);
}
public void InsertRange(int index,IEnumerable<JsonNode> collection)
{
m_list.InsertRange(index,collection);
}
public void RemoveAt(int index)
{
m_list.RemoveAt(index);
}
public bool Remove(JsonNode item)
{
return m_list.Remove(item);
}
public void Clear()
{
m_list.Clear();
}
//end exposed methods
public override string ToJsonString ()
{
if (m_list == null)
{
return STRING_LITERAL_NULL;
}
else
{
StringBuilder jsonString = new StringBuilder();
jsonString.Append (CHAR_SQUARED_OPEN);
foreach (JsonNode value in m_list)
{
if (value != null)
{
jsonString.Append (value.ToJsonString());
}
else
{
jsonString.Append (STRING_LITERAL_NULL);
}
jsonString.Append (CHAR_COMMA);
}
if (jsonString[jsonString.Length-1] == CHAR_COMMA)
{
jsonString.Remove(jsonString.Length -1,1);
}
jsonString.Append (CHAR_SQUARED_CLOSED);
return jsonString.ToString();
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e4f694d670baf414b9018735af14a6a7
timeCreated: 1522830148
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 82bab59c0aaa34beaa1f3397c03a32a3
folderAsset: yes
timeCreated: 1522830104
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@@ -0,0 +1,92 @@
// ----------------------------------------------------------------------------
// The MIT License
// UnityMobileInput https://github.com/mopsicus/UnityMobileInput
// Copyright (c) 2018 Mopsicus <mail@mopsicus.ru>
// ----------------------------------------------------------------------------
using UnityEditor;
using UnityEngine;
namespace Mopsicus.Plugins {
/// <summary>
/// Custom editor for MobileInput
/// </summary>
[CustomEditor (typeof (MobileInputField))]
public class MobileInputEditor : Editor {
/// <summary>
/// Offset size
/// </summary>
const int OFFSET = 20;
/// <summary>
/// Space between labels
/// </summary>
const int SPACE = 5;
/// <summary>
/// MobileInput target
/// </summary>
private MobileInputField _target;
/// <summary>
/// Serialized target object
/// </summary>
private SerializedObject _object;
/// <summary>
/// Return press event
/// </summary>
private SerializedProperty _onReturnPressedEvent;
#if UNITY_IOS
/// <summary>
/// Visible Done button
/// </summary>
private SerializedProperty _isWithDoneButton;
/// <summary>
/// Visible Clear buttonƒ
/// </summary>
private SerializedProperty _isWithClearButton;
#endif
/// <summary>
/// Init data
/// </summary>
private void OnEnable () {
_target = (MobileInputField) target;
_object = new SerializedObject (target);
_onReturnPressedEvent = _object.FindProperty ("OnReturnPressedEvent");
#if UNITY_IOS
_isWithDoneButton = _object.FindProperty ("IsWithDoneButton");
_isWithClearButton = _object.FindProperty ("IsWithClearButton");
#endif
}
/// <summary>
/// Draw inspector
/// </summary>
public override void OnInspectorGUI () {
_object.Update ();
EditorGUI.BeginChangeCheck ();
GUILayout.Space (OFFSET);
GUILayout.Label ("Select type for Return button:");
_target.ReturnKey = (MobileInputField.ReturnKeyType) GUILayout.Toolbar ((int) _target.ReturnKey, new string[] { "Default", "Next", "Done", "Search" });
GUILayout.Space (OFFSET);
#if UNITY_IOS
GUILayout.Label ("Options:");
_target.IsWithDoneButton = GUILayout.Toggle (_target.IsWithDoneButton, " Show \"Done\" button");
GUILayout.Space (SPACE);
_target.IsWithClearButton = GUILayout.Toggle (_target.IsWithClearButton, " Show \"Clear\" button");
GUILayout.Space (OFFSET);
#endif
EditorGUILayout.PropertyField (_onReturnPressedEvent);
if (EditorGUI.EndChangeCheck ()) {
_object.ApplyModifiedProperties ();
}
}
}
}

View File

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

View File

@@ -0,0 +1,320 @@
// ----------------------------------------------------------------------------
// The MIT License
// UnityMobileInput https://github.com/mopsicus/UnityMobileInput
// Copyright (c) 2018 Mopsicus <mail@mopsicus.ru>
// ----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using NiceJson;
using UnityEngine;
#if UNITY_IOS
using System.Runtime.InteropServices;
#endif
namespace Mopsicus.Plugins {
/// <summary>
/// Base class for InputField
/// </summary>
public abstract class MobileInputReceiver : MonoBehaviour {
/// <summary>
/// Current input id
/// </summary>
private int _id;
/// <summary>
/// Init input and register interface
/// </summary>
protected virtual void Start () {
_id = MobileInput.Register (this);
}
/// <summary>
/// Action on destroy
/// </summary>
protected virtual void OnDestroy () {
MobileInput.RemoveReceiver (_id);
}
/// <summary>
/// Send data to plugin
/// </summary>
/// <param name="data">Data</param>
protected void Execute (JsonObject data) {
MobileInput.Execute (_id, data);
}
/// <summary>
/// Send data to plugin manually
/// </summary>
/// <param name="data">Data</param>
public abstract void Send (JsonObject data);
/// <summary>
/// Hide input
/// </summary>
public abstract void Hide ();
}
/// <summary>
/// Mobile native input plugin
/// </summary>
public class MobileInput : MonoBehaviour, IPlugin {
/// <summary>
/// Event name for keyboard prepare to change
/// </summary>
const string KEYBOARD_PREPARE = "KEYBOARD_PREPARE";
/// <summary>
/// Event name for keyboard show/hide
/// </summary>
const string KEYBOARD_ACTION = "KEYBOARD_ACTION";
/// <summary>
/// Delegate for show/hide keyboard action
/// </summary>
public delegate void ShowDelegate (bool isShow, int height);
/// <summary>
/// Delegate for prepare show keyboard
/// </summary>
public delegate void PrepareDelegate ();
/// <summary>
/// Handler for ShowDelegate
/// </summary>
public static ShowDelegate OnShowKeyboard = delegate { };
/// <summary>
/// Handler for PrepareDelegate
/// </summary>
public static PrepareDelegate OnPrepareKeyboard = delegate { };
/// <summary>
/// Mobile fields dictionary
/// </summary>
private Dictionary<int, MobileInputReceiver> _inputs = new Dictionary<int, MobileInputReceiver> ();
/// <summary>
/// Current instance
/// </summary>
private static MobileInput _instance;
/// <summary>
/// Cache data for hidden app state
/// </summary>
private JsonObject _data;
/// <summary>
/// Cache error for hidden app state
/// </summary>
private JsonObject _error;
/// <summary>
/// MobileInput counter
/// </summary>
private int _counter = 0;
#if UNITY_IOS
/// <summary>
/// Send data to plugin input
/// </summary>
[DllImport ("__Internal")]
private static extern void inputExecute (int id, string json);
/// <summary>
/// Init MobileInput plugin
/// </summary>
[DllImport ("__Internal")]
private static extern void inputInit ();
/// <summary>
/// Destroy MobileInput plugin
/// </summary>
[DllImport ("__Internal")]
private static extern void inputDestroy ();
#endif
/// <summary>
/// Constructor
/// </summary>
private void Awake () {
if ((object) _instance == null) {
_instance = GetComponent<MobileInput> ();
Init ();
}
}
/// <summary>
/// Plugin name
/// </summary>
public string Name {
get {
return GetType ().Name.ToLower ();
}
}
/// <summary>
/// Current instance for external access
/// </summary>
public static MobileInput Plugin {
get {
return _instance;
}
}
/// <summary>
/// Callback on data
/// </summary>
public void OnData (JsonObject data) {
Debug.Log (string.Format ("{0} plugin OnData: {1}", GetType ().Name, data.ToJsonPrettyPrintString ()));
_data = data;
try {
JsonObject response = (JsonObject) JsonNode.ParseJsonString (data["data"]);
string code = response["msg"];
switch (code) {
case KEYBOARD_PREPARE:
OnPrepareKeyboard ();
break;
case KEYBOARD_ACTION:
bool isShow = response["show"];
int height = 0;
#if UNITY_ANDROID
height = (int) (response["height"] * (float) Screen.height);
#elif UNITY_IOS
height = response["height"];
#endif
OnShowKeyboard (isShow, height);
break;
default:
int id = response["id"];
if (_inputs.ContainsKey (id)) {
GetReceiver (id).Send (response);
}
break;
}
_data = null;
} catch (Exception e) {
Debug.LogError (string.Format ("{0} plugin OnData error: {1}", GetType ().Name, e.Message));
}
}
/// <summary>
/// Callback on error
/// </summary>
public void OnError (JsonObject data) {
Debug.LogError (string.Format ("{0} plugin OnError: {0}", GetType ().Name, data.ToJsonPrettyPrintString ()));
_error = data;
try {
_error = null;
} catch (Exception e) {
Debug.LogError (string.Format ("{0} plugin OnError error: {1}", GetType ().Name, e.Message));
}
}
/// <summary>
/// Init and save new MobileInput
/// </summary>
/// <param name="receiver">Receiver</param>
/// <returns>Id</returns>
public static int Register (MobileInputReceiver receiver) {
int index = _instance._counter;
_instance._counter++;
_instance._inputs[index] = receiver;
return index;
}
/// <summary>
/// Remove MobileInput
/// </summary>
/// <param name="id">Input id</param>
public static void RemoveReceiver (int id) {
_instance._inputs.Remove (id);
}
/// <summary>
/// Get MobileInput by index
/// </summary>
/// <param name="id">Input id</param>
/// <returns>Receiver</returns>
public static MobileInputReceiver GetReceiver (int id) {
return _instance._inputs[id];
}
/// <summary>
/// Send data to plugin
/// </summary>
/// <param name="id">id</param>
/// <param name="data">json</param>
public static void Execute (int id, JsonObject data) {
data["id"] = id;
string json = data.ToJsonString ();
#if UNITY_EDITOR
Debug.Log ("MobileInput execute " + json);
#elif UNITY_ANDROID
using (AndroidJavaClass plugin = new AndroidJavaClass (string.Format (Plugins.ANDROID_CLASS_MASK, _instance.Name))) {
plugin.CallStatic ("execute", id, json);
}
#elif UNITY_IOS
inputExecute (id, json);
#endif
}
/// <summary>
/// Init plugin
/// </summary>
public static void Init () {
#if UNITY_EDITOR
#elif UNITY_ANDROID
using (AndroidJavaClass plugin = new AndroidJavaClass (string.Format (Plugins.ANDROID_CLASS_MASK, _instance.Name))) {
plugin.CallStatic ("init");
}
#elif UNITY_IOS
inputInit ();
#endif
}
/// <summary>
/// Destructor
/// </summary>
public static void Destroy () {
#if UNITY_EDITOR
#elif UNITY_ANDROID
using (AndroidJavaClass plugin = new AndroidJavaClass (string.Format (Plugins.ANDROID_CLASS_MASK, _instance.Name))) {
plugin.CallStatic ("destroy");
}
#elif UNITY_IOS
inputDestroy ();
#endif
}
/// <summary>
/// Handler to check data on focus change
/// </summary>
private void OnApplicationPause (bool pauseStatus) {
if (!pauseStatus) {
if (_data != null) {
OnData (_data);
} else if (_error != null) {
OnError (_error);
}
}
}
/// <summary>
/// Handler on app focus
/// </summary>
void OnApplicationFocus (bool focusStatus) {
if (!focusStatus) {
foreach (var item in _instance._inputs.Values) {
item.Hide ();
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,621 @@
// ----------------------------------------------------------------------------
// The MIT License
// UnityMobileInput https://github.com/mopsicus/UnityMobileInput
// Copyright (c) 2018 Mopsicus <mail@mopsicus.ru>
// ----------------------------------------------------------------------------
using System;
using System.Collections;
using NiceJson;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
namespace Mopsicus.Plugins {
/// <summary>
/// Wrapper for Unity InputField
/// Add this component on your InputField
/// </summary>
[RequireComponent (typeof (InputField))]
public class MobileInputField : MobileInputReceiver {
/// <summary>
/// Config structure
/// </summary>
private struct MobileInputConfig {
public bool Multiline;
public Color TextColor;
public Color BackgroundColor;
public string ContentType;
public string InputType;
public string KeyboardType;
public float FontSize;
public string Align;
public string Placeholder;
public Color PlaceholderColor;
public int CharacterLimit;
}
/// <summary>
/// Button type
/// </summary>
public enum ReturnKeyType {
Default,
Next,
Done,
Search
}
/// <summary>
/// "Done" button visible (for iOS)
/// </summary>
public bool IsWithDoneButton = true;
/// <summary>
/// "(x)" button visible (for iOS)
/// </summary>
public bool IsWithClearButton = true;
/// <summary>
/// Type for return button
/// </summary>
public ReturnKeyType ReturnKey;
/// <summary>
/// Action when Return pressed, for subscribe
/// </summary>
public Action OnReturnPressed = delegate { };
/// <summary>
/// Action when Focus changed
/// </summary>
public Action<bool> OnFocusChanged = delegate { };
/// <summary>
/// Event when Return pressed, for Unity inspector
/// </summary>
public UnityEvent OnReturnPressedEvent;
/// <summary>
/// Mobile input creation flag
/// </summary>
private bool _isMobileInputCreated = false;
/// <summary>
/// InputField object
/// </summary>
private InputField _inputObject;
/// <summary>
/// Text object from _inputObject
/// </summary>
private Text _inputObjectText;
/// <summary>
/// Set focus on create flag
/// </summary>
private bool _isFocusOnCreate;
/// <summary>
/// Set visible on create flag
/// </summary>
private bool _isVisibleOnCreate = true;
/// <summary>
/// Last field position cache
/// </summary>
private Rect _lastRect;
/// <summary>
/// Current config
/// </summary>
private MobileInputConfig _config;
/// <summary>
/// InputField create event
/// </summary>
const string CREATE = "CREATE_EDIT";
/// <summary>
/// InputField remove event
/// </summary>
const string REMOVE = "REMOVE_EDIT";
/// <summary>
/// Set text to InputField
/// </summary>
const string SET_TEXT = "SET_TEXT";
/// <summary>
/// Set new Rect, position, size
/// </summary>
const string SET_RECT = "SET_RECT";
/// <summary>
/// Set focus to InputField
/// </summary>
const string SET_FOCUS = "SET_FOCUS";
/// <summary>
/// Event when InputField is focused
/// </summary>
const string ON_FOCUS = "ON_FOCUS";
/// <summary>
/// Event when InputField is unfocused
/// </summary>
const string ON_UNFOCUS = "ON_UNFOCUS";
/// <summary>
/// Set visible to InputField
/// </summary>
const string SET_VISIBLE = "SET_VISIBLE";
/// <summary>
/// Event when text changing in InputField
/// </summary>
const string TEXT_CHANGE = "TEXT_CHANGE";
/// <summary>
/// Event when text end changing in InputField
/// </summary>
const string TEXT_END_EDIT = "TEXT_END_EDIT";
/// <summary>
/// Event for Android
/// </summary>
const string ANDROID_KEY_DOWN = "ANDROID_KEY_DOWN";
/// <summary>
/// Event when Return key pressed
/// </summary>
const string RETURN_PRESSED = "RETURN_PRESSED";
/// <summary>
/// Ready event
/// </summary>
const string READY = "READY";
/// <summary>
/// Constructor
/// </summary>
private void Awake () {
_inputObject = this.GetComponent<InputField> ();
if ((object) _inputObject == null) {
Debug.LogError (string.Format ("No found InputField for {0} MobileInput", this.name));
throw new MissingComponentException ();
}
_inputObjectText = _inputObject.textComponent;
}
/// <summary>
/// Create mobile input on Start with coroutine
/// </summary>
protected override void Start () {
base.Start ();
StartCoroutine (InitialzieOnNextFrame ());
}
/// <summary>
/// Show native on enable
/// </summary>
private void OnEnable () {
if (_isMobileInputCreated) {
this.SetVisible (true);
}
}
/// <summary>
/// Hide native on disable
/// </summary>
private void OnDisable () {
if (_isMobileInputCreated) {
this.SetFocus (false);
this.SetVisible (false);
}
}
/// <summary>
/// Destructor
/// </summary>
protected override void OnDestroy () {
RemoveNative ();
base.OnDestroy ();
}
/// <summary>
/// Handler for app focus lost
/// </summary>
private void OnApplicationFocus (bool hasFocus) {
if (!_isMobileInputCreated || !this.Visible) {
return;
}
this.SetVisible (hasFocus);
}
/// <summary>
/// Current InputField for external access
/// </summary>
public InputField InputField {
get {
return _inputObject;
}
}
/// <summary>
/// MobileInput visible
/// </summary>
public bool Visible {
get;
private set;
}
/// <summary>
/// MobileInput text
/// </summary>
public string Text {
get {
return _inputObject.text;
}
set {
_inputObject.text = value;
SetTextNative (value);
}
}
/// <summary>
/// Initialization coroutine
/// </summary>
private IEnumerator InitialzieOnNextFrame () {
yield return null;
this.PrepareNativeEdit ();
#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR
this.CreateNativeEdit ();
this.SetTextNative (this._inputObjectText.text);
_inputObject.placeholder.gameObject.SetActive (false);
_inputObject.enabled = false;
_inputObjectText.enabled = false;
#endif
}
/// <summary>
/// Check position on each frame
/// If changed - send to plugin
/// It's need when app rotate on input field chage position
/// </summary>
private void Update () {
#if UNITY_ANDROID && !UNITY_EDITOR
this.UpdateForceKeyeventForAndroid ();
#endif
if (this._inputObject != null && _isMobileInputCreated) {
#if !UNITY_EDITOR
if (Input.touchCount > 0) {
for (int i = 0; i < Input.touches.Length; i++) {
if (!this._inputObjectText.rectTransform.rect.Contains (Input.touches[i].position)) {
Hide ();
return;
}
}
}
#endif
SetRectNative (this._inputObjectText.rectTransform);
}
}
/// <summary>
/// Get sizes and convert to current screen size
/// </summary>
/// <param name="rect">RectTranform from Gameobject</param>
/// <returns>Rect</returns>
public static Rect GetScreenRectFromRectTransform (RectTransform rect) {
Vector3[] corners = new Vector3[4];
rect.GetWorldCorners (corners);
float xMin = float.PositiveInfinity;
float xMax = float.NegativeInfinity;
float yMin = float.PositiveInfinity;
float yMax = float.NegativeInfinity;
for (int i = 0; i < 4; i++) {
Vector3 screenCoord;
if (rect.GetComponentInParent<Canvas> ().renderMode == RenderMode.ScreenSpaceOverlay) {
screenCoord = corners[i];
} else {
screenCoord = RectTransformUtility.WorldToScreenPoint (Camera.main, corners[i]);
}
if (screenCoord.x < xMin) {
xMin = screenCoord.x;
}
if (screenCoord.x > xMax) {
xMax = screenCoord.x;
}
if (screenCoord.y < yMin) {
yMin = screenCoord.y;
}
if (screenCoord.y > yMax) {
yMax = screenCoord.y;
}
}
Rect result = new Rect (xMin, Screen.height - yMax, xMax - xMin, yMax - yMin);
return result;
}
/// <summary>
/// Prepare config
/// </summary>
private void PrepareNativeEdit () {
Text placeHolder = _inputObject.placeholder.GetComponent<Text> ();
_config.Placeholder = placeHolder.text;
_config.PlaceholderColor = placeHolder.color;
_config.CharacterLimit = _inputObject.characterLimit;
Rect rect = GetScreenRectFromRectTransform (this._inputObjectText.rectTransform);
float ratio = rect.height / _inputObjectText.rectTransform.rect.height;
_config.FontSize = ((float) _inputObjectText.fontSize) * ratio;
_config.TextColor = _inputObjectText.color;
_config.Align = _inputObjectText.alignment.ToString ();
_config.ContentType = _inputObject.contentType.ToString ();
_config.BackgroundColor = _inputObject.colors.normalColor;
_config.Multiline = (_inputObject.lineType == InputField.LineType.SingleLine) ? false : true;
_config.KeyboardType = _inputObject.keyboardType.ToString ();
_config.InputType = _inputObject.inputType.ToString ();
}
/// <summary>
/// Text change callback
/// </summary>
/// <param name="text">new text</param>
private void OnTextChange (string text) {
if (text == this._inputObject.text) {
return;
}
this._inputObject.text = text;
if (this._inputObject.onValueChanged != null) {
this._inputObject.onValueChanged.Invoke (text);
}
}
/// <summary>
/// Text change end callback
/// </summary>
/// <param name="text">text</param>
private void OnTextEditEnd (string text) {
this._inputObject.text = text;
if (this._inputObject.onEndEdit != null) {
this._inputObject.onEndEdit.Invoke (text);
}
SetFocus (false);
}
/// <summary>
/// Sending data to plugin
/// </summary>
/// <param name="data">JSON</param>
public override void Send (JsonObject data) {
MobileInput.Plugin.StartCoroutine (PluginsMessageRoutine (data));
}
/// <summary>
/// Remove focus, keyboard when app lose focus
/// </summary>
public override void Hide () {
this.SetFocus (false);
}
/// <summary>
/// Coroutine for send, so its not freeze main thread
/// </summary>
/// <param name="data">JSON</param>
private IEnumerator PluginsMessageRoutine (JsonObject data) {
yield return null;
string msg = data["msg"];
if (msg.Equals (TEXT_CHANGE)) {
string text = data["text"];
this.OnTextChange (text);
} else if (msg.Equals (READY)) {
this.Ready ();
} else if (msg.Equals (ON_FOCUS)) {
OnFocusChanged (true);
} else if (msg.Equals (ON_UNFOCUS)) {
OnFocusChanged (false);
} else if (msg.Equals (TEXT_END_EDIT)) {
string text = data["text"];
this.OnTextEditEnd (text);
} else if (msg.Equals (RETURN_PRESSED)) {
OnReturnPressed ();
if (OnReturnPressedEvent != null) {
OnReturnPressedEvent.Invoke ();
}
}
}
/// <summary>
/// Convert float value to InvariantCulture string
/// </summary>
/// <param name="value">float value</param>
/// <returns></returns>
private string InvariantCultureString (float value){
return value.ToString ("G", System.Globalization.CultureInfo.InvariantCulture);
}
/// <summary>
/// Create native input field
/// </summary>
private void CreateNativeEdit () {
Rect rect = GetScreenRectFromRectTransform (this._inputObjectText.rectTransform);
JsonObject data = new JsonObject ();
data["msg"] = CREATE;
data["x"] = InvariantCultureString(rect.x / Screen.width);
data["y"] = InvariantCultureString(rect.y / Screen.height);
data["width"] = InvariantCultureString(rect.width / Screen.width);
data["height"] = InvariantCultureString(rect.height / Screen.height);
data["character_limit"] = _config.CharacterLimit;
data["text_color_r"] = InvariantCultureString(_config.TextColor.r);
data["text_color_g"] = InvariantCultureString(_config.TextColor.g);
data["text_color_b"] = InvariantCultureString(_config.TextColor.b);
data["text_color_a"] = InvariantCultureString(_config.TextColor.a);
data["back_color_r"] = InvariantCultureString(_config.BackgroundColor.r);
data["back_color_g"] = InvariantCultureString(_config.BackgroundColor.g);
data["back_color_b"] = InvariantCultureString(_config.BackgroundColor.b);
data["back_color_a"] = InvariantCultureString(_config.BackgroundColor.a);
data["font_size"] = InvariantCultureString(_config.FontSize);
data["content_type"] = _config.ContentType;
data["align"] = _config.Align;
data["with_done_button"] = this.IsWithDoneButton;
data["with_clear_button"] = this.IsWithClearButton;
data["placeholder"] = _config.Placeholder;
data["placeholder_color_r"] = InvariantCultureString(_config.PlaceholderColor.r);
data["placeholder_color_g"] = InvariantCultureString(_config.PlaceholderColor.g);
data["placeholder_color_b"] = InvariantCultureString(_config.PlaceholderColor.b);
data["placeholder_color_a"] = InvariantCultureString(_config.PlaceholderColor.a);
data["multiline"] = _config.Multiline;
data["input_type"] = _config.InputType;
data["keyboard_type"] = _config.KeyboardType;
switch (ReturnKey) {
case ReturnKeyType.Next:
data["return_key_type"] = "Next";
break;
case ReturnKeyType.Done:
data["return_key_type"] = "Done";
break;
case ReturnKeyType.Search:
data["return_key_type"] = "Search";
break;
default:
data["return_key_type"] = "Default";
break;
}
this.Execute (data);
}
/// <summary>
/// New field successfully added
/// </summary>
void Ready () {
_isMobileInputCreated = true;
if (!_isVisibleOnCreate) {
SetVisible (false);
}
if (_isFocusOnCreate) {
SetFocus (true);
}
}
/// <summary>
/// Set text to field
/// </summary>
/// <param name="text">New text</param>
void SetTextNative (string text) {
JsonObject data = new JsonObject ();
data["msg"] = SET_TEXT;
data["text"] = text;
this.Execute (data);
}
/// <summary>
/// Remove field
/// </summary>
private void RemoveNative () {
JsonObject data = new JsonObject ();
data["msg"] = REMOVE;
this.Execute (data);
}
/// <summary>
/// Set new size and position
/// </summary>
/// <param name="inputRect">RectTransform</param>
public void SetRectNative (RectTransform inputRect) {
Rect rect = GetScreenRectFromRectTransform (inputRect);
if (_lastRect == rect) {
return;
}
_lastRect = rect;
JsonObject data = new JsonObject ();
data["msg"] = SET_RECT;
data["x"] = InvariantCultureString(rect.x / Screen.width);
data["y"] = InvariantCultureString(rect.y / Screen.height);
data["width"] = InvariantCultureString(rect.width / Screen.width);
data["height"] = InvariantCultureString(rect.height / Screen.height);
this.Execute (data);
}
/// <summary>
/// Set focus on field
/// </summary>
/// <param name="isFocus">true | false</param>
public void SetFocus (bool isFocus) {
#if (UNITY_IOS || UNITY_ANDROID) && !UNITY_EDITOR
if (!_isMobileInputCreated) {
_isFocusOnCreate = isFocus;
return;
}
JsonObject data = new JsonObject ();
data["msg"] = SET_FOCUS;
data["is_focus"] = isFocus;
this.Execute (data);
#else
if (gameObject.activeInHierarchy) {
if (isFocus) {
_inputObject.ActivateInputField ();
} else {
_inputObject.DeactivateInputField ();
}
} else {
_isFocusOnCreate = isFocus;
}
#endif
}
/// <summary>
/// Set field visible
/// </summary>
/// <param name="isVisible">true | false</param>
public void SetVisible (bool isVisible) {
if (!_isMobileInputCreated) {
_isVisibleOnCreate = isVisible;
return;
}
JsonObject data = new JsonObject ();
data["msg"] = SET_VISIBLE;
data["is_visible"] = isVisible;
this.Execute (data);
this.Visible = isVisible;
}
#if UNITY_ANDROID && !UNITY_EDITOR
/// <summary>
/// Send android button state
/// </summary>
/// <param name="key">Code</param>
private void ForceSendKeydownAndroid (string key) {
JsonObject data = new JsonObject ();
data["msg"] = ANDROID_KEY_DOWN;
data["key"] = key;
this.Execute (data);
}
/// <summary>
/// Keyboard handler
/// </summary>
private void UpdateForceKeyeventForAndroid () {
if (UnityEngine.Input.anyKeyDown) {
if (UnityEngine.Input.GetKeyDown (KeyCode.Backspace)) {
this.ForceSendKeydownAndroid ("backspace");
} else {
foreach (char c in UnityEngine.Input.inputString) {
if (c == '\n') {
this.ForceSendKeydownAndroid ("enter");
} else {
this.ForceSendKeydownAndroid (Input.inputString);
}
}
}
}
}
#endif
}
}

View File

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

View File

@@ -0,0 +1,132 @@
// ----------------------------------------------------------------------------
// The MIT License
// UnityMobileInput https://github.com/mopsicus/UnityMobileInput
// Copyright (c) 2018 Mopsicus <mail@mopsicus.ru>
// ----------------------------------------------------------------------------
using UnityEngine;
using System;
using System.Collections.Generic;
using NiceJson;
#if UNITY_IOS
using System.Runtime.InteropServices;
#endif
namespace Mopsicus.Plugins {
/// <summary>
/// Mobile plugin interface
/// Each plugin must implement it
/// </summary>
public interface IPlugin {
/// <summary>
/// Plaugin name
/// </summary>
string Name { get; }
/// <summary>
/// Callback on get data
/// </summary>
void OnData (JsonObject data);
/// <summary>
/// Callback on get error
/// </summary>
void OnError (JsonObject data);
}
/// <summary>
/// Plugin service to manager all mobile plugins
/// </summary>
public class Plugins : MonoBehaviour {
#if UNITY_ANDROID
/// <summary>
/// Mask for Java classes
/// </summary>
public const string ANDROID_CLASS_MASK = "ru.mopsicus.{0}.Plugin";
#elif UNITY_IOS
/// <summary>
/// Init iOS plugins
/// </summary>
[DllImport ("__Internal")]
private static extern void pluginsInit (string data);
#endif
/// <summary>
/// Gameobject name on scene to receive data
/// ACHTUNG! Do not change it
/// </summary>
const string _dataObject = "Plugins";
/// <summary>
/// Function name to receive data
/// ACHTUNG! Do not change it
/// </summary>
const string _dataReceiver = "OnDataReceive";
/// <summary>
/// Dictionary of plugins
/// </summary>
private Dictionary<string, IPlugin> _plugins;
private void Awake () {
name = _dataObject;
DontDestroyOnLoad (gameObject);
InitPlugins ();
}
private void OnDestroy () {
_plugins = null;
}
/// <summary>
/// Init all plugins in app
/// </summary>
void InitPlugins () {
gameObject.AddComponent<MobileInput> ();
//
// other plugins
//
IPlugin[] plugins = GetComponents<IPlugin> ();
_plugins = new Dictionary<string, IPlugin> (plugins.Length);
foreach (var item in plugins) {
_plugins.Add (item.Name, item);
}
JsonObject data = new JsonObject ();
data["object"] = _dataObject;
data["receiver"] = _dataReceiver;
#if UNITY_IOS
pluginsInit (data.ToJsonString ());
#endif
Debug.Log ("Plugins init");
}
/// <summary>
/// Handler to process data to plugin
/// </summary>
/// <param name="data">data from plugin</param>
void OnDataReceive (string data) {
Debug.Log ("Plugins receive data: " + data);
try {
JsonObject info = (JsonObject) JsonNode.ParseJsonString (data);
if (_plugins.ContainsKey (info["name"])) {
IPlugin plugin = _plugins[info["name"]];
if (info.ContainsKey ("error")) {
plugin.OnError (info);
} else {
plugin.OnData (info);
}
} else {
Debug.LogError (string.Format ("{0} plugin does not exists", info["name"]));
}
} catch (Exception e) {
Debug.LogError (string.Format ("Plugins receive error: {0}, stack: {1}", e.Message, e.StackTrace));
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: af391257446ba4bc6b9124b683ceb46a
timeCreated: 1522834071
licenseType: Pro
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: