add
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa35a23a042f14b12ae57cd621e8a6e8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd55cea5e8ce949a395e88966d10f0bf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6ec5c22f648534b2490352b23199aae1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7efa08dd091db4556b539d69d5505878
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
132
Assets/3rd/UnityMobileInput/Scripts/UnityMobileInput/Plugins.cs
Normal file
132
Assets/3rd/UnityMobileInput/Scripts/UnityMobileInput/Plugins.cs
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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:
|
||||
Reference in New Issue
Block a user