├── README.md ├── demo ├── Assembly-CSharp-vs.csproj ├── Assembly-CSharp.csproj ├── Assets │ ├── AssetStoreTools.meta │ ├── AssetStoreTools │ │ ├── Editor.meta │ │ ├── Editor │ │ │ ├── AssetStoreTools.dll │ │ │ ├── AssetStoreTools.dll.meta │ │ │ ├── AssetStoreToolsExtra.dll │ │ │ ├── AssetStoreToolsExtra.dll.meta │ │ │ ├── DroidSansMono.ttf │ │ │ ├── DroidSansMono.ttf.meta │ │ │ ├── icon.png │ │ │ └── icon.png.meta │ │ └── Labels.asset │ ├── NativeEditPlugin.meta │ ├── NativeEditPlugin │ │ ├── Plugins.meta │ │ ├── Plugins │ │ │ ├── Android │ │ │ │ ├── AndroidManifest.xml │ │ │ │ └── nativeeditplugin.jar │ │ │ ├── iOS.meta │ │ │ └── iOS │ │ │ │ ├── EditBox_iOS.h │ │ │ │ ├── EditBox_iOS.h.meta │ │ │ │ ├── EditBox_iOS.m │ │ │ │ ├── EditBox_iOS.m.meta │ │ │ │ ├── JsonObject.h │ │ │ │ ├── JsonObject.h.meta │ │ │ │ ├── JsonObject.m │ │ │ │ ├── JsonObject.m.meta │ │ │ │ ├── PlaceholderTextView.h │ │ │ │ ├── PlaceholderTextView.h.meta │ │ │ │ ├── PlaceholderTextView.m │ │ │ │ ├── PlaceholderTextView.m.meta │ │ │ │ ├── PluginMsgInterface.mm │ │ │ │ └── PluginMsgInterface.mm.meta │ │ ├── README.md │ │ ├── demo.meta │ │ ├── demo │ │ │ ├── demo.cs │ │ │ ├── demo.cs.meta │ │ │ ├── demo.unity │ │ │ └── demo.unity.meta │ │ ├── scripts.meta │ │ └── scripts │ │ │ ├── JsonObject.cs │ │ │ ├── JsonObject.cs.meta │ │ │ ├── MiniJSON.cs │ │ │ ├── MiniJSON.cs.meta │ │ │ ├── NativeEditBox.cs │ │ │ ├── NativeEditBox.cs.meta │ │ │ ├── PluginMsgHandler.cs │ │ │ └── PluginMsgHandler.cs.meta │ ├── Plugins.meta │ └── Plugins │ │ ├── Android.meta │ │ └── Android │ │ ├── AndroidManifest.xml │ │ └── AndroidManifest.xml.meta ├── ProjectSettings │ ├── AudioManager.asset │ ├── DynamicsManager.asset │ ├── EditorBuildSettings.asset │ ├── EditorSettings.asset │ ├── GraphicsSettings.asset │ ├── InputManager.asset │ ├── NavMeshAreas.asset │ ├── NetworkManager.asset │ ├── Physics2DSettings.asset │ ├── ProjectSettings.asset │ ├── ProjectVersion.txt │ ├── QualitySettings.asset │ ├── TagManager.asset │ └── TimeManager.asset ├── demo-csharp.sln ├── demo.sln ├── demo.userprefs ├── nativeedit-csharp.sln ├── nativeedit.sln └── nativeedit.userprefs ├── release └── NativeEditPlugin │ ├── Plugins │ ├── Android │ │ ├── AndroidManifest.xml │ │ └── nativeeditplugin.jar │ └── iOS │ │ ├── EditBox_iOS.h │ │ ├── EditBox_iOS.m │ │ ├── JsonObject.h │ │ ├── JsonObject.m │ │ ├── PlaceholderTextView.h │ │ ├── PlaceholderTextView.m │ │ └── PluginMsgInterface.mm │ ├── README.md │ ├── demo │ ├── demo.cs │ └── demo.unity │ └── scripts │ ├── JsonObject.cs │ ├── MiniJSON.cs │ ├── NativeEditBox.cs │ └── PluginMsgHandler.cs └── src └── androidProj ├── .gradle └── 2.2.1 │ └── taskArtifacts │ ├── cache.properties │ ├── cache.properties.lock │ ├── fileHashes.bin │ ├── fileSnapshots.bin │ ├── outputFileStates.bin │ └── taskArtifacts.bin ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── libraries │ ├── appcompat_v7_22_0_0.xml │ ├── classes.xml │ ├── support_annotations_22_0_0.xml │ └── support_v4_22_0_0.xml ├── misc.xml ├── modules.xml ├── scopes │ └── scope_settings.xml ├── vcs.xml └── workspace.xml ├── androidProj.iml ├── app └── app.iml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties ├── nativeeditplugin ├── .gitignore ├── build.gradle ├── libs │ └── classes.jar ├── nativeeditplugin.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── bkmin │ │ └── android │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── bkmin │ │ └── android │ │ ├── EditBox.java │ │ └── NativeEditPlugin.java │ └── res │ └── values │ └── strings.xml └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | ## UnityNativeEdit v1.0 2 | Unity Native Input Plugin for both iOS and Android (Unity UI InputField compatible). 3 | This means you don't need a separate 'Unity' Input box and you can use all native text functions such as `Select`, `Copy` and `Paste` 4 | 5 | ## Usage 6 | 1. Simply copy the files in `release/NativeEditPlugin` into your existing unity project asset folder. 7 | 2. Make empty Gameobject and attach ```PluginMsgHandler``` to your new GameObject 8 | 3. Attach ```NativeEditBox``` script to your UnityUI ```InputField```object. 9 | 4. Build and run on your android or ios device! 10 | 5. For `Android` make sure your `AndroidManifest.xml` has the following setting 11 | 12 | ```xml 13 | 15 | ... 16 | 17 | ... 18 | 19 | ``` 20 | You can refer to sample `AndroidManifest.xml` in `/Plugings/Android` folder 21 | 22 | 23 | ## Etc 24 | 1. NativeEditBox will work with delegate defined in your Unity UI InputField, `On Value Change` and `End Edit` 25 | 2. It's open source and free to use/redistribute! 26 | 3. Please refer to `demo` Unity project. 27 | -------------------------------------------------------------------------------- /demo/Assembly-CSharp-vs.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.20506 7 | 2.0 8 | {C132594A-928C-86DF-54BB-28617E4DB357} 9 | Library 10 | Properties 11 | 12 | Assembly-CSharp 13 | v3.5 14 | 512 15 | Assets 16 | 17 | 18 | true 19 | full 20 | false 21 | Temp\bin\Debug\ 22 | DEBUG;TRACE;UNITY_5_0_1;UNITY_5_0;UNITY_5;ENABLE_LICENSE_RENAME;ENABLE_NEW_BUGREPORTER;ENABLE_2D_PHYSICS;ENABLE_4_6_FEATURES;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_FRAME_DEBUGGER;ENABLE_GENERICS;ENABLE_HOME_SCREEN;ENABLE_IMAGEEFFECTS;ENABLE_LIGHT_PROBES_LEGACY;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_NEW_HIERARCHY;ENABLE_PHYSICS;ENABLE_PHYSICS_PHYSX3;ENABLE_PLUGIN_INSPECTOR;ENABLE_SHADOWS;ENABLE_SINGLE_INSTANCE_BUILD_SETTING;ENABLE_SPRITES;ENABLE_TERRAIN;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_WWW;ENABLE_AUDIOMIXER_SUSPEND;ENABLE_NONPRO;INCLUDE_DYNAMIC_GI;INCLUDE_GI;INCLUDE_IL2CPP;PLATFORM_SUPPORTS_MONO;UNITY_IPHONE;ENABLE_RUNTIME_GI;ENABLE_SUBSTANCE;ENABLE_GAMECENTER;ENABLE_NETWORK;UNITY_IPHONE_API;UNITY_IOS;ENABLE_TEXTUREID_MAP;PLAYERCONNECTION_LISTENS_FIXED_PORT;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_MONO;DEVELOPMENT_BUILD;ENABLE_PROFILER;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_OSX 23 | prompt 24 | 4 25 | 0169 26 | 27 | 28 | pdbonly 29 | true 30 | Temp\bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 0169 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | /Applications/Unity/Unity.app/Contents/Frameworks/Managed/UnityEngine.dll 43 | 44 | 45 | /Applications/Unity/Unity.app/Contents/Frameworks/Managed/UnityEditor.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll 58 | 59 | 60 | /Applications/Unity/Unity.app/Contents/PlaybackEngines/iossupport/UnityEditor.iOS.Extensions.Xcode.dll 61 | 62 | 63 | 64 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /demo/Assembly-CSharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.20506 7 | 2.0 8 | {C132594A-928C-86DF-54BB-28617E4DB357} 9 | Library 10 | Properties 11 | 12 | Assembly-CSharp 13 | v3.5 14 | 512 15 | Assets 16 | 17 | 18 | true 19 | full 20 | false 21 | Temp\bin\Debug\ 22 | DEBUG;TRACE;UNITY_5_0_1;UNITY_5_0;UNITY_5;ENABLE_LICENSE_RENAME;ENABLE_NEW_BUGREPORTER;ENABLE_2D_PHYSICS;ENABLE_4_6_FEATURES;ENABLE_AUDIO;ENABLE_CACHING;ENABLE_CLOTH;ENABLE_FRAME_DEBUGGER;ENABLE_GENERICS;ENABLE_HOME_SCREEN;ENABLE_IMAGEEFFECTS;ENABLE_LIGHT_PROBES_LEGACY;ENABLE_MICROPHONE;ENABLE_MULTIPLE_DISPLAYS;ENABLE_NEW_HIERARCHY;ENABLE_PHYSICS;ENABLE_PHYSICS_PHYSX3;ENABLE_PLUGIN_INSPECTOR;ENABLE_SHADOWS;ENABLE_SINGLE_INSTANCE_BUILD_SETTING;ENABLE_SPRITES;ENABLE_TERRAIN;ENABLE_UNITYEVENTS;ENABLE_WEBCAM;ENABLE_WWW;ENABLE_AUDIOMIXER_SUSPEND;ENABLE_NONPRO;INCLUDE_DYNAMIC_GI;INCLUDE_GI;INCLUDE_IL2CPP;PLATFORM_SUPPORTS_MONO;UNITY_IPHONE;ENABLE_RUNTIME_GI;ENABLE_SUBSTANCE;ENABLE_GAMECENTER;ENABLE_NETWORK;UNITY_IPHONE_API;UNITY_IOS;ENABLE_TEXTUREID_MAP;PLAYERCONNECTION_LISTENS_FIXED_PORT;DEBUGGER_LISTENS_FIXED_PORT;ENABLE_MONO;DEVELOPMENT_BUILD;ENABLE_PROFILER;UNITY_EDITOR;UNITY_EDITOR_64;UNITY_EDITOR_OSX 23 | prompt 24 | 4 25 | 0169 26 | 27 | 28 | pdbonly 29 | true 30 | Temp\bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 0169 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | /Applications/Unity/Unity.app/Contents/Frameworks/Managed/UnityEngine.dll 43 | 44 | 45 | /Applications/Unity/Unity.app/Contents/Frameworks/Managed/UnityEditor.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | /Applications/Unity/Unity.app/Contents/UnityExtensions/Unity/GUISystem/UnityEngine.UI.dll 58 | 59 | 60 | /Applications/Unity/Unity.app/Contents/PlaybackEngines/iossupport/UnityEditor.iOS.Extensions.Xcode.dll 61 | 62 | 63 | 64 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b0264992f90e27e48beeee54b801c8f2 3 | folderAsset: yes 4 | timeCreated: 1430955535 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 47c3c77b488bde14eac761a5144660ed 3 | folderAsset: yes 4 | timeCreated: 1430955535 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/AssetStoreTools.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/Assets/AssetStoreTools/Editor/AssetStoreTools.dll -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/AssetStoreTools.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 11188de2b6632fa4486c470af4b55fa0 3 | PluginImporter: 4 | serializedVersion: 1 5 | iconMap: {} 6 | executionOrder: {} 7 | isPreloaded: 0 8 | platformData: 9 | Any: 10 | enabled: 1 11 | settings: {} 12 | userData: 13 | assetBundleName: 14 | assetBundleVariant: 15 | -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/AssetStoreToolsExtra.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/Assets/AssetStoreTools/Editor/AssetStoreToolsExtra.dll -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/AssetStoreToolsExtra.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e35231d99115e9e4c8cb29414445831f 3 | PluginImporter: 4 | serializedVersion: 1 5 | iconMap: {} 6 | executionOrder: {} 7 | isPreloaded: 0 8 | platformData: 9 | Any: 10 | enabled: 1 11 | settings: {} 12 | userData: 13 | assetBundleName: 14 | assetBundleVariant: 15 | -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/DroidSansMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/Assets/AssetStoreTools/Editor/DroidSansMono.ttf -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/DroidSansMono.ttf.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 35021dda9bd03434195c7dcd6ad7618f 3 | TrueTypeFontImporter: 4 | serializedVersion: 2 5 | fontSize: 16 6 | forceTextureCase: -2 7 | characterSpacing: 1 8 | characterPadding: 0 9 | includeFontData: 1 10 | use2xBehaviour: 0 11 | fontNames: [] 12 | customCharacters: 13 | fontRenderingMode: 0 14 | userData: 15 | assetBundleName: 16 | assetBundleVariant: 17 | -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/Assets/AssetStoreTools/Editor/icon.png -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Editor/icon.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 41844c716792706449720732c95b2747 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | serializedVersion: 2 6 | mipmaps: 7 | mipMapMode: 0 8 | enableMipMap: 1 9 | linearTexture: 0 10 | correctGamma: 0 11 | fadeOut: 0 12 | borderMipMap: 0 13 | mipMapFadeDistanceStart: 1 14 | mipMapFadeDistanceEnd: 3 15 | bumpmap: 16 | convertToNormalMap: 0 17 | externalNormalMap: 0 18 | heightScale: .25 19 | normalMapFilter: 0 20 | isReadable: 0 21 | grayScaleToAlpha: 0 22 | generateCubemap: 0 23 | cubemapConvolution: 0 24 | cubemapConvolutionSteps: 8 25 | cubemapConvolutionExponent: 1.5 26 | seamlessCubemap: 0 27 | textureFormat: -1 28 | maxTextureSize: 1024 29 | textureSettings: 30 | filterMode: -1 31 | aniso: -1 32 | mipBias: -1 33 | wrapMode: -1 34 | nPOTScale: 1 35 | lightmap: 0 36 | rGBM: 0 37 | compressionQuality: 50 38 | spriteMode: 0 39 | spriteExtrude: 1 40 | spriteMeshType: 1 41 | alignment: 0 42 | spritePivot: {x: .5, y: .5} 43 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 44 | spritePixelsToUnits: 100 45 | alphaIsTransparency: 0 46 | textureType: -1 47 | buildTargetSettings: [] 48 | spriteSheet: 49 | sprites: [] 50 | spritePackingTag: 51 | userData: 52 | assetBundleName: 53 | assetBundleVariant: 54 | -------------------------------------------------------------------------------- /demo/Assets/AssetStoreTools/Labels.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/Assets/AssetStoreTools/Labels.asset -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d541cfba5912d43fc837495d4a0d6011 3 | folderAsset: yes 4 | timeCreated: 1430959055 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6aacecba01ec1410bbf45026b033c1ab 3 | folderAsset: yes 4 | timeCreated: 1430955862 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 14 | 15 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/Android/nativeeditplugin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/Assets/NativeEditPlugin/Plugins/Android/nativeeditplugin.jar -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 86b9e2365e8a748a7b13e8ba9458dd8d 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/EditBox_iOS.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "JsonObject.h" 4 | 5 | /// UnityEditBox Plugin 6 | /// Written by bkmin 2014/11 Nureka Inc. 7 | 8 | #define MSG_CREATE @"CreateEdit" 9 | #define MSG_REMOVE @"RemoveEdit" 10 | #define MSG_SET_TEXT @"SetText" 11 | #define MSG_GET_TEXT @"GetText" 12 | #define MSG_SET_RECT @"SetRect" 13 | #define MSG_SET_FOCUS @"SetFocus" 14 | #define MSG_SET_VISIBLE @"SetVisible" 15 | #define MSG_TEXT_CHANGE @"TextChange" 16 | #define MSG_TEXT_END_EDIT @"TextEndEdit" 17 | 18 | @interface EditBoxHoldView : UIView 19 | { 20 | 21 | } 22 | 23 | -(id) initHoldView:(CGRect) frame; 24 | 25 | @end 26 | 27 | @interface EditBox : NSObject 28 | { 29 | UIView* editView; 30 | UIViewController* viewController; 31 | CGRect rectKeyboardFrame; 32 | UIToolbar* keyboardDoneButtonView; 33 | UIBarButtonItem* doneButton; 34 | int tag; 35 | } 36 | 37 | +(void) initializeEditBox:(UIViewController*) _unityViewController unityName:(const char*) unityName; 38 | +(JsonObject*) processRecvJsonMsg:(int)nSenderId msg:(JsonObject*) jsonMsg; 39 | +(void) finalizeEditBox; 40 | 41 | -(void) showKeyboard:(bool)isShow; 42 | -(BOOL) IsFocused; 43 | @end 44 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/EditBox_iOS.h.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4be821ace4f6e414596aefd815c62414 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/EditBox_iOS.m: -------------------------------------------------------------------------------- 1 | #import "EditBox_iOS.h" 2 | #import "PlaceholderTextView.h" 3 | #import 4 | 5 | /// UnityEditBox Plugin 6 | /// Written by bkmin 2014/11 Nureka Inc. 7 | 8 | UIViewController* unityViewController = nil; 9 | NSMutableDictionary* dictEditBox = nil; 10 | EditBoxHoldView* viewPlugin = nil; 11 | 12 | #define DEF_PixelPerPoint 2.2639f // 72 points per inch. iPhone 163DPI 13 | char g_unityName[64]; 14 | 15 | bool approxEqualFloat(float x, float y) 16 | { 17 | return fabs(x-y) < 0.001f; 18 | } 19 | 20 | @implementation EditBoxHoldView 21 | 22 | -(id) initHoldView:(CGRect) frame 23 | { 24 | if (self = [super initWithFrame:frame]) 25 | { 26 | UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)]; 27 | [self addGestureRecognizer:tap]; 28 | self.userInteractionEnabled = YES; 29 | } 30 | return self; 31 | } 32 | 33 | -(void) tapAction:(id) sender 34 | { 35 | for (EditBox *eb in [dictEditBox allValues]) 36 | { 37 | if ([eb IsFocused]) 38 | { 39 | [eb showKeyboard:NO]; 40 | } 41 | } 42 | } 43 | 44 | @end 45 | 46 | 47 | @implementation EditBox 48 | 49 | +(void) initializeEditBox:(UIViewController*) _unityViewController unityName:(const char*) unityName 50 | { 51 | unityViewController = _unityViewController; 52 | dictEditBox = [[NSMutableDictionary alloc] init]; 53 | 54 | CGRect frameView = unityViewController.view.frame; 55 | frameView.origin = CGPointMake(0.0f, 0.0f); 56 | viewPlugin = [[EditBoxHoldView alloc] initHoldView:frameView]; 57 | [unityViewController.view addSubview:viewPlugin]; 58 | 59 | strcpy(g_unityName, unityName); 60 | } 61 | 62 | +(JsonObject*) makeJsonRet:(BOOL) isError error:(NSString*) strError 63 | { 64 | JsonObject* jsonRet = [[JsonObject alloc] init]; 65 | 66 | [jsonRet setBool:@"bError" value:isError]; 67 | [jsonRet setString:@"strError" value:strError]; 68 | return jsonRet; 69 | } 70 | 71 | +(JsonObject*) processRecvJsonMsg:(int)nSenderId msg:(JsonObject*) jsonMsg 72 | { 73 | JsonObject* jsonRet; 74 | 75 | NSString* msg = [jsonMsg getString:@"msg"]; 76 | if ([msg isEqualToString:MSG_CREATE]) 77 | { 78 | EditBox* nb = [[EditBox alloc] initWithViewController:unityViewController _tag:nSenderId]; 79 | [nb create:jsonMsg]; 80 | [dictEditBox setObject:nb forKey:[NSNumber numberWithInt:nSenderId]]; 81 | jsonRet = [EditBox makeJsonRet:NO error:@""]; 82 | } 83 | else 84 | { 85 | EditBox* b = [dictEditBox objectForKey:[NSNumber numberWithInt:nSenderId]]; 86 | if (b) 87 | { 88 | jsonRet = [b processJsonMsg:msg json:jsonMsg]; 89 | } 90 | else 91 | { 92 | jsonRet = [EditBox makeJsonRet:YES error:@"EditBox not found"]; 93 | } 94 | } 95 | return jsonRet; 96 | } 97 | 98 | +(void) finalizeEditBox 99 | { 100 | NSArray* objs = [dictEditBox allValues]; 101 | for (EditBox* b in objs) 102 | { 103 | [b remove]; 104 | } 105 | dictEditBox = nil; 106 | } 107 | 108 | -(BOOL) IsFocused 109 | { 110 | return editView.isFirstResponder; 111 | } 112 | 113 | -(void) sendJsonToUnity:(JsonObject*) json 114 | { 115 | [json setInt:@"senderId" value:tag]; 116 | 117 | 118 | NSData *jsonData = [json serialize]; 119 | NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 120 | UnitySendMessage(g_unityName, "OnMsgFromPlugin", [jsonString UTF8String]); 121 | } 122 | 123 | -(JsonObject*) processJsonMsg:(NSString*) msg json:(JsonObject*) jsonMsg 124 | { 125 | JsonObject* jsonRet = [EditBox makeJsonRet:NO error:@""]; 126 | if ([msg isEqualToString:MSG_REMOVE]) 127 | { 128 | [self remove]; 129 | } 130 | else if ([msg isEqualToString:MSG_SET_TEXT]) 131 | { 132 | [self setText:jsonMsg]; 133 | } 134 | else if ([msg isEqualToString:MSG_GET_TEXT]) 135 | { 136 | NSString* text = [self getText]; 137 | [jsonRet setString:@"text" value:text]; 138 | } 139 | else if ([msg isEqualToString:MSG_SET_RECT]) 140 | { 141 | [self setRect:jsonMsg]; 142 | } 143 | else if ([msg isEqualToString:MSG_SET_FOCUS]) 144 | { 145 | BOOL isFocus = [jsonMsg getBool:@"isFocus"]; 146 | [self setFocus:isFocus]; 147 | } 148 | else if ([msg isEqualToString:MSG_SET_VISIBLE]) 149 | { 150 | BOOL isVisible = [jsonMsg getBool:@"isVisible"]; 151 | [self setVisible:isVisible]; 152 | } 153 | 154 | return jsonRet; 155 | } 156 | 157 | -(id)initWithViewController:(UIViewController*)theViewController _tag:(int)_tag 158 | { 159 | if(self = [super init]) { 160 | viewController = theViewController; 161 | tag = _tag; 162 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; 163 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 164 | } 165 | return self; 166 | } 167 | 168 | -(void) setRect:(JsonObject*)json 169 | { 170 | float x = [json getFloat:@"x"] * viewController.view.bounds.size.width; 171 | float y = [json getFloat:@"y"] * viewController.view.bounds.size.height; 172 | float width = [json getFloat:@"width"] * viewController.view.bounds.size.width; 173 | float height = [json getFloat:@"height"] * viewController.view.bounds.size.height; 174 | 175 | x -= editView.superview.frame.origin.x; 176 | y -= editView.superview.frame.origin.y; 177 | editView.frame = CGRectMake(x, y, width, height); 178 | } 179 | 180 | -(void) create:(JsonObject*)json 181 | { 182 | NSString* placeholder = [json getString:@"placeHolder"]; 183 | 184 | NSString* font = [json getString:@"font"]; 185 | float fontSize = [json getFloat:@"fontSize"]; 186 | 187 | float x = [json getFloat:@"x"] * viewController.view.bounds.size.width; 188 | float y = [json getFloat:@"y"] * viewController.view.bounds.size.height; 189 | float width = [json getFloat:@"width"] * viewController.view.bounds.size.width; 190 | float height = [json getFloat:@"height"] * viewController.view.bounds.size.height; 191 | 192 | float textColor_r = [json getFloat:@"textColor_r"]; 193 | float textColor_g = [json getFloat:@"textColor_g"]; 194 | float textColor_b = [json getFloat:@"textColor_b"]; 195 | float textColor_a = [json getFloat:@"textColor_a"]; 196 | float backColor_r = [json getFloat:@"backColor_r"]; 197 | float backColor_g = [json getFloat:@"backColor_g"]; 198 | float backColor_b = [json getFloat:@"backColor_b"]; 199 | float backColor_a = [json getFloat:@"backColor_a"]; 200 | 201 | NSString* contentType = [json getString:@"contentType"]; 202 | NSString* alignment = [json getString:@"align"]; 203 | BOOL withDoneButton = [json getBool:@"withDoneButton"]; 204 | BOOL multiline = [json getBool:@"multiline"]; 205 | 206 | BOOL autoCorr = NO; 207 | BOOL password = NO; 208 | UIKeyboardType keyType = UIKeyboardTypeDefault; 209 | 210 | if ([contentType isEqualToString:@"Autocorrected"]) 211 | { 212 | autoCorr = YES; 213 | } 214 | else if ([contentType isEqualToString:@"IntegerNumber"]) 215 | { 216 | keyType = UIKeyboardTypeNumberPad; 217 | } 218 | else if ([contentType isEqualToString:@"DecimalNumber"]) 219 | { 220 | keyType = UIKeyboardTypeDecimalPad; 221 | } 222 | else if ([contentType isEqualToString:@"Alphanumeric"]) 223 | { 224 | keyType = UIKeyboardTypeAlphabet; 225 | } 226 | else if ([contentType isEqualToString:@"Name"]) 227 | { 228 | keyType = UIKeyboardTypeNamePhonePad; 229 | } 230 | else if ([contentType isEqualToString:@"EmailAddress"]) 231 | { 232 | keyType = UIKeyboardTypeEmailAddress; 233 | } 234 | else if ([contentType isEqualToString:@"Password"]) 235 | { 236 | password = YES; 237 | } 238 | else if ([contentType isEqualToString:@"Pin"]) 239 | { 240 | keyType = UIKeyboardTypePhonePad; 241 | } 242 | 243 | UIControlContentHorizontalAlignment halign = UIControlContentHorizontalAlignmentLeft; 244 | UIControlContentVerticalAlignment valign = UIControlContentVerticalAlignmentCenter; 245 | 246 | if ([alignment isEqualToString:@"UpperLeft"]) 247 | { 248 | valign = UIControlContentVerticalAlignmentTop; 249 | halign = UIControlContentHorizontalAlignmentLeft; 250 | } 251 | else if ([alignment isEqualToString:@"UpperCenter"]) 252 | { 253 | valign = UIControlContentVerticalAlignmentTop; 254 | halign = UIControlContentHorizontalAlignmentCenter; 255 | } 256 | else if ([alignment isEqualToString:@"UpperRight"]) 257 | { 258 | valign = UIControlContentVerticalAlignmentTop; 259 | halign = UIControlContentHorizontalAlignmentRight; 260 | } 261 | else if ([alignment isEqualToString:@"MiddleLeft"]) 262 | { 263 | valign = UIControlContentVerticalAlignmentCenter; 264 | halign = UIControlContentHorizontalAlignmentLeft; 265 | } 266 | else if ([alignment isEqualToString:@"MiddleCenter"]) 267 | { 268 | valign = UIControlContentVerticalAlignmentCenter; 269 | halign = UIControlContentHorizontalAlignmentCenter; 270 | } 271 | else if ([alignment isEqualToString:@"MiddleRight"]) 272 | { 273 | valign = UIControlContentVerticalAlignmentCenter; 274 | halign = UIControlContentHorizontalAlignmentRight; 275 | } 276 | else if ([alignment isEqualToString:@"LowerLeft"]) 277 | { 278 | valign = UIControlContentVerticalAlignmentBottom; 279 | halign = UIControlContentHorizontalAlignmentLeft; 280 | } 281 | else if ([alignment isEqualToString:@"LowerCenter"]) 282 | { 283 | valign = UIControlContentVerticalAlignmentBottom; 284 | halign = UIControlContentHorizontalAlignmentCenter; 285 | } 286 | else if ([alignment isEqualToString:@"LowerRight"]) 287 | { 288 | valign = UIControlContentVerticalAlignmentBottom; 289 | halign = UIControlContentHorizontalAlignmentRight; 290 | } 291 | 292 | fontSize = fontSize / DEF_PixelPerPoint; 293 | 294 | if (withDoneButton) 295 | { 296 | keyboardDoneButtonView = [[UIToolbar alloc] init]; 297 | [keyboardDoneButtonView sizeToFit]; 298 | doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self 299 | action:@selector(doneClicked:)]; 300 | 301 | UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 302 | [keyboardDoneButtonView setItems:[NSArray arrayWithObjects:flexibleSpace, flexibleSpace,doneButton, nil]]; 303 | } 304 | else 305 | { 306 | keyboardDoneButtonView = nil; 307 | } 308 | 309 | if (multiline) 310 | { 311 | PlaceholderTextView* textView = [[PlaceholderTextView alloc] initWithFrame:CGRectMake(x, y, width, height)]; 312 | textView.keyboardType = keyType; 313 | [textView setFont:[UIFont fontWithName:font size:fontSize]]; 314 | textView.scrollEnabled = TRUE; 315 | 316 | textView.delegate = self; 317 | textView.tag = 0; 318 | textView.text = @""; 319 | 320 | textView.textColor = [UIColor colorWithRed:textColor_r green:textColor_g blue:textColor_b alpha:textColor_a]; 321 | textView.backgroundColor =[UIColor colorWithRed:backColor_r green:backColor_g blue:backColor_b alpha:backColor_a]; 322 | textView.returnKeyType = UIReturnKeyDefault; 323 | textView.autocorrectionType = autoCorr ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo ; 324 | textView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); 325 | textView.placeholder = placeholder; 326 | textView.delegate = self; 327 | 328 | [textView setSecureTextEntry:password]; 329 | if (keyboardDoneButtonView != nil) textView.inputAccessoryView = keyboardDoneButtonView; 330 | 331 | 332 | /// Todo 333 | /// UITextView Alignment is not implemented 334 | 335 | editView = textView; 336 | } 337 | else 338 | { 339 | UITextField* textField = [[UITextField alloc] initWithFrame:CGRectMake(x, y, width, height)]; 340 | textField.keyboardType = keyType; 341 | [textField setFont:[UIFont fontWithName:font size:fontSize]]; 342 | textField.delegate = self; 343 | textField.tag = 0; 344 | textField.text = @""; 345 | textField.textColor = [UIColor colorWithRed:textColor_r green:textColor_g blue:textColor_b alpha:textColor_a]; 346 | textField.backgroundColor =[UIColor colorWithRed:backColor_r green:backColor_g blue:backColor_b alpha:backColor_a]; 347 | textField.returnKeyType = UIReturnKeyDefault; 348 | textField.autocorrectionType = autoCorr ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo; 349 | textField.contentVerticalAlignment = valign; 350 | textField.contentHorizontalAlignment = halign; 351 | textField.placeholder = placeholder; 352 | textField.delegate = self; 353 | 354 | [textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; 355 | [textField setSecureTextEntry:password]; 356 | if (keyboardDoneButtonView != nil) textField.inputAccessoryView = keyboardDoneButtonView; 357 | 358 | editView = textField; 359 | } 360 | [viewPlugin addSubview:editView]; 361 | } 362 | 363 | -(void) setText:(JsonObject*)json 364 | { 365 | NSString* newText = [json getString:@"text"]; 366 | if([editView isKindOfClass:[UITextField class]]) { 367 | [((UITextField*)editView) setText:newText]; 368 | } else if([editView isKindOfClass:[UITextView class]]){ 369 | [((UITextView*)editView) setText:newText]; 370 | } 371 | } 372 | 373 | -(IBAction) doneClicked:(id)sender 374 | { 375 | [self showKeyboard:false]; 376 | } 377 | 378 | -(int) getLineCount 379 | { 380 | if([editView isKindOfClass:[UITextField class]]) { 381 | return 1; 382 | } else if([editView isKindOfClass:[UITextView class]]){ 383 | UITextView* tv = ((UITextView*)editView); 384 | int lineCount = (int) tv.contentSize.height / tv.font.lineHeight; 385 | return (lineCount); 386 | } 387 | return 0; 388 | } 389 | 390 | 391 | -(void) remove 392 | { 393 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 394 | [editView resignFirstResponder]; 395 | [editView removeFromSuperview]; 396 | if (keyboardDoneButtonView != nil) 397 | { 398 | doneButton = nil; 399 | keyboardDoneButtonView = nil; 400 | } 401 | } 402 | 403 | -(void) setFocus:(BOOL) isFocus 404 | { 405 | if (isFocus) 406 | { 407 | [editView becomeFirstResponder]; 408 | } 409 | else 410 | { 411 | [editView resignFirstResponder]; 412 | } 413 | } 414 | 415 | -(NSString*) getText 416 | { 417 | if([editView isKindOfClass:[UITextField class]]) { 418 | return ((UITextField*)editView).text; 419 | } else if([editView isKindOfClass:[UITextView class]]){ 420 | return ((UITextView*)editView).text; 421 | } 422 | return @""; 423 | } 424 | 425 | -(bool) isFocused 426 | { 427 | return editView.isFirstResponder; 428 | } 429 | 430 | -(void) showKeyboard:(bool)isShow 431 | { 432 | [viewController.view endEditing:(isShow ? YES : NO)]; 433 | } 434 | -(void) setVisible:(bool)isVisible 435 | { 436 | editView.hidden = (isVisible ? NO : YES); 437 | } 438 | 439 | -(void) onTextChange:(NSString*) text 440 | { 441 | JsonObject* jsonToUnity = [[JsonObject alloc] init]; 442 | 443 | [jsonToUnity setString:@"msg" value:MSG_TEXT_CHANGE]; 444 | [jsonToUnity setString:@"text" value:text]; 445 | [self sendJsonToUnity:jsonToUnity]; 446 | } 447 | 448 | -(void) onTextEditEnd:(NSString*) text 449 | { 450 | JsonObject* jsonToUnity = [[JsonObject alloc] init]; 451 | 452 | [jsonToUnity setString:@"msg" value:MSG_TEXT_END_EDIT]; 453 | [jsonToUnity setString:@"text" value:text]; 454 | [self sendJsonToUnity:jsonToUnity]; 455 | } 456 | 457 | -(void) textViewDidChange:(UITextView *)textView 458 | { 459 | [self onTextChange:textView.text]; 460 | } 461 | 462 | -(void) textViewDidEndEditing:(UITextView *)textView 463 | { 464 | [self onTextEditEnd:textView.text]; 465 | } 466 | 467 | -(void) textFieldDidChange :(UITextField *)theTextField{ 468 | [self onTextChange:theTextField.text]; 469 | } 470 | 471 | -(void) textFieldDidEndEditing:(UITextField *)textField 472 | { 473 | [self onTextEditEnd:textField.text]; 474 | } 475 | 476 | -(void) keyboardWillShow:(NSNotification *)notification 477 | { 478 | if (![editView isFirstResponder]) return; 479 | 480 | NSDictionary* keyboardInfo = [notification userInfo]; 481 | NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey]; 482 | rectKeyboardFrame = [keyboardFrameBegin CGRectValue]; 483 | 484 | } 485 | 486 | -(void) keyboardWillHide:(NSNotification*)notification 487 | { 488 | if (![editView isFirstResponder]) return; 489 | 490 | } 491 | 492 | -(float) getKeyboardheight 493 | { 494 | float height = rectKeyboardFrame.size.height / viewController.view.bounds.size.height; 495 | return height; 496 | } 497 | 498 | 499 | @end 500 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/EditBox_iOS.m.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5815c9642cf774804aadf042a07142e6 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/JsonObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // JsonObject.h 3 | // stockissue 4 | // 5 | // Created by KYUNGMIN BANG on 12/8/14. 6 | // Copyright (c) 2014 Nureka Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JsonObject : NSObject 12 | 13 | @property (nonatomic, strong) NSMutableDictionary* dict; 14 | 15 | -(id)initWithJsonData:(NSData*) json; 16 | -(id)initWithCmd:(NSString*) cmd; 17 | -(id)initWithDictionary:(NSMutableDictionary*) _dict; 18 | -(NSData*)serialize; 19 | 20 | -(void) setInt:(NSString*) key value:(int)value; 21 | -(void) setFloat:(NSString*) key value:(float)value; 22 | -(void) setBool:(NSString*) key value:(BOOL)value; 23 | -(void) setString:(NSString*) key value:(NSString*)value; 24 | -(void) setArray:(NSString*) key value:(NSArray*) value; 25 | -(void) setJsonObject:(NSString*) key value:(JsonObject*) value; 26 | 27 | -(int) getInt:(NSString*) key; 28 | -(float) getFloat:(NSString*) key; 29 | -(BOOL) getBool:(NSString*) key; 30 | -(NSString*) getString:(NSString*) key; 31 | -(NSArray*) getJsonArray:(NSString*) key; 32 | -(NSArray*) getDictArray:(NSString*) key; 33 | -(JsonObject*) getJsonObject:(NSString*) key; 34 | 35 | @end 36 | 37 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/JsonObject.h.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 44a934fb557174e1e9af925e42770b24 3 | timeCreated: 1430351529 4 | licenseType: Pro 5 | PluginImporter: 6 | serializedVersion: 1 7 | iconMap: {} 8 | executionOrder: {} 9 | isPreloaded: 0 10 | platformData: 11 | Any: 12 | enabled: 1 13 | settings: {} 14 | userData: 15 | assetBundleName: 16 | assetBundleVariant: 17 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/JsonObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // JsonObject.m 3 | // stockissue 4 | // 5 | // Created by KYUNGMIN BANG on 12/8/14. 6 | // Copyright (c) 2014 Nureka Inc. All rights reserved. 7 | // 8 | 9 | #import "JsonObject.h" 10 | 11 | 12 | @implementation JsonObject 13 | @synthesize dict; 14 | 15 | -(void) dealloc 16 | { 17 | dict = nil; 18 | } 19 | 20 | -(id)init 21 | { 22 | self = [super init]; 23 | if (self) 24 | { 25 | dict = [[NSMutableDictionary alloc] init]; 26 | 27 | } 28 | return self; 29 | } 30 | 31 | -(id)initWithDictionary:(NSMutableDictionary*) _dict 32 | { 33 | self = [super init]; 34 | if (self) 35 | { 36 | dict = _dict; 37 | 38 | } 39 | return self; 40 | } 41 | 42 | -(id)initWithJsonData:(NSData*) json 43 | { 44 | self = [super init]; 45 | if (self) 46 | { 47 | NSError *error; 48 | 49 | dict = [NSJSONSerialization 50 | JSONObjectWithData:json 51 | options:NSJSONReadingMutableContainers 52 | error:&error]; 53 | if (dict == nil) 54 | { 55 | NSLog(@"Json parse error %@",[error description]); 56 | } 57 | } 58 | return self; 59 | } 60 | -(id)initWithCmd:(NSString*) cmd 61 | { 62 | self = [self init]; 63 | if (dict) 64 | { 65 | dict[@"cmd"] = cmd; 66 | } 67 | return self; 68 | } 69 | 70 | -(NSData*)serialize 71 | { 72 | NSError *error; 73 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict 74 | options:0 75 | error:&error]; 76 | return jsonData; 77 | } 78 | 79 | -(void) setInt:(NSString*) key value:(int)value 80 | { 81 | dict[key] = [NSNumber numberWithInt:value]; 82 | } 83 | -(void) setFloat:(NSString*) key value:(float)value 84 | { 85 | dict[key] = [NSNumber numberWithFloat:value]; 86 | } 87 | -(void) setBool:(NSString*) key value:(BOOL)value 88 | { 89 | dict[key] = [NSNumber numberWithBool:value]; 90 | } 91 | -(void) setString:(NSString*) key value:(NSString*)value 92 | { 93 | dict[key] = value; 94 | } 95 | -(void) setArray:(NSString*) key value:(NSArray*) value 96 | { 97 | dict[key] = value; 98 | } 99 | -(void) setJsonObject:(NSString*) key value:(JsonObject*) value 100 | { 101 | dict[key] = value.dict; 102 | } 103 | 104 | -(int) getInt:(NSString*) key 105 | { 106 | id obj = [dict objectForKey:key]; 107 | if (obj == nil || obj == (id)[NSNull null]) return 0; 108 | return [obj intValue]; 109 | } 110 | -(float) getFloat:(NSString*) key 111 | { 112 | id obj = [dict objectForKey:key]; 113 | if (obj == nil || obj == (id)[NSNull null]) return 0.0f; 114 | return [obj floatValue]; 115 | } 116 | -(BOOL) getBool:(NSString*) key 117 | { 118 | id obj = [dict objectForKey:key]; 119 | if (obj == nil || obj == (id)[NSNull null]) return NO; 120 | return [obj boolValue]; 121 | } 122 | -(NSString*) getString:(NSString*) key 123 | { 124 | id obj = [dict objectForKey:key]; 125 | if (!obj || obj == (id)[NSNull null]) return @""; 126 | return (NSString*) obj; 127 | } 128 | -(NSArray*) getDictArray:(NSString*) key 129 | { 130 | id obj = [dict objectForKey:key]; 131 | if (obj == nil || obj == (id)[NSNull null]) return [[NSArray alloc] init]; 132 | return (NSArray*) obj; 133 | } 134 | -(NSArray*) getJsonArray:(NSString*) key 135 | { 136 | id obj = [dict objectForKey:key]; 137 | NSMutableArray* arr = [[NSMutableArray alloc] init]; 138 | if (obj == nil || obj == (id)[NSNull null]) return arr; 139 | for (id arrObj in (NSMutableArray*) obj) { 140 | JsonObject* newObj = [[JsonObject alloc] initWithDictionary:(NSMutableDictionary*) arrObj]; 141 | [arr addObject:newObj]; 142 | } 143 | return (NSArray*) arr; 144 | } 145 | -(JsonObject*) getJsonObject:(NSString*) key 146 | { 147 | id obj = [dict objectForKey:key]; 148 | JsonObject* newObj = [[JsonObject alloc] init]; 149 | if (obj == nil || obj == (id)[NSNull null]) return newObj; 150 | newObj.dict = (NSMutableDictionary*) obj; 151 | return newObj; 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/JsonObject.m.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b4de1bb970b5a49a982cc91817847573 3 | timeCreated: 1430351529 4 | licenseType: Pro 5 | PluginImporter: 6 | serializedVersion: 1 7 | iconMap: {} 8 | executionOrder: {} 9 | isPreloaded: 0 10 | platformData: 11 | Any: 12 | enabled: 1 13 | settings: {} 14 | userData: 15 | assetBundleName: 16 | assetBundleVariant: 17 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/PlaceholderTextView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface PlaceholderTextView : UITextView 5 | { 6 | NSObject* _editBox; 7 | } 8 | 9 | @property(nonatomic, strong) NSString *placeholder; 10 | 11 | @property (nonatomic, strong) UIColor *realTextColor UI_APPEARANCE_SELECTOR; 12 | @property (nonatomic, strong) UIColor *placeholderColor UI_APPEARANCE_SELECTOR; 13 | 14 | -(void) SetEditbox:(NSObject*) box; 15 | 16 | @end -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/PlaceholderTextView.h.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 80d5992a0f19242b280f279570b95e50 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/PlaceholderTextView.m: -------------------------------------------------------------------------------- 1 | #import "PlaceholderTextView.h" 2 | #import "EditBox_iOS.h" 3 | 4 | @interface PlaceholderTextView () 5 | 6 | @property (unsafe_unretained, nonatomic, readonly) NSString* realText; 7 | 8 | - (void) beginEditing:(NSNotification*) notification; 9 | - (void) endEditing:(NSNotification*) notification; 10 | 11 | @end 12 | 13 | @implementation PlaceholderTextView 14 | 15 | @synthesize realTextColor; 16 | @synthesize placeholder; 17 | @synthesize placeholderColor; 18 | 19 | #pragma mark - 20 | #pragma mark Initialisation 21 | 22 | - (id) initWithFrame:(CGRect)frame { 23 | if ((self = [super initWithFrame:frame])) { 24 | [self awakeFromNib]; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)awakeFromNib { 30 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginEditing:) name:UITextViewTextDidBeginEditingNotification object:self]; 31 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endEditing:) name:UITextViewTextDidEndEditingNotification object:self]; 32 | 33 | self.realTextColor = self.textColor; 34 | self.placeholderColor = [UIColor lightGrayColor]; 35 | } 36 | 37 | #pragma mark - 38 | #pragma mark Setter/Getters 39 | 40 | - (void) setPlaceholder:(NSString *)aPlaceholder { 41 | if ([self.realText isEqualToString:placeholder] && ![self isFirstResponder]) { 42 | self.text = aPlaceholder; 43 | } 44 | if (aPlaceholder != placeholder) { 45 | placeholder = aPlaceholder; 46 | } 47 | 48 | 49 | [self endEditing:nil]; 50 | } 51 | 52 | - (void)setPlaceholderColor:(UIColor *)aPlaceholderColor { 53 | placeholderColor = aPlaceholderColor; 54 | 55 | if ([super.text isEqualToString:self.placeholder]) { 56 | self.textColor = self.placeholderColor; 57 | } 58 | } 59 | 60 | - (NSString *) text { 61 | NSString* text = [super text]; 62 | if ([text isEqualToString:self.placeholder]) return @""; 63 | return text; 64 | } 65 | 66 | - (void) setText:(NSString *)text { 67 | if (([text isEqualToString:@""] || text == nil) && ![self isFirstResponder]) { 68 | super.text = self.placeholder; 69 | } 70 | else { 71 | super.text = text; 72 | } 73 | 74 | if ([text isEqualToString:self.placeholder] || text == nil) { 75 | self.textColor = self.placeholderColor; 76 | } 77 | else { 78 | self.textColor = self.realTextColor; 79 | } 80 | } 81 | 82 | - (NSString *) realText { 83 | return [super text]; 84 | } 85 | 86 | - (void) beginEditing:(NSNotification*) notification { 87 | if ([self.realText isEqualToString:self.placeholder]) { 88 | super.text = nil; 89 | self.textColor = self.realTextColor; 90 | } 91 | } 92 | 93 | - (void) endEditing:(NSNotification*) notification { 94 | if ([self.realText isEqualToString:@""] || self.realText == nil) { 95 | super.text = self.placeholder; 96 | self.textColor = self.placeholderColor; 97 | } 98 | } 99 | 100 | - (void) setTextColor:(UIColor *)textColor { 101 | if ([self.realText isEqualToString:self.placeholder]) { 102 | if ([textColor isEqual:self.placeholderColor]){ 103 | [super setTextColor:textColor]; 104 | } else { 105 | self.realTextColor = textColor; 106 | } 107 | } 108 | else { 109 | self.realTextColor = textColor; 110 | [super setTextColor:textColor]; 111 | } 112 | } 113 | 114 | -(void) SetEditbox:(NSObject*)box 115 | { 116 | _editBox = box; 117 | 118 | } 119 | 120 | #pragma mark - 121 | #pragma mark Dealloc 122 | 123 | - (void)dealloc { 124 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 125 | 126 | } 127 | 128 | @end -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/PlaceholderTextView.m.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ead440a6679c8498bad6d96a9f96282e 3 | DefaultImporter: 4 | userData: 5 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/PluginMsgInterface.mm: -------------------------------------------------------------------------------- 1 | // 2 | // PluginMsgHandler.m 3 | // Unity-iPhone 4 | // 5 | // Created by KYUNGMIN BANG on 2/24/15. 6 | // 7 | // 8 | 9 | #import "EditBox_iOS.h" 10 | 11 | UIViewController* UnityGetGLViewController(); 12 | 13 | char* gCopyString(const char* string) { 14 | if(string == NULL) { 15 | return NULL; 16 | } 17 | char* ret = (char*) malloc(strlen(string) + 1); // memory will be auto-freed by unity 18 | strcpy(ret, string); 19 | return ret; 20 | } 21 | 22 | extern "C" { 23 | 24 | /* typedef void* MonoDomain; 25 | typedef void* MonoAssembly; 26 | typedef void* MonoImage; 27 | typedef void* MonoClass; 28 | typedef void* MonoObject; 29 | typedef void* MonoMethodDesc; 30 | typedef void* MonoMethod; 31 | typedef void* gpointer; 32 | typedef int gboolean; 33 | 34 | MonoDomain *mono_domain_get(); 35 | MonoAssembly *mono_domain_assembly_open(MonoDomain *domain, const char *assemblyName); 36 | MonoImage *mono_assembly_get_image(MonoAssembly *assembly); 37 | MonoMethodDesc *mono_method_desc_new(const char *methodString, gboolean useNamespace); 38 | MonoMethodDesc *mono_method_desc_free(MonoMethodDesc *desc); 39 | MonoMethod *mono_method_desc_search_in_image(MonoMethodDesc *methodDesc, MonoImage *image); 40 | MonoObject *mono_runtime_invoke(MonoMethod *method, void *obj, void **params, MonoObject **exc); 41 | gpointer mono_object_unbox(MonoObject *obj); 42 | 43 | void initializUnityPluginHandler() 44 | { 45 | MonoDomain *domain = mono_domain_get(); 46 | NSString *assemblyPath = [[[NSBundle mainBundle] bundlePath] 47 | stringByAppendingPathComponent:@"Data/Managed/Assembly-CSharp.dll"]; 48 | MonoAssembly *assembly = mono_domain_assembly_open(domain, assemblyPath.UTF8String); 49 | MonoImage *image = mono_assembly_get_image(assembly); 50 | 51 | MonoMethodDesc *desc = mono_method_desc_new("PluginMsgHandler:InitializeHandlerByNative()", FALSE); 52 | MonoMethod *method = mono_method_desc_search_in_image(desc, image); 53 | mono_runtime_invoke(method, NULL, NULL, NULL); 54 | mono_method_desc_free(desc); 55 | } */ 56 | 57 | void _iOS_InitPluginMsgHandler(const char* unityName) 58 | { 59 | [EditBox initializeEditBox:UnityGetGLViewController() unityName:unityName]; 60 | NSLog(@"_iOS_InitPluginMsgHandler called"); 61 | } 62 | 63 | char* _iOS_SendUnityMsgToPlugin(int nSenderId, const char* jsonMsgApp) 64 | { 65 | NSString* strJson = [NSString stringWithUTF8String:jsonMsgApp]; 66 | JsonObject* jsonMsg = [[JsonObject alloc] initWithJsonData:[strJson dataUsingEncoding:NSUTF8StringEncoding]]; 67 | JsonObject* jsonRet = [EditBox processRecvJsonMsg:nSenderId msg:jsonMsg]; 68 | 69 | NSString* strRet = [[NSString alloc] initWithData:[jsonRet serialize] encoding:NSUTF8StringEncoding]; 70 | return gCopyString([strRet UTF8String]); 71 | } 72 | void _iOS_ClosePluginMsgHandler() 73 | { 74 | [EditBox finalizeEditBox]; 75 | } 76 | } -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/Plugins/iOS/PluginMsgInterface.mm.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 49a9ded873bbe4dcf920129bd063913e 3 | timeCreated: 1430351529 4 | licenseType: Pro 5 | PluginImporter: 6 | serializedVersion: 1 7 | iconMap: {} 8 | executionOrder: {} 9 | isPreloaded: 0 10 | platformData: 11 | Any: 12 | enabled: 1 13 | settings: {} 14 | userData: 15 | assetBundleName: 16 | assetBundleVariant: 17 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/README.md: -------------------------------------------------------------------------------- 1 | ## UnityNativeEdit v1.0 2 | Unity Native Input Plugin for both iOS and Android (Unity UI InputField compatible). 3 | This means you don't need a separate 'Unity' Input box and you can use all native text functions such as `Select`, `Copy` and `Paste` 4 | 5 | ## Usage 6 | 1. Simply copy the files in `release/NativeEditPlugin` into your existing unity project asset folder. 7 | 2. Make empty Gameobject and attach ```PluginMsgHandler``` to your new GameObject 8 | 3. Attach ```NativeEditBox``` script to your UnityUI ```InputField```object. 9 | 4. Build and run on your android or ios device! 10 | 5. For `Android` make sure your `AndroidManifest.xml` has the following setting 11 | 12 | ```xml 13 | 15 | ... 16 | 17 | ... 18 | 19 | ``` 20 | You can refer to sample `AndroidManifest.xml` in `/Plugings/Android` folder 21 | 22 | 23 | ## Etc 24 | 1. NativeEditBox will work with delegate defined in your Unity UI InputField, `On Value Change` and `End Edit` 25 | 2. It's open source and free to use/redistribute! 26 | 3. Please refer to `demo` Unity project. 27 | 28 | 29 | --> Goto https://github.com/kmbang/UnityNativeEdit/ for latest update -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/demo.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9afd885945d234ee287edaf3288ca395 3 | folderAsset: yes 4 | timeCreated: 1430955862 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/demo/demo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.EventSystems; 3 | using UnityEngine.UI; 4 | using System.Collections; 5 | 6 | public class demo : MonoBehaviour { 7 | 8 | public NativeEditBox testNativeEdit; 9 | public Canvas mainCanvas; 10 | private RectTransform rectTrans; 11 | 12 | // Use this for initialization 13 | void Start () { 14 | rectTrans = testNativeEdit.transform.FindChild("Text").GetComponent(); 15 | 16 | GameObject tempTest = GameObject.Instantiate(testNativeEdit.gameObject); 17 | tempTest.transform.SetParent(mainCanvas.transform, false); 18 | tempTest.transform.position += new Vector3(0.0f, -250.0f, 0.0f); 19 | 20 | NativeEditBox tempNB = tempTest.GetComponent();; 21 | tempNB.SetTextNative("fdfdsfsd"); 22 | } 23 | 24 | // Update is called once per frame 25 | void Update () { 26 | 27 | 28 | } 29 | 30 | private string GetCurObjName() 31 | { 32 | string strObjName = ""; 33 | GameObject objSel = EventSystem.current.currentSelectedGameObject; 34 | if (objSel != null && objSel.transform.parent != null) 35 | { 36 | strObjName = objSel.transform.parent.name; 37 | } 38 | 39 | return strObjName; 40 | } 41 | 42 | public void OnEditValugChanged(string str) 43 | { 44 | Text txt = this.GetComponent(); 45 | txt.text = string.Format("[{0}] val changed {1}", this.GetCurObjName(), str); 46 | } 47 | 48 | public void OnEditEnded(string str) 49 | { 50 | Text txt = this.GetComponent(); 51 | txt.text = string.Format("[{0}] edit ended {1}", this.GetCurObjName(), str); 52 | } 53 | 54 | private bool bTempFocus = false; 55 | private bool bTempVisible = false; 56 | public void OnButton1() 57 | { 58 | bTempFocus = !bTempFocus; 59 | Debug.Log("OnButton1 clicked"); 60 | testNativeEdit.SetFocusNative(bTempFocus); 61 | } 62 | 63 | public void OnButton2() 64 | { 65 | Debug.Log("OnButton2 clicked"); 66 | bTempVisible = !bTempVisible; 67 | testNativeEdit.SetVisible(bTempVisible); 68 | } 69 | 70 | public void OnButton3() 71 | { 72 | rectTrans.sizeDelta = new Vector2(-20.0f, -5.0f); 73 | testNativeEdit.SetRectNative(rectTrans); 74 | Debug.Log("OnButton3 clicked"); 75 | } 76 | 77 | 78 | public void OnButton4() 79 | { 80 | //rectTrans.sizeDelta = new Vector2(20.0f, 5.0f); 81 | //testNativeEdit.SetRectNative(rectTrans); 82 | 83 | Text txt = this.GetComponent(); 84 | string sCurText = testNativeEdit.GetTextNative(); 85 | txt.text = string.Format("[{0}] GetText {1}", this.GetCurObjName(), sCurText); 86 | Debug.Log("OnButton4 clicked"); 87 | } 88 | 89 | public void OnButton5() 90 | { 91 | Debug.Log("OnButton5 clicked"); 92 | testNativeEdit.SetTextNative("TestText Set!!@#@5"); 93 | } 94 | 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/demo/demo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 950b9a9e1d9e94b4db99ac9e6773096c 3 | timeCreated: 1430955862 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/demo/demo.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/Assets/NativeEditPlugin/demo/demo.unity -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/demo/demo.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1139c7b6167ad4e309d3398cf5b01a7b 3 | timeCreated: 1430959201 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b93aa809b90c340e2ad3e386c67f81ef 3 | folderAsset: yes 4 | timeCreated: 1430955862 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts/JsonObject.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System; 6 | 7 | /* 8 | * Copyright (c) 2015 Kyungmin Bang 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining 11 | * a copy of this software and associated documentation files (the 12 | * "Software"), to deal in the Software without restriction, including 13 | * without limitation the rights to use, copy, modify, merge, publish, 14 | * distribute, sublicense, and/or sell copies of the Software, and to 15 | * permit persons to whom the Software is furnished to do so, subject to 16 | * the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be 19 | * included in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | 31 | /// 32 | /// JsonObject provide safe and type-compatible wrapper to access Json Element 33 | /// Safe means, even if a certain Json doesn't contain 'key', it doesn't crash. 34 | /// 35 | public class JsonObject : UnityEngine.Object { 36 | /// 37 | /// Supported object type : double, bool, string, List, Array! 38 | /// 39 | public Dictionary m_dict; 40 | 41 | public JsonObject() 42 | { 43 | m_dict = new Dictionary(); 44 | } 45 | 46 | public JsonObject(string strJson) 47 | { 48 | m_dict = MiniJSON_Min.Json.Deserialize(strJson) as Dictionary; 49 | } 50 | 51 | public JsonObject(Dictionary dict) 52 | { 53 | m_dict = dict; 54 | } 55 | 56 | public System.Object this[string key] 57 | { 58 | get { return m_dict[key]; } 59 | set { m_dict[key] = value; } 60 | } 61 | 62 | public string getCmd() { return (string) m_dict["cmd"]; } 63 | 64 | public string Serialize() 65 | { 66 | string strData = MiniJSON_Min.Json.Serialize(m_dict); 67 | return strData; 68 | } 69 | 70 | //// Deserialize helper 71 | 72 | private object GetDictValue(string key) 73 | { 74 | System.Object obj; 75 | if (m_dict.TryGetValue(key, out obj)) 76 | { 77 | return ((obj != null) ? obj : ""); 78 | } 79 | return ""; 80 | } 81 | 82 | public bool keyExist(string key) 83 | { 84 | System.Object obj; 85 | if (m_dict.TryGetValue(key, out obj)) 86 | { 87 | return true; 88 | } 89 | return false; 90 | } 91 | 92 | public Dictionary GetJsonDict(string key) 93 | { 94 | System.Object obj; 95 | if (m_dict.TryGetValue(key, out obj)) return (Dictionary) obj; 96 | return new Dictionary(); 97 | } 98 | 99 | public JsonObject GetJsonObject(string key) 100 | { 101 | Dictionary dict = this.GetJsonDict(key); 102 | return new JsonObject(dict); 103 | } 104 | 105 | public bool GetBool(string key) 106 | { 107 | bool val; 108 | if (bool.TryParse(this.GetDictValue(key).ToString(), out val)) return val; 109 | return false; 110 | } 111 | 112 | public int GetInt(string key) 113 | { 114 | int val; 115 | if (int.TryParse(this.GetDictValue(key).ToString(), out val)) return val; 116 | return 0; 117 | } 118 | 119 | public float GetFloat(string key) 120 | { 121 | float val; 122 | if (float.TryParse(this.GetDictValue(key).ToString(), out val)) return val; 123 | return 0.0f; 124 | } 125 | 126 | public string GetString(string key) 127 | { 128 | return (string) this.GetDictValue(key).ToString(); 129 | } 130 | 131 | public object GetEnum(System.Type type, string key) 132 | { 133 | string obj = (string) this.GetDictValue(key); 134 | if (obj.Length > 0) 135 | { 136 | return System.Enum.Parse(type, obj); 137 | } 138 | return 0; 139 | } 140 | 141 | public List GetListJsonObject(string key) 142 | { 143 | System.Object obj; 144 | List retList = new List(); 145 | if (m_dict.TryGetValue(key, out obj)) 146 | { 147 | foreach(object elem in (List) obj) 148 | { 149 | retList.Add(new JsonObject( (Dictionary) elem)); 150 | } 151 | } 152 | return retList; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts/JsonObject.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e63d0e7bfc81f4fa68464e1164ad4f95 3 | timeCreated: 1430955879 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts/MiniJSON.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: be9bdf430eb614c7080a7f4b10e9f9a0 3 | timeCreated: 1430955862 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts/NativeEditBox.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Kyungmin Bang 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | 25 | /* 26 | * NativeEditBox script should be attached to Unity UI InputField object 27 | * 28 | * Limitation 29 | * 30 | * 1. Screen auto rotation is not supported. 31 | */ 32 | 33 | 34 | using UnityEngine; 35 | using System.Collections; 36 | using UnityEngine.UI; 37 | 38 | public class NativeEditBox : PluginMsgReceiver { 39 | private struct EditBoxConfig 40 | { 41 | public bool multiline; 42 | public Color textColor; 43 | public Color backColor; 44 | public string contentType; 45 | public string font; 46 | public float fontSize; 47 | public string align; 48 | public string placeHolder; 49 | } 50 | 51 | public bool withDoneButton = true; 52 | 53 | private bool bNativeEditCreated = false; 54 | 55 | private InputField objUnityInput; 56 | private Text objUnityText; 57 | 58 | private static string MSG_CREATE = "CreateEdit"; 59 | private static string MSG_REMOVE = "RemoveEdit"; 60 | private static string MSG_SET_TEXT = "SetText"; 61 | private static string MSG_GET_TEXT = "GetText"; 62 | private static string MSG_SET_RECT = "SetRect"; 63 | private static string MSG_SET_FOCUS = "SetFocus"; 64 | private static string MSG_SET_VISIBLE = "SetVisible"; 65 | private static string MSG_TEXT_CHANGE = "TextChange"; 66 | private static string MSG_TEXT_END_EDIT = "TextEndEdit"; 67 | private static string MSG_ANDROID_KEY_DOWN = "AndroidKeyDown"; // to fix bug Some keys 'back' & 'enter' are eaten by unity and never arrive at plugin 68 | 69 | public static Rect GetScreenRectFromRectTransform(RectTransform rectTransform) 70 | { 71 | Vector3[] corners = new Vector3[4]; 72 | 73 | rectTransform.GetWorldCorners(corners); 74 | 75 | float xMin = float.PositiveInfinity; 76 | float xMax = float.NegativeInfinity; 77 | float yMin = float.PositiveInfinity; 78 | float yMax = float.NegativeInfinity; 79 | 80 | for (int i = 0; i < 4; i++) 81 | { 82 | // For Canvas mode Screen Space - Overlay there is no Camera; best solution I've found 83 | // is to use RectTransformUtility.WorldToScreenPoint) with a null camera. 84 | Vector3 screenCoord = RectTransformUtility.WorldToScreenPoint(null, corners[i]); 85 | 86 | if (screenCoord.x < xMin) 87 | xMin = screenCoord.x; 88 | if (screenCoord.x > xMax) 89 | xMax = screenCoord.x; 90 | if (screenCoord.y < yMin) 91 | yMin = screenCoord.y; 92 | if (screenCoord.y > yMax) 93 | yMax = screenCoord.y; 94 | } 95 | Rect result = new Rect(xMin, Screen.height - yMax, xMax - xMin, yMax - yMin); 96 | return result; 97 | } 98 | 99 | private EditBoxConfig mConfig; 100 | 101 | void Awake() 102 | { 103 | // base.Awake(); 104 | } 105 | 106 | 107 | protected new void OnDestroy() 108 | { 109 | base.OnDestroy(); 110 | } 111 | 112 | void OnEnable() 113 | { 114 | if (bNativeEditCreated) this.SetVisible(true); 115 | } 116 | 117 | void OnDisable() 118 | { 119 | if (bNativeEditCreated) this.SetVisible(false); 120 | } 121 | 122 | // Use this for initialization 123 | new void Start () { 124 | base.Start(); 125 | 126 | bNativeEditCreated = false; 127 | this.PrepareNativeEdit(); 128 | 129 | #if (UNITY_IPHONE || UNITY_ANDROID) &&!UNITY_EDITOR 130 | this.CreateNativeEdit(); 131 | this.SetTextNative(this.objUnityText.text); 132 | 133 | objUnityInput.placeholder.enabled = false; 134 | objUnityText.enabled = false; 135 | objUnityInput.enabled = false; 136 | #endif 137 | } 138 | 139 | // Update is called once per frame 140 | void Update () { 141 | this.UpdateForceKeyeventForAndroid(); 142 | } 143 | 144 | private void PrepareNativeEdit() 145 | { 146 | objUnityInput = this.GetComponent(); 147 | if (objUnityInput == null) 148 | { 149 | Debug.LogErrorFormat("No InputField found {0} NativeEditBox Error", this.name); 150 | throw new MissingComponentException(); 151 | } 152 | 153 | Graphic placeHolder = objUnityInput.placeholder; 154 | objUnityText = objUnityInput.textComponent; 155 | 156 | mConfig.placeHolder = placeHolder.GetComponent().text; 157 | mConfig.font = objUnityText.font.fontNames.Length > 0 ? objUnityText.font.fontNames[0] : "Arial"; 158 | 159 | Rect rectScreen = GetScreenRectFromRectTransform(this.objUnityText.rectTransform); 160 | float fHeightRatio = rectScreen.height / objUnityText.rectTransform.rect.height; 161 | mConfig.fontSize = ((float) objUnityText.fontSize) * fHeightRatio; 162 | 163 | mConfig.textColor = objUnityText.color; 164 | mConfig.align = objUnityText.alignment.ToString(); 165 | mConfig.contentType = objUnityInput.contentType.ToString(); 166 | mConfig.backColor = new Color(1.0f, 1.0f, 1.0f, 0.0f); 167 | mConfig.multiline = (objUnityInput.lineType == InputField.LineType.SingleLine) ? false : true; 168 | } 169 | 170 | private void onTextChange(string newText) 171 | { 172 | this.objUnityInput.text = newText; 173 | if (this.objUnityInput.onValueChange != null) this.objUnityInput.onValueChange.Invoke(newText); 174 | } 175 | 176 | private void onTextEditEnd(string newText) 177 | { 178 | this.objUnityInput.text = newText; 179 | if (this.objUnityInput.onEndEdit != null) this.objUnityInput.onEndEdit.Invoke(newText); 180 | } 181 | 182 | public override void OnPluginMsgDirect(JsonObject jsonMsg) 183 | { 184 | string msg = jsonMsg.GetString("msg"); 185 | if (msg.Equals(MSG_TEXT_CHANGE)) 186 | { 187 | string text = jsonMsg.GetString("text"); 188 | this.onTextChange(text); 189 | } 190 | else if (msg.Equals(MSG_TEXT_END_EDIT)) 191 | { 192 | string text = jsonMsg.GetString("text"); 193 | this.onTextEditEnd(text); 194 | } 195 | } 196 | 197 | private bool CheckErrorJsonRet(JsonObject jsonRet) 198 | { 199 | bool bError = jsonRet.GetBool("bError"); 200 | string strError = jsonRet.GetString("strError"); 201 | if (bError) 202 | { 203 | PluginMsgHandler.getInst().FileLogError(string.Format("NativeEditbox error {0}", strError)); 204 | } 205 | return bError; 206 | } 207 | 208 | private void CreateNativeEdit() 209 | { 210 | Rect rectScreen = GetScreenRectFromRectTransform(this.objUnityText.rectTransform); 211 | 212 | JsonObject jsonMsg = new JsonObject(); 213 | 214 | jsonMsg["msg"] = MSG_CREATE; 215 | 216 | jsonMsg["x"] = rectScreen.x / Screen.width; 217 | jsonMsg["y"] = rectScreen.y / Screen.height; 218 | jsonMsg["width"] = rectScreen.width / Screen.width; 219 | jsonMsg["height"] = rectScreen.height / Screen.height; 220 | 221 | jsonMsg["textColor_r"] = mConfig.textColor.r; 222 | jsonMsg["textColor_g"] = mConfig.textColor.g; 223 | jsonMsg["textColor_b"] = mConfig.textColor.b; 224 | jsonMsg["textColor_a"] = mConfig.textColor.a; 225 | jsonMsg["backColor_r"] = mConfig.backColor.r; 226 | jsonMsg["backColor_g"] = mConfig.backColor.g; 227 | jsonMsg["backColor_b"] = mConfig.backColor.b; 228 | jsonMsg["backColor_a"] = mConfig.backColor.a; 229 | jsonMsg["font"] = mConfig.font; 230 | jsonMsg["fontSize"] = mConfig.fontSize; 231 | jsonMsg["contentType"] = mConfig.contentType; 232 | jsonMsg["align"] = mConfig.align; 233 | jsonMsg["withDoneButton"] = this.withDoneButton; 234 | jsonMsg["placeHolder"] = mConfig.placeHolder; 235 | jsonMsg["multiline"] = mConfig.multiline; 236 | 237 | JsonObject jsonRet = this.SendPluginMsg(jsonMsg); 238 | bNativeEditCreated = !this.CheckErrorJsonRet(jsonRet); 239 | } 240 | 241 | public void SetTextNative(string newText) 242 | { 243 | JsonObject jsonMsg = new JsonObject(); 244 | 245 | jsonMsg["msg"] = MSG_SET_TEXT; 246 | jsonMsg["text"] = newText; 247 | 248 | this.SendPluginMsg(jsonMsg); 249 | } 250 | 251 | public string GetTextNative() 252 | { 253 | JsonObject jsonMsg = new JsonObject(); 254 | 255 | jsonMsg["msg"] = MSG_GET_TEXT; 256 | JsonObject jsonRet = this.SendPluginMsg(jsonMsg); 257 | bool bError = this.CheckErrorJsonRet(jsonRet); 258 | 259 | if (bError) return ""; 260 | 261 | Debug.Log(string.Format("GetTextNative {0}", jsonRet.GetString("text"))); 262 | return jsonRet.GetString("text"); 263 | } 264 | 265 | private void RemoveNative() 266 | { 267 | JsonObject jsonMsg = new JsonObject(); 268 | 269 | jsonMsg["msg"] = MSG_REMOVE; 270 | this.SendPluginMsg(jsonMsg); 271 | } 272 | 273 | public void SetRectNative(RectTransform rectTrans) 274 | { 275 | Rect rectScreen = GetScreenRectFromRectTransform(rectTrans); 276 | 277 | JsonObject jsonMsg = new JsonObject(); 278 | 279 | jsonMsg["msg"] = MSG_SET_RECT; 280 | 281 | jsonMsg["x"] = rectScreen.x / Screen.width; 282 | jsonMsg["y"] = rectScreen.y / Screen.height; 283 | jsonMsg["width"] = rectScreen.width / Screen.width; 284 | jsonMsg["height"] = rectScreen.height / Screen.height; 285 | 286 | this.SendPluginMsg(jsonMsg); 287 | } 288 | 289 | public void SetFocusNative(bool bFocus) 290 | { 291 | JsonObject jsonMsg = new JsonObject(); 292 | 293 | jsonMsg["msg"] = MSG_SET_FOCUS; 294 | jsonMsg["isFocus"] = bFocus; 295 | 296 | this.SendPluginMsg(jsonMsg); 297 | } 298 | 299 | public void SetVisible(bool bVisible) 300 | { 301 | JsonObject jsonMsg = new JsonObject(); 302 | 303 | jsonMsg["msg"] = MSG_SET_VISIBLE; 304 | jsonMsg["isVisible"] = bVisible; 305 | 306 | this.SendPluginMsg(jsonMsg); 307 | } 308 | 309 | void ForceSendKeydown_Android(string key) 310 | { 311 | JsonObject jsonMsg = new JsonObject(); 312 | 313 | jsonMsg["msg"] = MSG_ANDROID_KEY_DOWN; 314 | jsonMsg["key"] = key; 315 | this.SendPluginMsg(jsonMsg); 316 | } 317 | 318 | 319 | void UpdateForceKeyeventForAndroid() 320 | { 321 | #if UNITY_ANDROID &&!UNITY_EDITOR 322 | 323 | if (Input.anyKeyDown) 324 | { 325 | if (Input.GetKeyDown(KeyCode.Backspace)) 326 | { 327 | this.ForceSendKeydown_Android("backspace"); 328 | } 329 | else 330 | { 331 | foreach(char c in Input.inputString) 332 | { 333 | if (c == "\n"[0]) 334 | { 335 | this.ForceSendKeydown_Android("enter"); 336 | } 337 | } 338 | } 339 | } 340 | #endif 341 | } 342 | 343 | } 344 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts/NativeEditBox.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d94fbbbea60e45d68a29d0a9973dcb2 3 | timeCreated: 1430955862 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts/PluginMsgHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Kyungmin Bang 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | using UnityEngine; 25 | using System.Collections; 26 | using System.Collections.Generic; 27 | using System.Runtime.InteropServices; 28 | using System; 29 | using System.IO; 30 | using AOT; 31 | 32 | public abstract class PluginMsgReceiver : MonoBehaviour 33 | { 34 | private int nReceiverId; 35 | 36 | protected void Start() 37 | { 38 | nReceiverId = PluginMsgHandler.getInst().RegisterAndGetReceiverId(this); 39 | } 40 | 41 | protected void OnDestroy() 42 | { 43 | PluginMsgHandler.getInst().RemoveReceiver(nReceiverId); 44 | } 45 | 46 | protected void Update() 47 | { 48 | } 49 | 50 | protected JsonObject SendPluginMsg(JsonObject jsonMsg) 51 | { 52 | return PluginMsgHandler.getInst().SendMsgToPlugin(nReceiverId, jsonMsg); 53 | } 54 | 55 | public abstract void OnPluginMsgDirect(JsonObject jsonMsg); 56 | } 57 | 58 | public class PluginMsgHandler : MonoBehaviour { 59 | private static PluginMsgHandler inst; 60 | public static PluginMsgHandler getInst() { return inst; } 61 | 62 | private static bool sPluginInitialized = false; 63 | private int snCurReceiverIdx = 0; 64 | private Dictionary m_dictReceiver = new Dictionary(); 65 | 66 | private static StreamWriter fileWriter = null; 67 | 68 | public delegate void ShowKeyboardDelegate(bool bKeyboardShow, int nKeyHeight); 69 | public ShowKeyboardDelegate OnShowKeyboard = null; 70 | 71 | private static string MSG_SHOW_KEYBOARD = "ShowKeyboard"; 72 | private static string DEFAULT_NAME = "NativeEditPluginHandler"; 73 | private static bool ENABLE_WRITE_LOG = false; 74 | 75 | void Awake() 76 | { 77 | int tempRandom = (int) UnityEngine.Random.Range(0, 10000.0f); 78 | this.name = DEFAULT_NAME + tempRandom.ToString(); 79 | 80 | if (ENABLE_WRITE_LOG) 81 | { 82 | string fileName = Application.persistentDataPath + "/unity_app.log"; 83 | fileWriter = File.CreateText(fileName); 84 | fileWriter.WriteLine("[LogWriter] Initialized"); 85 | Debug.Log(string.Format("log location {0}", fileName)); 86 | } 87 | inst = this; 88 | this.InitializeHandler(); 89 | } 90 | 91 | void OnDestory() 92 | { 93 | FileLog("Application closed"); 94 | if (fileWriter != null) fileWriter.Close(); 95 | fileWriter = null; 96 | this.FinalizeHandler(); 97 | } 98 | 99 | public int RegisterAndGetReceiverId(PluginMsgReceiver receiver) 100 | { 101 | snCurReceiverIdx++; 102 | 103 | m_dictReceiver[snCurReceiverIdx] = receiver; 104 | return snCurReceiverIdx; 105 | } 106 | 107 | public void RemoveReceiver(int nReceiverId) 108 | { 109 | m_dictReceiver.Remove(nReceiverId); 110 | } 111 | 112 | public void FileLog(string strLog, string strTag = "NativeEditBoxLog") 113 | { 114 | string strOut = string.Format("[!] {0} {1} [{2}]",strTag, strLog, DateTime.Now.ToLongTimeString()); 115 | 116 | if (fileWriter != null) 117 | { 118 | fileWriter.WriteLine(strOut); 119 | fileWriter.Flush(); 120 | } 121 | 122 | Debug.Log(strOut); 123 | } 124 | public void FileLogError(string strLog) 125 | { 126 | string strOut = string.Format("[!ERROR!] {0} [{1}]", strLog, DateTime.Now.ToLongTimeString()); 127 | if (fileWriter != null) 128 | { 129 | fileWriter.WriteLine(strOut); 130 | fileWriter.Flush(); 131 | } 132 | Debug.Log(strOut); 133 | } 134 | public PluginMsgReceiver GetReceiver(int nSenderId) 135 | { 136 | return m_dictReceiver[nSenderId]; 137 | } 138 | 139 | private void OnMsgFromPlugin(string jsonPluginMsg) 140 | { 141 | if (jsonPluginMsg == null) return; 142 | 143 | JsonObject jsonMsg = new JsonObject(jsonPluginMsg); 144 | 145 | string msg = jsonMsg.GetString("msg"); 146 | 147 | if (msg.Equals(MSG_SHOW_KEYBOARD)) 148 | { 149 | bool bShow = jsonMsg.GetBool("show"); 150 | int nKeyHeight = (int)( jsonMsg.GetFloat("keyheight") * (float) Screen.height); 151 | //FileLog(string.Format("keyshow {0} height {1}", bShow, nKeyHeight)); 152 | if (OnShowKeyboard != null) 153 | { 154 | OnShowKeyboard(bShow, nKeyHeight); 155 | } 156 | } 157 | else 158 | { 159 | int nSenderId = jsonMsg.GetInt("senderId"); 160 | PluginMsgReceiver receiver = PluginMsgHandler.getInst().GetReceiver(nSenderId); 161 | receiver.OnPluginMsgDirect(jsonMsg); 162 | } 163 | } 164 | 165 | #if UNITY_IPHONE 166 | [DllImport ("__Internal")] 167 | private static extern void _iOS_InitPluginMsgHandler(string unityName); 168 | [DllImport ("__Internal")] 169 | private static extern string _iOS_SendUnityMsgToPlugin(int nSenderId, string strMsg); 170 | [DllImport ("__Internal")] 171 | private static extern void _iOS_ClosePluginMsgHandler(); 172 | 173 | public void InitializeHandler() 174 | { 175 | #if UNITY_EDITOR 176 | return; 177 | #endif 178 | if (sPluginInitialized) return; 179 | 180 | _iOS_InitPluginMsgHandler(this.name); 181 | sPluginInitialized = true; 182 | } 183 | 184 | public void FinalizeHandler() 185 | { 186 | #if UNITY_EDITOR 187 | return; 188 | #endif 189 | _iOS_ClosePluginMsgHandler(); 190 | } 191 | 192 | #elif UNITY_ANDROID 193 | 194 | private static AndroidJavaClass smAndroid; 195 | public void InitializeHandler() 196 | { 197 | #if UNITY_EDITOR 198 | return; 199 | #endif 200 | if (sPluginInitialized) return; 201 | 202 | smAndroid = new AndroidJavaClass("com.bkmin.android.NativeEditPlugin"); 203 | smAndroid.CallStatic("InitPluginMsgHandler", this.name); 204 | sPluginInitialized = true; 205 | } 206 | 207 | public void FinalizeHandler() 208 | { 209 | #if UNITY_EDITOR 210 | return; 211 | #endif 212 | smAndroid.CallStatic("ClosePluginMsgHandler"); 213 | } 214 | 215 | #else 216 | public void InitializeHandler() 217 | { 218 | } 219 | public void FinalizeHandler() 220 | { 221 | } 222 | 223 | #endif 224 | 225 | 226 | public JsonObject SendMsgToPlugin(int nSenderId, JsonObject jsonMsg) 227 | { 228 | #if UNITY_EDITOR 229 | return new JsonObject(); 230 | #endif 231 | 232 | jsonMsg["senderId"] = nSenderId; 233 | string strJson = jsonMsg.Serialize(); 234 | 235 | string strRet = ""; 236 | #if UNITY_IPHONE 237 | strRet = _iOS_SendUnityMsgToPlugin(nSenderId, strJson); 238 | #elif UNITY_ANDROID 239 | strRet = smAndroid.CallStatic("SendUnityMsgToPlugin", nSenderId, strJson); 240 | #endif 241 | 242 | JsonObject jsonRet = new JsonObject(strRet); 243 | return jsonRet; 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /demo/Assets/NativeEditPlugin/scripts/PluginMsgHandler.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26888b4265e1a4353aaf9c45987db8c3 3 | timeCreated: 1430955862 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /demo/Assets/Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43ed4bbb5a5d3413fbabfb45a14b2fc9 3 | folderAsset: yes 4 | timeCreated: 1430960228 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /demo/Assets/Plugins/Android.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 72c849c8861e341128c79b4e08f88147 3 | folderAsset: yes 4 | DefaultImporter: 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /demo/Assets/Plugins/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 14 | 15 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /demo/Assets/Plugins/Android/AndroidManifest.xml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0c193a17dd00d4eafb043a79cc8e1323 3 | TextScriptImporter: 4 | userData: 5 | assetBundleName: 6 | assetBundleVariant: 7 | -------------------------------------------------------------------------------- /demo/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.0.1f1 2 | m_StandardAssetsVersion: 0 3 | -------------------------------------------------------------------------------- /demo/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /demo/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/demo/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /demo/demo-csharp.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2008 3 | 4 | Project("{FE01CE2A-7FBA-C8FA-FAED-7C982A04E229}") = "demo", "Assembly-CSharp-vs.csproj", "{C132594A-928C-86DF-54BB-28617E4DB357}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {C132594A-928C-86DF-54BB-28617E4DB357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {C132594A-928C-86DF-54BB-28617E4DB357}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {C132594A-928C-86DF-54BB-28617E4DB357}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {C132594A-928C-86DF-54BB-28617E4DB357}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(MonoDevelopProperties) = preSolution 21 | StartupItem = Assembly-CSharp.csproj 22 | Policies = $0 23 | $0.TextStylePolicy = $1 24 | $1.inheritsSet = null 25 | $1.scope = text/x-csharp 26 | $0.CSharpFormattingPolicy = $2 27 | $2.inheritsSet = Mono 28 | $2.inheritsScope = text/x-csharp 29 | $2.scope = text/x-csharp 30 | $0.TextStylePolicy = $3 31 | $3.FileWidth = 120 32 | $3.TabWidth = 4 33 | $3.IndentWidth = 4 34 | $3.EolMarker = Unix 35 | $3.inheritsSet = Mono 36 | $3.inheritsScope = text/plain 37 | $3.scope = text/plain 38 | EndGlobalSection 39 | 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /demo/demo.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2008 3 | 4 | Project("{FE01CE2A-7FBA-C8FA-FAED-7C982A04E229}") = "demo", "Assembly-CSharp.csproj", "{C132594A-928C-86DF-54BB-28617E4DB357}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {C132594A-928C-86DF-54BB-28617E4DB357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {C132594A-928C-86DF-54BB-28617E4DB357}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {C132594A-928C-86DF-54BB-28617E4DB357}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {C132594A-928C-86DF-54BB-28617E4DB357}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(MonoDevelopProperties) = preSolution 21 | StartupItem = Assembly-CSharp.csproj 22 | Policies = $0 23 | $0.TextStylePolicy = $1 24 | $1.inheritsSet = null 25 | $1.scope = text/x-csharp 26 | $0.CSharpFormattingPolicy = $2 27 | $2.inheritsSet = Mono 28 | $2.inheritsScope = text/x-csharp 29 | $2.scope = text/x-csharp 30 | $0.TextStylePolicy = $3 31 | $3.FileWidth = 120 32 | $3.TabWidth = 4 33 | $3.IndentWidth = 4 34 | $3.EolMarker = Unix 35 | $3.inheritsSet = Mono 36 | $3.inheritsScope = text/plain 37 | $3.scope = text/plain 38 | EndGlobalSection 39 | 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /demo/demo.userprefs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demo/nativeedit-csharp.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2008 3 | 4 | Project("{E855D0F1-6F75-F4ED-FEBD-B76D61562D31}") = "nativeedit", "Assembly-CSharp-vs.csproj", "{012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(MonoDevelopProperties) = preSolution 21 | StartupItem = Assembly-CSharp.csproj 22 | Policies = $0 23 | $0.TextStylePolicy = $1 24 | $1.inheritsSet = null 25 | $1.scope = text/x-csharp 26 | $0.CSharpFormattingPolicy = $2 27 | $2.inheritsSet = Mono 28 | $2.inheritsScope = text/x-csharp 29 | $2.scope = text/x-csharp 30 | $0.TextStylePolicy = $3 31 | $3.FileWidth = 120 32 | $3.TabWidth = 4 33 | $3.IndentWidth = 4 34 | $3.EolMarker = Unix 35 | $3.inheritsSet = Mono 36 | $3.inheritsScope = text/plain 37 | $3.scope = text/plain 38 | EndGlobalSection 39 | 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /demo/nativeedit.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2008 3 | 4 | Project("{E855D0F1-6F75-F4ED-FEBD-B76D61562D31}") = "nativeedit", "Assembly-CSharp.csproj", "{012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {012A0CDF-EBAB-B5D6-D1C8-FDB6C1E56972}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | GlobalSection(MonoDevelopProperties) = preSolution 21 | StartupItem = Assembly-CSharp.csproj 22 | Policies = $0 23 | $0.TextStylePolicy = $1 24 | $1.inheritsSet = null 25 | $1.scope = text/x-csharp 26 | $0.CSharpFormattingPolicy = $2 27 | $2.inheritsSet = Mono 28 | $2.inheritsScope = text/x-csharp 29 | $2.scope = text/x-csharp 30 | $0.TextStylePolicy = $3 31 | $3.FileWidth = 120 32 | $3.TabWidth = 4 33 | $3.IndentWidth = 4 34 | $3.EolMarker = Unix 35 | $3.inheritsSet = Mono 36 | $3.inheritsScope = text/plain 37 | $3.scope = text/plain 38 | EndGlobalSection 39 | 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /demo/nativeedit.userprefs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 14 | 15 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/Android/nativeeditplugin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/release/NativeEditPlugin/Plugins/Android/nativeeditplugin.jar -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/iOS/EditBox_iOS.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "JsonObject.h" 4 | 5 | /// UnityEditBox Plugin 6 | /// Written by bkmin 2014/11 Nureka Inc. 7 | 8 | #define MSG_CREATE @"CreateEdit" 9 | #define MSG_REMOVE @"RemoveEdit" 10 | #define MSG_SET_TEXT @"SetText" 11 | #define MSG_GET_TEXT @"GetText" 12 | #define MSG_SET_RECT @"SetRect" 13 | #define MSG_SET_FOCUS @"SetFocus" 14 | #define MSG_SET_VISIBLE @"SetVisible" 15 | #define MSG_TEXT_CHANGE @"TextChange" 16 | #define MSG_TEXT_END_EDIT @"TextEndEdit" 17 | 18 | @interface EditBoxHoldView : UIView 19 | { 20 | 21 | } 22 | 23 | -(id) initHoldView:(CGRect) frame; 24 | 25 | @end 26 | 27 | @interface EditBox : NSObject 28 | { 29 | UIView* editView; 30 | UIViewController* viewController; 31 | CGRect rectKeyboardFrame; 32 | UIToolbar* keyboardDoneButtonView; 33 | UIBarButtonItem* doneButton; 34 | int tag; 35 | } 36 | 37 | +(void) initializeEditBox:(UIViewController*) _unityViewController unityName:(const char*) unityName; 38 | +(JsonObject*) processRecvJsonMsg:(int)nSenderId msg:(JsonObject*) jsonMsg; 39 | +(void) finalizeEditBox; 40 | 41 | -(void) showKeyboard:(bool)isShow; 42 | -(BOOL) IsFocused; 43 | @end 44 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/iOS/EditBox_iOS.m: -------------------------------------------------------------------------------- 1 | #import "EditBox_iOS.h" 2 | #import "PlaceholderTextView.h" 3 | #import 4 | 5 | /// UnityEditBox Plugin 6 | /// Written by bkmin 2014/11 Nureka Inc. 7 | 8 | UIViewController* unityViewController = nil; 9 | NSMutableDictionary* dictEditBox = nil; 10 | EditBoxHoldView* viewPlugin = nil; 11 | 12 | #define DEF_PixelPerPoint 2.2639f // 72 points per inch. iPhone 163DPI 13 | char g_unityName[64]; 14 | 15 | bool approxEqualFloat(float x, float y) 16 | { 17 | return fabs(x-y) < 0.001f; 18 | } 19 | 20 | @implementation EditBoxHoldView 21 | 22 | -(id) initHoldView:(CGRect) frame 23 | { 24 | if (self = [super initWithFrame:frame]) 25 | { 26 | UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)]; 27 | [self addGestureRecognizer:tap]; 28 | self.userInteractionEnabled = YES; 29 | } 30 | return self; 31 | } 32 | 33 | -(void) tapAction:(id) sender 34 | { 35 | for (EditBox *eb in [dictEditBox allValues]) 36 | { 37 | if ([eb IsFocused]) 38 | { 39 | [eb showKeyboard:NO]; 40 | } 41 | } 42 | } 43 | 44 | @end 45 | 46 | 47 | @implementation EditBox 48 | 49 | +(void) initializeEditBox:(UIViewController*) _unityViewController unityName:(const char*) unityName 50 | { 51 | unityViewController = _unityViewController; 52 | dictEditBox = [[NSMutableDictionary alloc] init]; 53 | 54 | CGRect frameView = unityViewController.view.frame; 55 | frameView.origin = CGPointMake(0.0f, 0.0f); 56 | viewPlugin = [[EditBoxHoldView alloc] initHoldView:frameView]; 57 | [unityViewController.view addSubview:viewPlugin]; 58 | 59 | strcpy(g_unityName, unityName); 60 | } 61 | 62 | +(JsonObject*) makeJsonRet:(BOOL) isError error:(NSString*) strError 63 | { 64 | JsonObject* jsonRet = [[JsonObject alloc] init]; 65 | 66 | [jsonRet setBool:@"bError" value:isError]; 67 | [jsonRet setString:@"strError" value:strError]; 68 | return jsonRet; 69 | } 70 | 71 | +(JsonObject*) processRecvJsonMsg:(int)nSenderId msg:(JsonObject*) jsonMsg 72 | { 73 | JsonObject* jsonRet; 74 | 75 | NSString* msg = [jsonMsg getString:@"msg"]; 76 | if ([msg isEqualToString:MSG_CREATE]) 77 | { 78 | EditBox* nb = [[EditBox alloc] initWithViewController:unityViewController _tag:nSenderId]; 79 | [nb create:jsonMsg]; 80 | [dictEditBox setObject:nb forKey:[NSNumber numberWithInt:nSenderId]]; 81 | jsonRet = [EditBox makeJsonRet:NO error:@""]; 82 | } 83 | else 84 | { 85 | EditBox* b = [dictEditBox objectForKey:[NSNumber numberWithInt:nSenderId]]; 86 | if (b) 87 | { 88 | jsonRet = [b processJsonMsg:msg json:jsonMsg]; 89 | } 90 | else 91 | { 92 | jsonRet = [EditBox makeJsonRet:YES error:@"EditBox not found"]; 93 | } 94 | } 95 | return jsonRet; 96 | } 97 | 98 | +(void) finalizeEditBox 99 | { 100 | NSArray* objs = [dictEditBox allValues]; 101 | for (EditBox* b in objs) 102 | { 103 | [b remove]; 104 | } 105 | dictEditBox = nil; 106 | } 107 | 108 | -(BOOL) IsFocused 109 | { 110 | return editView.isFirstResponder; 111 | } 112 | 113 | -(void) sendJsonToUnity:(JsonObject*) json 114 | { 115 | [json setInt:@"senderId" value:tag]; 116 | 117 | 118 | NSData *jsonData = [json serialize]; 119 | NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 120 | UnitySendMessage(g_unityName, "OnMsgFromPlugin", [jsonString UTF8String]); 121 | } 122 | 123 | -(JsonObject*) processJsonMsg:(NSString*) msg json:(JsonObject*) jsonMsg 124 | { 125 | JsonObject* jsonRet = [EditBox makeJsonRet:NO error:@""]; 126 | if ([msg isEqualToString:MSG_REMOVE]) 127 | { 128 | [self remove]; 129 | } 130 | else if ([msg isEqualToString:MSG_SET_TEXT]) 131 | { 132 | [self setText:jsonMsg]; 133 | } 134 | else if ([msg isEqualToString:MSG_GET_TEXT]) 135 | { 136 | NSString* text = [self getText]; 137 | [jsonRet setString:@"text" value:text]; 138 | } 139 | else if ([msg isEqualToString:MSG_SET_RECT]) 140 | { 141 | [self setRect:jsonMsg]; 142 | } 143 | else if ([msg isEqualToString:MSG_SET_FOCUS]) 144 | { 145 | BOOL isFocus = [jsonMsg getBool:@"isFocus"]; 146 | [self setFocus:isFocus]; 147 | } 148 | else if ([msg isEqualToString:MSG_SET_VISIBLE]) 149 | { 150 | BOOL isVisible = [jsonMsg getBool:@"isVisible"]; 151 | [self setVisible:isVisible]; 152 | } 153 | 154 | return jsonRet; 155 | } 156 | 157 | -(id)initWithViewController:(UIViewController*)theViewController _tag:(int)_tag 158 | { 159 | if(self = [super init]) { 160 | viewController = theViewController; 161 | tag = _tag; 162 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; 163 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 164 | } 165 | return self; 166 | } 167 | 168 | -(void) setRect:(JsonObject*)json 169 | { 170 | float x = [json getFloat:@"x"] * viewController.view.bounds.size.width; 171 | float y = [json getFloat:@"y"] * viewController.view.bounds.size.height; 172 | float width = [json getFloat:@"width"] * viewController.view.bounds.size.width; 173 | float height = [json getFloat:@"height"] * viewController.view.bounds.size.height; 174 | 175 | x -= editView.superview.frame.origin.x; 176 | y -= editView.superview.frame.origin.y; 177 | editView.frame = CGRectMake(x, y, width, height); 178 | } 179 | 180 | -(void) create:(JsonObject*)json 181 | { 182 | NSString* placeholder = [json getString:@"placeHolder"]; 183 | 184 | NSString* font = [json getString:@"font"]; 185 | float fontSize = [json getFloat:@"fontSize"]; 186 | 187 | float x = [json getFloat:@"x"] * viewController.view.bounds.size.width; 188 | float y = [json getFloat:@"y"] * viewController.view.bounds.size.height; 189 | float width = [json getFloat:@"width"] * viewController.view.bounds.size.width; 190 | float height = [json getFloat:@"height"] * viewController.view.bounds.size.height; 191 | 192 | float textColor_r = [json getFloat:@"textColor_r"]; 193 | float textColor_g = [json getFloat:@"textColor_g"]; 194 | float textColor_b = [json getFloat:@"textColor_b"]; 195 | float textColor_a = [json getFloat:@"textColor_a"]; 196 | float backColor_r = [json getFloat:@"backColor_r"]; 197 | float backColor_g = [json getFloat:@"backColor_g"]; 198 | float backColor_b = [json getFloat:@"backColor_b"]; 199 | float backColor_a = [json getFloat:@"backColor_a"]; 200 | 201 | NSString* contentType = [json getString:@"contentType"]; 202 | NSString* alignment = [json getString:@"align"]; 203 | BOOL withDoneButton = [json getBool:@"withDoneButton"]; 204 | BOOL multiline = [json getBool:@"multiline"]; 205 | 206 | BOOL autoCorr = NO; 207 | BOOL password = NO; 208 | UIKeyboardType keyType = UIKeyboardTypeDefault; 209 | 210 | if ([contentType isEqualToString:@"Autocorrected"]) 211 | { 212 | autoCorr = YES; 213 | } 214 | else if ([contentType isEqualToString:@"IntegerNumber"]) 215 | { 216 | keyType = UIKeyboardTypeNumberPad; 217 | } 218 | else if ([contentType isEqualToString:@"DecimalNumber"]) 219 | { 220 | keyType = UIKeyboardTypeDecimalPad; 221 | } 222 | else if ([contentType isEqualToString:@"Alphanumeric"]) 223 | { 224 | keyType = UIKeyboardTypeAlphabet; 225 | } 226 | else if ([contentType isEqualToString:@"Name"]) 227 | { 228 | keyType = UIKeyboardTypeNamePhonePad; 229 | } 230 | else if ([contentType isEqualToString:@"EmailAddress"]) 231 | { 232 | keyType = UIKeyboardTypeEmailAddress; 233 | } 234 | else if ([contentType isEqualToString:@"Password"]) 235 | { 236 | password = YES; 237 | } 238 | else if ([contentType isEqualToString:@"Pin"]) 239 | { 240 | keyType = UIKeyboardTypePhonePad; 241 | } 242 | 243 | UIControlContentHorizontalAlignment halign = UIControlContentHorizontalAlignmentLeft; 244 | UIControlContentVerticalAlignment valign = UIControlContentVerticalAlignmentCenter; 245 | 246 | if ([alignment isEqualToString:@"UpperLeft"]) 247 | { 248 | valign = UIControlContentVerticalAlignmentTop; 249 | halign = UIControlContentHorizontalAlignmentLeft; 250 | } 251 | else if ([alignment isEqualToString:@"UpperCenter"]) 252 | { 253 | valign = UIControlContentVerticalAlignmentTop; 254 | halign = UIControlContentHorizontalAlignmentCenter; 255 | } 256 | else if ([alignment isEqualToString:@"UpperRight"]) 257 | { 258 | valign = UIControlContentVerticalAlignmentTop; 259 | halign = UIControlContentHorizontalAlignmentRight; 260 | } 261 | else if ([alignment isEqualToString:@"MiddleLeft"]) 262 | { 263 | valign = UIControlContentVerticalAlignmentCenter; 264 | halign = UIControlContentHorizontalAlignmentLeft; 265 | } 266 | else if ([alignment isEqualToString:@"MiddleCenter"]) 267 | { 268 | valign = UIControlContentVerticalAlignmentCenter; 269 | halign = UIControlContentHorizontalAlignmentCenter; 270 | } 271 | else if ([alignment isEqualToString:@"MiddleRight"]) 272 | { 273 | valign = UIControlContentVerticalAlignmentCenter; 274 | halign = UIControlContentHorizontalAlignmentRight; 275 | } 276 | else if ([alignment isEqualToString:@"LowerLeft"]) 277 | { 278 | valign = UIControlContentVerticalAlignmentBottom; 279 | halign = UIControlContentHorizontalAlignmentLeft; 280 | } 281 | else if ([alignment isEqualToString:@"LowerCenter"]) 282 | { 283 | valign = UIControlContentVerticalAlignmentBottom; 284 | halign = UIControlContentHorizontalAlignmentCenter; 285 | } 286 | else if ([alignment isEqualToString:@"LowerRight"]) 287 | { 288 | valign = UIControlContentVerticalAlignmentBottom; 289 | halign = UIControlContentHorizontalAlignmentRight; 290 | } 291 | 292 | fontSize = fontSize / DEF_PixelPerPoint; 293 | 294 | if (withDoneButton) 295 | { 296 | keyboardDoneButtonView = [[UIToolbar alloc] init]; 297 | [keyboardDoneButtonView sizeToFit]; 298 | doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self 299 | action:@selector(doneClicked:)]; 300 | 301 | UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 302 | [keyboardDoneButtonView setItems:[NSArray arrayWithObjects:flexibleSpace, flexibleSpace,doneButton, nil]]; 303 | } 304 | else 305 | { 306 | keyboardDoneButtonView = nil; 307 | } 308 | 309 | if (multiline) 310 | { 311 | PlaceholderTextView* textView = [[PlaceholderTextView alloc] initWithFrame:CGRectMake(x, y, width, height)]; 312 | textView.keyboardType = keyType; 313 | [textView setFont:[UIFont fontWithName:font size:fontSize]]; 314 | textView.scrollEnabled = TRUE; 315 | 316 | textView.delegate = self; 317 | textView.tag = 0; 318 | textView.text = @""; 319 | 320 | textView.textColor = [UIColor colorWithRed:textColor_r green:textColor_g blue:textColor_b alpha:textColor_a]; 321 | textView.backgroundColor =[UIColor colorWithRed:backColor_r green:backColor_g blue:backColor_b alpha:backColor_a]; 322 | textView.returnKeyType = UIReturnKeyDefault; 323 | textView.autocorrectionType = autoCorr ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo ; 324 | textView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); 325 | textView.placeholder = placeholder; 326 | textView.delegate = self; 327 | 328 | [textView setSecureTextEntry:password]; 329 | if (keyboardDoneButtonView != nil) textView.inputAccessoryView = keyboardDoneButtonView; 330 | 331 | 332 | /// Todo 333 | /// UITextView Alignment is not implemented 334 | 335 | editView = textView; 336 | } 337 | else 338 | { 339 | UITextField* textField = [[UITextField alloc] initWithFrame:CGRectMake(x, y, width, height)]; 340 | textField.keyboardType = keyType; 341 | [textField setFont:[UIFont fontWithName:font size:fontSize]]; 342 | textField.delegate = self; 343 | textField.tag = 0; 344 | textField.text = @""; 345 | textField.textColor = [UIColor colorWithRed:textColor_r green:textColor_g blue:textColor_b alpha:textColor_a]; 346 | textField.backgroundColor =[UIColor colorWithRed:backColor_r green:backColor_g blue:backColor_b alpha:backColor_a]; 347 | textField.returnKeyType = UIReturnKeyDefault; 348 | textField.autocorrectionType = autoCorr ? UITextAutocorrectionTypeYes : UITextAutocorrectionTypeNo; 349 | textField.contentVerticalAlignment = valign; 350 | textField.contentHorizontalAlignment = halign; 351 | textField.placeholder = placeholder; 352 | textField.delegate = self; 353 | 354 | [textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; 355 | [textField setSecureTextEntry:password]; 356 | if (keyboardDoneButtonView != nil) textField.inputAccessoryView = keyboardDoneButtonView; 357 | 358 | editView = textField; 359 | } 360 | [viewPlugin addSubview:editView]; 361 | } 362 | 363 | -(void) setText:(JsonObject*)json 364 | { 365 | NSString* newText = [json getString:@"text"]; 366 | if([editView isKindOfClass:[UITextField class]]) { 367 | [((UITextField*)editView) setText:newText]; 368 | } else if([editView isKindOfClass:[UITextView class]]){ 369 | [((UITextView*)editView) setText:newText]; 370 | } 371 | } 372 | 373 | -(IBAction) doneClicked:(id)sender 374 | { 375 | [self showKeyboard:false]; 376 | } 377 | 378 | -(int) getLineCount 379 | { 380 | if([editView isKindOfClass:[UITextField class]]) { 381 | return 1; 382 | } else if([editView isKindOfClass:[UITextView class]]){ 383 | UITextView* tv = ((UITextView*)editView); 384 | int lineCount = (int) tv.contentSize.height / tv.font.lineHeight; 385 | return (lineCount); 386 | } 387 | return 0; 388 | } 389 | 390 | 391 | -(void) remove 392 | { 393 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 394 | [editView resignFirstResponder]; 395 | [editView removeFromSuperview]; 396 | if (keyboardDoneButtonView != nil) 397 | { 398 | doneButton = nil; 399 | keyboardDoneButtonView = nil; 400 | } 401 | } 402 | 403 | -(void) setFocus:(BOOL) isFocus 404 | { 405 | if (isFocus) 406 | { 407 | [editView becomeFirstResponder]; 408 | } 409 | else 410 | { 411 | [editView resignFirstResponder]; 412 | } 413 | } 414 | 415 | -(NSString*) getText 416 | { 417 | if([editView isKindOfClass:[UITextField class]]) { 418 | return ((UITextField*)editView).text; 419 | } else if([editView isKindOfClass:[UITextView class]]){ 420 | return ((UITextView*)editView).text; 421 | } 422 | return @""; 423 | } 424 | 425 | -(bool) isFocused 426 | { 427 | return editView.isFirstResponder; 428 | } 429 | 430 | -(void) showKeyboard:(bool)isShow 431 | { 432 | [viewController.view endEditing:(isShow ? YES : NO)]; 433 | } 434 | -(void) setVisible:(bool)isVisible 435 | { 436 | editView.hidden = (isVisible ? NO : YES); 437 | } 438 | 439 | -(void) onTextChange:(NSString*) text 440 | { 441 | JsonObject* jsonToUnity = [[JsonObject alloc] init]; 442 | 443 | [jsonToUnity setString:@"msg" value:MSG_TEXT_CHANGE]; 444 | [jsonToUnity setString:@"text" value:text]; 445 | [self sendJsonToUnity:jsonToUnity]; 446 | } 447 | 448 | -(void) onTextEditEnd:(NSString*) text 449 | { 450 | JsonObject* jsonToUnity = [[JsonObject alloc] init]; 451 | 452 | [jsonToUnity setString:@"msg" value:MSG_TEXT_END_EDIT]; 453 | [jsonToUnity setString:@"text" value:text]; 454 | [self sendJsonToUnity:jsonToUnity]; 455 | } 456 | 457 | -(void) textViewDidChange:(UITextView *)textView 458 | { 459 | [self onTextChange:textView.text]; 460 | } 461 | 462 | -(void) textViewDidEndEditing:(UITextView *)textView 463 | { 464 | [self onTextEditEnd:textView.text]; 465 | } 466 | 467 | -(void) textFieldDidChange :(UITextField *)theTextField{ 468 | [self onTextChange:theTextField.text]; 469 | } 470 | 471 | -(void) textFieldDidEndEditing:(UITextField *)textField 472 | { 473 | [self onTextEditEnd:textField.text]; 474 | } 475 | 476 | -(void) keyboardWillShow:(NSNotification *)notification 477 | { 478 | if (![editView isFirstResponder]) return; 479 | 480 | NSDictionary* keyboardInfo = [notification userInfo]; 481 | NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey]; 482 | rectKeyboardFrame = [keyboardFrameBegin CGRectValue]; 483 | 484 | } 485 | 486 | -(void) keyboardWillHide:(NSNotification*)notification 487 | { 488 | if (![editView isFirstResponder]) return; 489 | 490 | } 491 | 492 | -(float) getKeyboardheight 493 | { 494 | float height = rectKeyboardFrame.size.height / viewController.view.bounds.size.height; 495 | return height; 496 | } 497 | 498 | 499 | @end 500 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/iOS/JsonObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // JsonObject.h 3 | // stockissue 4 | // 5 | // Created by KYUNGMIN BANG on 12/8/14. 6 | // Copyright (c) 2014 Nureka Inc. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JsonObject : NSObject 12 | 13 | @property (nonatomic, strong) NSMutableDictionary* dict; 14 | 15 | -(id)initWithJsonData:(NSData*) json; 16 | -(id)initWithCmd:(NSString*) cmd; 17 | -(id)initWithDictionary:(NSMutableDictionary*) _dict; 18 | -(NSData*)serialize; 19 | 20 | -(void) setInt:(NSString*) key value:(int)value; 21 | -(void) setFloat:(NSString*) key value:(float)value; 22 | -(void) setBool:(NSString*) key value:(BOOL)value; 23 | -(void) setString:(NSString*) key value:(NSString*)value; 24 | -(void) setArray:(NSString*) key value:(NSArray*) value; 25 | -(void) setJsonObject:(NSString*) key value:(JsonObject*) value; 26 | 27 | -(int) getInt:(NSString*) key; 28 | -(float) getFloat:(NSString*) key; 29 | -(BOOL) getBool:(NSString*) key; 30 | -(NSString*) getString:(NSString*) key; 31 | -(NSArray*) getJsonArray:(NSString*) key; 32 | -(NSArray*) getDictArray:(NSString*) key; 33 | -(JsonObject*) getJsonObject:(NSString*) key; 34 | 35 | @end 36 | 37 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/iOS/JsonObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // JsonObject.m 3 | // stockissue 4 | // 5 | // Created by KYUNGMIN BANG on 12/8/14. 6 | // Copyright (c) 2014 Nureka Inc. All rights reserved. 7 | // 8 | 9 | #import "JsonObject.h" 10 | 11 | 12 | @implementation JsonObject 13 | @synthesize dict; 14 | 15 | -(void) dealloc 16 | { 17 | dict = nil; 18 | } 19 | 20 | -(id)init 21 | { 22 | self = [super init]; 23 | if (self) 24 | { 25 | dict = [[NSMutableDictionary alloc] init]; 26 | 27 | } 28 | return self; 29 | } 30 | 31 | -(id)initWithDictionary:(NSMutableDictionary*) _dict 32 | { 33 | self = [super init]; 34 | if (self) 35 | { 36 | dict = _dict; 37 | 38 | } 39 | return self; 40 | } 41 | 42 | -(id)initWithJsonData:(NSData*) json 43 | { 44 | self = [super init]; 45 | if (self) 46 | { 47 | NSError *error; 48 | 49 | dict = [NSJSONSerialization 50 | JSONObjectWithData:json 51 | options:NSJSONReadingMutableContainers 52 | error:&error]; 53 | if (dict == nil) 54 | { 55 | NSLog(@"Json parse error %@",[error description]); 56 | } 57 | } 58 | return self; 59 | } 60 | -(id)initWithCmd:(NSString*) cmd 61 | { 62 | self = [self init]; 63 | if (dict) 64 | { 65 | dict[@"cmd"] = cmd; 66 | } 67 | return self; 68 | } 69 | 70 | -(NSData*)serialize 71 | { 72 | NSError *error; 73 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict 74 | options:0 75 | error:&error]; 76 | return jsonData; 77 | } 78 | 79 | -(void) setInt:(NSString*) key value:(int)value 80 | { 81 | dict[key] = [NSNumber numberWithInt:value]; 82 | } 83 | -(void) setFloat:(NSString*) key value:(float)value 84 | { 85 | dict[key] = [NSNumber numberWithFloat:value]; 86 | } 87 | -(void) setBool:(NSString*) key value:(BOOL)value 88 | { 89 | dict[key] = [NSNumber numberWithBool:value]; 90 | } 91 | -(void) setString:(NSString*) key value:(NSString*)value 92 | { 93 | dict[key] = value; 94 | } 95 | -(void) setArray:(NSString*) key value:(NSArray*) value 96 | { 97 | dict[key] = value; 98 | } 99 | -(void) setJsonObject:(NSString*) key value:(JsonObject*) value 100 | { 101 | dict[key] = value.dict; 102 | } 103 | 104 | -(int) getInt:(NSString*) key 105 | { 106 | id obj = [dict objectForKey:key]; 107 | if (obj == nil || obj == (id)[NSNull null]) return 0; 108 | return [obj intValue]; 109 | } 110 | -(float) getFloat:(NSString*) key 111 | { 112 | id obj = [dict objectForKey:key]; 113 | if (obj == nil || obj == (id)[NSNull null]) return 0.0f; 114 | return [obj floatValue]; 115 | } 116 | -(BOOL) getBool:(NSString*) key 117 | { 118 | id obj = [dict objectForKey:key]; 119 | if (obj == nil || obj == (id)[NSNull null]) return NO; 120 | return [obj boolValue]; 121 | } 122 | -(NSString*) getString:(NSString*) key 123 | { 124 | id obj = [dict objectForKey:key]; 125 | if (!obj || obj == (id)[NSNull null]) return @""; 126 | return (NSString*) obj; 127 | } 128 | -(NSArray*) getDictArray:(NSString*) key 129 | { 130 | id obj = [dict objectForKey:key]; 131 | if (obj == nil || obj == (id)[NSNull null]) return [[NSArray alloc] init]; 132 | return (NSArray*) obj; 133 | } 134 | -(NSArray*) getJsonArray:(NSString*) key 135 | { 136 | id obj = [dict objectForKey:key]; 137 | NSMutableArray* arr = [[NSMutableArray alloc] init]; 138 | if (obj == nil || obj == (id)[NSNull null]) return arr; 139 | for (id arrObj in (NSMutableArray*) obj) { 140 | JsonObject* newObj = [[JsonObject alloc] initWithDictionary:(NSMutableDictionary*) arrObj]; 141 | [arr addObject:newObj]; 142 | } 143 | return (NSArray*) arr; 144 | } 145 | -(JsonObject*) getJsonObject:(NSString*) key 146 | { 147 | id obj = [dict objectForKey:key]; 148 | JsonObject* newObj = [[JsonObject alloc] init]; 149 | if (obj == nil || obj == (id)[NSNull null]) return newObj; 150 | newObj.dict = (NSMutableDictionary*) obj; 151 | return newObj; 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/iOS/PlaceholderTextView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface PlaceholderTextView : UITextView 5 | { 6 | NSObject* _editBox; 7 | } 8 | 9 | @property(nonatomic, strong) NSString *placeholder; 10 | 11 | @property (nonatomic, strong) UIColor *realTextColor UI_APPEARANCE_SELECTOR; 12 | @property (nonatomic, strong) UIColor *placeholderColor UI_APPEARANCE_SELECTOR; 13 | 14 | -(void) SetEditbox:(NSObject*) box; 15 | 16 | @end -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/iOS/PlaceholderTextView.m: -------------------------------------------------------------------------------- 1 | #import "PlaceholderTextView.h" 2 | #import "EditBox_iOS.h" 3 | 4 | @interface PlaceholderTextView () 5 | 6 | @property (unsafe_unretained, nonatomic, readonly) NSString* realText; 7 | 8 | - (void) beginEditing:(NSNotification*) notification; 9 | - (void) endEditing:(NSNotification*) notification; 10 | 11 | @end 12 | 13 | @implementation PlaceholderTextView 14 | 15 | @synthesize realTextColor; 16 | @synthesize placeholder; 17 | @synthesize placeholderColor; 18 | 19 | #pragma mark - 20 | #pragma mark Initialisation 21 | 22 | - (id) initWithFrame:(CGRect)frame { 23 | if ((self = [super initWithFrame:frame])) { 24 | [self awakeFromNib]; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)awakeFromNib { 30 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(beginEditing:) name:UITextViewTextDidBeginEditingNotification object:self]; 31 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(endEditing:) name:UITextViewTextDidEndEditingNotification object:self]; 32 | 33 | self.realTextColor = self.textColor; 34 | self.placeholderColor = [UIColor lightGrayColor]; 35 | } 36 | 37 | #pragma mark - 38 | #pragma mark Setter/Getters 39 | 40 | - (void) setPlaceholder:(NSString *)aPlaceholder { 41 | if ([self.realText isEqualToString:placeholder] && ![self isFirstResponder]) { 42 | self.text = aPlaceholder; 43 | } 44 | if (aPlaceholder != placeholder) { 45 | placeholder = aPlaceholder; 46 | } 47 | 48 | 49 | [self endEditing:nil]; 50 | } 51 | 52 | - (void)setPlaceholderColor:(UIColor *)aPlaceholderColor { 53 | placeholderColor = aPlaceholderColor; 54 | 55 | if ([super.text isEqualToString:self.placeholder]) { 56 | self.textColor = self.placeholderColor; 57 | } 58 | } 59 | 60 | - (NSString *) text { 61 | NSString* text = [super text]; 62 | if ([text isEqualToString:self.placeholder]) return @""; 63 | return text; 64 | } 65 | 66 | - (void) setText:(NSString *)text { 67 | if (([text isEqualToString:@""] || text == nil) && ![self isFirstResponder]) { 68 | super.text = self.placeholder; 69 | } 70 | else { 71 | super.text = text; 72 | } 73 | 74 | if ([text isEqualToString:self.placeholder] || text == nil) { 75 | self.textColor = self.placeholderColor; 76 | } 77 | else { 78 | self.textColor = self.realTextColor; 79 | } 80 | } 81 | 82 | - (NSString *) realText { 83 | return [super text]; 84 | } 85 | 86 | - (void) beginEditing:(NSNotification*) notification { 87 | if ([self.realText isEqualToString:self.placeholder]) { 88 | super.text = nil; 89 | self.textColor = self.realTextColor; 90 | } 91 | } 92 | 93 | - (void) endEditing:(NSNotification*) notification { 94 | if ([self.realText isEqualToString:@""] || self.realText == nil) { 95 | super.text = self.placeholder; 96 | self.textColor = self.placeholderColor; 97 | } 98 | } 99 | 100 | - (void) setTextColor:(UIColor *)textColor { 101 | if ([self.realText isEqualToString:self.placeholder]) { 102 | if ([textColor isEqual:self.placeholderColor]){ 103 | [super setTextColor:textColor]; 104 | } else { 105 | self.realTextColor = textColor; 106 | } 107 | } 108 | else { 109 | self.realTextColor = textColor; 110 | [super setTextColor:textColor]; 111 | } 112 | } 113 | 114 | -(void) SetEditbox:(NSObject*)box 115 | { 116 | _editBox = box; 117 | 118 | } 119 | 120 | #pragma mark - 121 | #pragma mark Dealloc 122 | 123 | - (void)dealloc { 124 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 125 | 126 | } 127 | 128 | @end -------------------------------------------------------------------------------- /release/NativeEditPlugin/Plugins/iOS/PluginMsgInterface.mm: -------------------------------------------------------------------------------- 1 | // 2 | // PluginMsgHandler.m 3 | // Unity-iPhone 4 | // 5 | // Created by KYUNGMIN BANG on 2/24/15. 6 | // 7 | // 8 | 9 | #import "EditBox_iOS.h" 10 | 11 | UIViewController* UnityGetGLViewController(); 12 | 13 | char* gCopyString(const char* string) { 14 | if(string == NULL) { 15 | return NULL; 16 | } 17 | char* ret = (char*) malloc(strlen(string) + 1); // memory will be auto-freed by unity 18 | strcpy(ret, string); 19 | return ret; 20 | } 21 | 22 | extern "C" { 23 | 24 | /* typedef void* MonoDomain; 25 | typedef void* MonoAssembly; 26 | typedef void* MonoImage; 27 | typedef void* MonoClass; 28 | typedef void* MonoObject; 29 | typedef void* MonoMethodDesc; 30 | typedef void* MonoMethod; 31 | typedef void* gpointer; 32 | typedef int gboolean; 33 | 34 | MonoDomain *mono_domain_get(); 35 | MonoAssembly *mono_domain_assembly_open(MonoDomain *domain, const char *assemblyName); 36 | MonoImage *mono_assembly_get_image(MonoAssembly *assembly); 37 | MonoMethodDesc *mono_method_desc_new(const char *methodString, gboolean useNamespace); 38 | MonoMethodDesc *mono_method_desc_free(MonoMethodDesc *desc); 39 | MonoMethod *mono_method_desc_search_in_image(MonoMethodDesc *methodDesc, MonoImage *image); 40 | MonoObject *mono_runtime_invoke(MonoMethod *method, void *obj, void **params, MonoObject **exc); 41 | gpointer mono_object_unbox(MonoObject *obj); 42 | 43 | void initializUnityPluginHandler() 44 | { 45 | MonoDomain *domain = mono_domain_get(); 46 | NSString *assemblyPath = [[[NSBundle mainBundle] bundlePath] 47 | stringByAppendingPathComponent:@"Data/Managed/Assembly-CSharp.dll"]; 48 | MonoAssembly *assembly = mono_domain_assembly_open(domain, assemblyPath.UTF8String); 49 | MonoImage *image = mono_assembly_get_image(assembly); 50 | 51 | MonoMethodDesc *desc = mono_method_desc_new("PluginMsgHandler:InitializeHandlerByNative()", FALSE); 52 | MonoMethod *method = mono_method_desc_search_in_image(desc, image); 53 | mono_runtime_invoke(method, NULL, NULL, NULL); 54 | mono_method_desc_free(desc); 55 | } */ 56 | 57 | void _iOS_InitPluginMsgHandler(const char* unityName) 58 | { 59 | [EditBox initializeEditBox:UnityGetGLViewController() unityName:unityName]; 60 | NSLog(@"_iOS_InitPluginMsgHandler called"); 61 | } 62 | 63 | char* _iOS_SendUnityMsgToPlugin(int nSenderId, const char* jsonMsgApp) 64 | { 65 | NSString* strJson = [NSString stringWithUTF8String:jsonMsgApp]; 66 | JsonObject* jsonMsg = [[JsonObject alloc] initWithJsonData:[strJson dataUsingEncoding:NSUTF8StringEncoding]]; 67 | JsonObject* jsonRet = [EditBox processRecvJsonMsg:nSenderId msg:jsonMsg]; 68 | 69 | NSString* strRet = [[NSString alloc] initWithData:[jsonRet serialize] encoding:NSUTF8StringEncoding]; 70 | return gCopyString([strRet UTF8String]); 71 | } 72 | void _iOS_ClosePluginMsgHandler() 73 | { 74 | [EditBox finalizeEditBox]; 75 | } 76 | } -------------------------------------------------------------------------------- /release/NativeEditPlugin/README.md: -------------------------------------------------------------------------------- 1 | ## UnityNativeEdit 2 | Unity Native Input Plugin for both iOS and Android (Unity UI InputField compatible). 3 | This means you don't need a separate 'Unity' Input box and you can use all native text functions such as `Select`, `Copy` and `Paste` 4 | 5 | ## Usage 6 | 1. Simply copy the files in `release/Assets` into your existing unity project asset folder. 7 | 2. Make empty Gameobject and attach ```PluginMsgHandler``` to your new GameObject 8 | 3. Attach ```NativeEditBox``` script to your UnityUI ```InputField```object. 9 | 4. Build and run on your android or ios device! 10 | 11 | 12 | ## Etc 13 | 1. NativeEditBox will work with delegate defined in your Unity UI InputField, `On Value Change` and `End Edit` 14 | 2. It's open source and free to use/redistribute! 15 | 3. Please refer to `demo` Unity project. 16 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/demo/demo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.EventSystems; 3 | using UnityEngine.UI; 4 | using System.Collections; 5 | 6 | public class demo : MonoBehaviour { 7 | 8 | public NativeEditBox testNativeEdit; 9 | public Canvas mainCanvas; 10 | private RectTransform rectTrans; 11 | 12 | // Use this for initialization 13 | void Start () { 14 | rectTrans = testNativeEdit.transform.FindChild("Text").GetComponent(); 15 | 16 | GameObject tempTest = GameObject.Instantiate(testNativeEdit.gameObject); 17 | tempTest.transform.SetParent(mainCanvas.transform, false); 18 | tempTest.transform.position += new Vector3(0.0f, -250.0f, 0.0f); 19 | 20 | NativeEditBox tempNB = tempTest.GetComponent();; 21 | tempNB.SetTextNative("fdfdsfsd"); 22 | } 23 | 24 | // Update is called once per frame 25 | void Update () { 26 | 27 | 28 | } 29 | 30 | private string GetCurObjName() 31 | { 32 | string strObjName = ""; 33 | GameObject objSel = EventSystem.current.currentSelectedGameObject; 34 | if (objSel != null && objSel.transform.parent != null) 35 | { 36 | strObjName = objSel.transform.parent.name; 37 | } 38 | 39 | return strObjName; 40 | } 41 | 42 | public void OnEditValugChanged(string str) 43 | { 44 | Text txt = this.GetComponent(); 45 | txt.text = string.Format("[{0}] val changed {1}", this.GetCurObjName(), str); 46 | } 47 | 48 | public void OnEditEnded(string str) 49 | { 50 | Text txt = this.GetComponent(); 51 | txt.text = string.Format("[{0}] edit ended {1}", this.GetCurObjName(), str); 52 | } 53 | 54 | private bool bTempFocus = false; 55 | private bool bTempVisible = false; 56 | public void OnButton1() 57 | { 58 | bTempFocus = !bTempFocus; 59 | Debug.Log("OnButton1 clicked"); 60 | testNativeEdit.SetFocusNative(bTempFocus); 61 | } 62 | 63 | public void OnButton2() 64 | { 65 | Debug.Log("OnButton2 clicked"); 66 | bTempVisible = !bTempVisible; 67 | testNativeEdit.SetVisible(bTempVisible); 68 | } 69 | 70 | public void OnButton3() 71 | { 72 | rectTrans.sizeDelta = new Vector2(-20.0f, -5.0f); 73 | testNativeEdit.SetRectNative(rectTrans); 74 | Debug.Log("OnButton3 clicked"); 75 | } 76 | 77 | 78 | public void OnButton4() 79 | { 80 | //rectTrans.sizeDelta = new Vector2(20.0f, 5.0f); 81 | //testNativeEdit.SetRectNative(rectTrans); 82 | 83 | Text txt = this.GetComponent(); 84 | string sCurText = testNativeEdit.GetTextNative(); 85 | txt.text = string.Format("[{0}] GetText {1}", this.GetCurObjName(), sCurText); 86 | Debug.Log("OnButton4 clicked"); 87 | } 88 | 89 | public void OnButton5() 90 | { 91 | Debug.Log("OnButton5 clicked"); 92 | testNativeEdit.SetTextNative("TestText Set!!@#@5"); 93 | } 94 | 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/demo/demo.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/release/NativeEditPlugin/demo/demo.unity -------------------------------------------------------------------------------- /release/NativeEditPlugin/scripts/JsonObject.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System; 6 | 7 | /* 8 | * Copyright (c) 2015 Kyungmin Bang 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining 11 | * a copy of this software and associated documentation files (the 12 | * "Software"), to deal in the Software without restriction, including 13 | * without limitation the rights to use, copy, modify, merge, publish, 14 | * distribute, sublicense, and/or sell copies of the Software, and to 15 | * permit persons to whom the Software is furnished to do so, subject to 16 | * the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be 19 | * included in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | 30 | 31 | /// 32 | /// JsonObject provide safe and type-compatible wrapper to access Json Element 33 | /// Safe means, even if a certain Json doesn't contain 'key', it doesn't crash. 34 | /// 35 | public class JsonObject : UnityEngine.Object { 36 | /// 37 | /// Supported object type : double, bool, string, List, Array! 38 | /// 39 | public Dictionary m_dict; 40 | 41 | public JsonObject() 42 | { 43 | m_dict = new Dictionary(); 44 | } 45 | 46 | public JsonObject(string strJson) 47 | { 48 | m_dict = MiniJSON_Min.Json.Deserialize(strJson) as Dictionary; 49 | } 50 | 51 | public JsonObject(Dictionary dict) 52 | { 53 | m_dict = dict; 54 | } 55 | 56 | public System.Object this[string key] 57 | { 58 | get { return m_dict[key]; } 59 | set { m_dict[key] = value; } 60 | } 61 | 62 | public string getCmd() { return (string) m_dict["cmd"]; } 63 | 64 | public string Serialize() 65 | { 66 | string strData = MiniJSON_Min.Json.Serialize(m_dict); 67 | return strData; 68 | } 69 | 70 | //// Deserialize helper 71 | 72 | private object GetDictValue(string key) 73 | { 74 | System.Object obj; 75 | if (m_dict.TryGetValue(key, out obj)) 76 | { 77 | return ((obj != null) ? obj : ""); 78 | } 79 | return ""; 80 | } 81 | 82 | public bool keyExist(string key) 83 | { 84 | System.Object obj; 85 | if (m_dict.TryGetValue(key, out obj)) 86 | { 87 | return true; 88 | } 89 | return false; 90 | } 91 | 92 | public Dictionary GetJsonDict(string key) 93 | { 94 | System.Object obj; 95 | if (m_dict.TryGetValue(key, out obj)) return (Dictionary) obj; 96 | return new Dictionary(); 97 | } 98 | 99 | public JsonObject GetJsonObject(string key) 100 | { 101 | Dictionary dict = this.GetJsonDict(key); 102 | return new JsonObject(dict); 103 | } 104 | 105 | public bool GetBool(string key) 106 | { 107 | bool val; 108 | if (bool.TryParse(this.GetDictValue(key).ToString(), out val)) return val; 109 | return false; 110 | } 111 | 112 | public int GetInt(string key) 113 | { 114 | int val; 115 | if (int.TryParse(this.GetDictValue(key).ToString(), out val)) return val; 116 | return 0; 117 | } 118 | 119 | public float GetFloat(string key) 120 | { 121 | float val; 122 | if (float.TryParse(this.GetDictValue(key).ToString(), out val)) return val; 123 | return 0.0f; 124 | } 125 | 126 | public string GetString(string key) 127 | { 128 | return (string) this.GetDictValue(key).ToString(); 129 | } 130 | 131 | public object GetEnum(System.Type type, string key) 132 | { 133 | string obj = (string) this.GetDictValue(key); 134 | if (obj.Length > 0) 135 | { 136 | return System.Enum.Parse(type, obj); 137 | } 138 | return 0; 139 | } 140 | 141 | public List GetListJsonObject(string key) 142 | { 143 | System.Object obj; 144 | List retList = new List(); 145 | if (m_dict.TryGetValue(key, out obj)) 146 | { 147 | foreach(object elem in (List) obj) 148 | { 149 | retList.Add(new JsonObject( (Dictionary) elem)); 150 | } 151 | } 152 | return retList; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/scripts/NativeEditBox.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Kyungmin Bang 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | 25 | /* 26 | * NativeEditBox script should be attached to Unity UI InputField object 27 | * 28 | * Limitation 29 | * 30 | * 1. Screen auto rotation is not supported. 31 | */ 32 | 33 | 34 | using UnityEngine; 35 | using System.Collections; 36 | using UnityEngine.UI; 37 | 38 | public class NativeEditBox : PluginMsgReceiver { 39 | private struct EditBoxConfig 40 | { 41 | public bool multiline; 42 | public Color textColor; 43 | public Color backColor; 44 | public string contentType; 45 | public string font; 46 | public float fontSize; 47 | public string align; 48 | public string placeHolder; 49 | } 50 | 51 | public bool withDoneButton = true; 52 | 53 | private bool bNativeEditCreated = false; 54 | 55 | private InputField objUnityInput; 56 | private Text objUnityText; 57 | 58 | private static string MSG_CREATE = "CreateEdit"; 59 | private static string MSG_REMOVE = "RemoveEdit"; 60 | private static string MSG_SET_TEXT = "SetText"; 61 | private static string MSG_GET_TEXT = "GetText"; 62 | private static string MSG_SET_RECT = "SetRect"; 63 | private static string MSG_SET_FOCUS = "SetFocus"; 64 | private static string MSG_SET_VISIBLE = "SetVisible"; 65 | private static string MSG_TEXT_CHANGE = "TextChange"; 66 | private static string MSG_TEXT_END_EDIT = "TextEndEdit"; 67 | private static string MSG_ANDROID_KEY_DOWN = "AndroidKeyDown"; // to fix bug Some keys 'back' & 'enter' are eaten by unity and never arrive at plugin 68 | 69 | public static Rect GetScreenRectFromRectTransform(RectTransform rectTransform) 70 | { 71 | Vector3[] corners = new Vector3[4]; 72 | 73 | rectTransform.GetWorldCorners(corners); 74 | 75 | float xMin = float.PositiveInfinity; 76 | float xMax = float.NegativeInfinity; 77 | float yMin = float.PositiveInfinity; 78 | float yMax = float.NegativeInfinity; 79 | 80 | for (int i = 0; i < 4; i++) 81 | { 82 | // For Canvas mode Screen Space - Overlay there is no Camera; best solution I've found 83 | // is to use RectTransformUtility.WorldToScreenPoint) with a null camera. 84 | Vector3 screenCoord = RectTransformUtility.WorldToScreenPoint(null, corners[i]); 85 | 86 | if (screenCoord.x < xMin) 87 | xMin = screenCoord.x; 88 | if (screenCoord.x > xMax) 89 | xMax = screenCoord.x; 90 | if (screenCoord.y < yMin) 91 | yMin = screenCoord.y; 92 | if (screenCoord.y > yMax) 93 | yMax = screenCoord.y; 94 | } 95 | Rect result = new Rect(xMin, Screen.height - yMax, xMax - xMin, yMax - yMin); 96 | return result; 97 | } 98 | 99 | private EditBoxConfig mConfig; 100 | 101 | void Awake() 102 | { 103 | // base.Awake(); 104 | } 105 | 106 | 107 | protected new void OnDestroy() 108 | { 109 | base.OnDestroy(); 110 | } 111 | 112 | void OnEnable() 113 | { 114 | if (bNativeEditCreated) this.SetVisible(true); 115 | } 116 | 117 | void OnDisable() 118 | { 119 | if (bNativeEditCreated) this.SetVisible(false); 120 | } 121 | 122 | // Use this for initialization 123 | new void Start () { 124 | base.Start(); 125 | 126 | bNativeEditCreated = false; 127 | this.PrepareNativeEdit(); 128 | 129 | #if (UNITY_IPHONE || UNITY_ANDROID) &&!UNITY_EDITOR 130 | this.CreateNativeEdit(); 131 | this.SetTextNative(this.objUnityText.text); 132 | 133 | objUnityInput.placeholder.enabled = false; 134 | objUnityText.enabled = false; 135 | objUnityInput.enabled = false; 136 | #endif 137 | } 138 | 139 | // Update is called once per frame 140 | void Update () { 141 | this.UpdateForceKeyeventForAndroid(); 142 | } 143 | 144 | private void PrepareNativeEdit() 145 | { 146 | objUnityInput = this.GetComponent(); 147 | if (objUnityInput == null) 148 | { 149 | Debug.LogErrorFormat("No InputField found {0} NativeEditBox Error", this.name); 150 | throw new MissingComponentException(); 151 | } 152 | 153 | Graphic placeHolder = objUnityInput.placeholder; 154 | objUnityText = objUnityInput.textComponent; 155 | 156 | mConfig.placeHolder = placeHolder.GetComponent().text; 157 | mConfig.font = objUnityText.font.fontNames.Length > 0 ? objUnityText.font.fontNames[0] : "Arial"; 158 | 159 | Rect rectScreen = GetScreenRectFromRectTransform(this.objUnityText.rectTransform); 160 | float fHeightRatio = rectScreen.height / objUnityText.rectTransform.rect.height; 161 | mConfig.fontSize = ((float) objUnityText.fontSize) * fHeightRatio; 162 | 163 | mConfig.textColor = objUnityText.color; 164 | mConfig.align = objUnityText.alignment.ToString(); 165 | mConfig.contentType = objUnityInput.contentType.ToString(); 166 | mConfig.backColor = new Color(1.0f, 1.0f, 1.0f, 0.0f); 167 | mConfig.multiline = (objUnityInput.lineType == InputField.LineType.SingleLine) ? false : true; 168 | } 169 | 170 | private void onTextChange(string newText) 171 | { 172 | this.objUnityInput.text = newText; 173 | if (this.objUnityInput.onValueChange != null) this.objUnityInput.onValueChange.Invoke(newText); 174 | } 175 | 176 | private void onTextEditEnd(string newText) 177 | { 178 | this.objUnityInput.text = newText; 179 | if (this.objUnityInput.onEndEdit != null) this.objUnityInput.onEndEdit.Invoke(newText); 180 | } 181 | 182 | public override void OnPluginMsgDirect(JsonObject jsonMsg) 183 | { 184 | string msg = jsonMsg.GetString("msg"); 185 | if (msg.Equals(MSG_TEXT_CHANGE)) 186 | { 187 | string text = jsonMsg.GetString("text"); 188 | this.onTextChange(text); 189 | } 190 | else if (msg.Equals(MSG_TEXT_END_EDIT)) 191 | { 192 | string text = jsonMsg.GetString("text"); 193 | this.onTextEditEnd(text); 194 | } 195 | } 196 | 197 | private bool CheckErrorJsonRet(JsonObject jsonRet) 198 | { 199 | bool bError = jsonRet.GetBool("bError"); 200 | string strError = jsonRet.GetString("strError"); 201 | if (bError) 202 | { 203 | PluginMsgHandler.getInst().FileLogError(string.Format("NativeEditbox error {0}", strError)); 204 | } 205 | return bError; 206 | } 207 | 208 | private void CreateNativeEdit() 209 | { 210 | Rect rectScreen = GetScreenRectFromRectTransform(this.objUnityText.rectTransform); 211 | 212 | JsonObject jsonMsg = new JsonObject(); 213 | 214 | jsonMsg["msg"] = MSG_CREATE; 215 | 216 | jsonMsg["x"] = rectScreen.x / Screen.width; 217 | jsonMsg["y"] = rectScreen.y / Screen.height; 218 | jsonMsg["width"] = rectScreen.width / Screen.width; 219 | jsonMsg["height"] = rectScreen.height / Screen.height; 220 | 221 | jsonMsg["textColor_r"] = mConfig.textColor.r; 222 | jsonMsg["textColor_g"] = mConfig.textColor.g; 223 | jsonMsg["textColor_b"] = mConfig.textColor.b; 224 | jsonMsg["textColor_a"] = mConfig.textColor.a; 225 | jsonMsg["backColor_r"] = mConfig.backColor.r; 226 | jsonMsg["backColor_g"] = mConfig.backColor.g; 227 | jsonMsg["backColor_b"] = mConfig.backColor.b; 228 | jsonMsg["backColor_a"] = mConfig.backColor.a; 229 | jsonMsg["font"] = mConfig.font; 230 | jsonMsg["fontSize"] = mConfig.fontSize; 231 | jsonMsg["contentType"] = mConfig.contentType; 232 | jsonMsg["align"] = mConfig.align; 233 | jsonMsg["withDoneButton"] = this.withDoneButton; 234 | jsonMsg["placeHolder"] = mConfig.placeHolder; 235 | jsonMsg["multiline"] = mConfig.multiline; 236 | 237 | JsonObject jsonRet = this.SendPluginMsg(jsonMsg); 238 | bNativeEditCreated = !this.CheckErrorJsonRet(jsonRet); 239 | } 240 | 241 | public void SetTextNative(string newText) 242 | { 243 | JsonObject jsonMsg = new JsonObject(); 244 | 245 | jsonMsg["msg"] = MSG_SET_TEXT; 246 | jsonMsg["text"] = newText; 247 | 248 | this.SendPluginMsg(jsonMsg); 249 | } 250 | 251 | public string GetTextNative() 252 | { 253 | JsonObject jsonMsg = new JsonObject(); 254 | 255 | jsonMsg["msg"] = MSG_GET_TEXT; 256 | JsonObject jsonRet = this.SendPluginMsg(jsonMsg); 257 | bool bError = this.CheckErrorJsonRet(jsonRet); 258 | 259 | if (bError) return ""; 260 | 261 | Debug.Log(string.Format("GetTextNative {0}", jsonRet.GetString("text"))); 262 | return jsonRet.GetString("text"); 263 | } 264 | 265 | private void RemoveNative() 266 | { 267 | JsonObject jsonMsg = new JsonObject(); 268 | 269 | jsonMsg["msg"] = MSG_REMOVE; 270 | this.SendPluginMsg(jsonMsg); 271 | } 272 | 273 | public void SetRectNative(RectTransform rectTrans) 274 | { 275 | Rect rectScreen = GetScreenRectFromRectTransform(rectTrans); 276 | 277 | JsonObject jsonMsg = new JsonObject(); 278 | 279 | jsonMsg["msg"] = MSG_SET_RECT; 280 | 281 | jsonMsg["x"] = rectScreen.x / Screen.width; 282 | jsonMsg["y"] = rectScreen.y / Screen.height; 283 | jsonMsg["width"] = rectScreen.width / Screen.width; 284 | jsonMsg["height"] = rectScreen.height / Screen.height; 285 | 286 | this.SendPluginMsg(jsonMsg); 287 | } 288 | 289 | public void SetFocusNative(bool bFocus) 290 | { 291 | JsonObject jsonMsg = new JsonObject(); 292 | 293 | jsonMsg["msg"] = MSG_SET_FOCUS; 294 | jsonMsg["isFocus"] = bFocus; 295 | 296 | this.SendPluginMsg(jsonMsg); 297 | } 298 | 299 | public void SetVisible(bool bVisible) 300 | { 301 | JsonObject jsonMsg = new JsonObject(); 302 | 303 | jsonMsg["msg"] = MSG_SET_VISIBLE; 304 | jsonMsg["isVisible"] = bVisible; 305 | 306 | this.SendPluginMsg(jsonMsg); 307 | } 308 | 309 | void ForceSendKeydown_Android(string key) 310 | { 311 | JsonObject jsonMsg = new JsonObject(); 312 | 313 | jsonMsg["msg"] = MSG_ANDROID_KEY_DOWN; 314 | jsonMsg["key"] = key; 315 | this.SendPluginMsg(jsonMsg); 316 | } 317 | 318 | 319 | void UpdateForceKeyeventForAndroid() 320 | { 321 | #if UNITY_ANDROID &&!UNITY_EDITOR 322 | 323 | if (Input.anyKeyDown) 324 | { 325 | if (Input.GetKeyDown(KeyCode.Backspace)) 326 | { 327 | this.ForceSendKeydown_Android("backspace"); 328 | } 329 | else 330 | { 331 | foreach(char c in Input.inputString) 332 | { 333 | if (c == "\n"[0]) 334 | { 335 | this.ForceSendKeydown_Android("enter"); 336 | } 337 | } 338 | } 339 | } 340 | #endif 341 | } 342 | 343 | } 344 | -------------------------------------------------------------------------------- /release/NativeEditPlugin/scripts/PluginMsgHandler.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 Kyungmin Bang 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | using UnityEngine; 25 | using System.Collections; 26 | using System.Collections.Generic; 27 | using System.Runtime.InteropServices; 28 | using System; 29 | using System.IO; 30 | using AOT; 31 | 32 | public abstract class PluginMsgReceiver : MonoBehaviour 33 | { 34 | private int nReceiverId; 35 | 36 | protected void Start() 37 | { 38 | nReceiverId = PluginMsgHandler.getInst().RegisterAndGetReceiverId(this); 39 | } 40 | 41 | protected void OnDestroy() 42 | { 43 | PluginMsgHandler.getInst().RemoveReceiver(nReceiverId); 44 | } 45 | 46 | protected void Update() 47 | { 48 | } 49 | 50 | protected JsonObject SendPluginMsg(JsonObject jsonMsg) 51 | { 52 | return PluginMsgHandler.getInst().SendMsgToPlugin(nReceiverId, jsonMsg); 53 | } 54 | 55 | public abstract void OnPluginMsgDirect(JsonObject jsonMsg); 56 | } 57 | 58 | public class PluginMsgHandler : MonoBehaviour { 59 | private static PluginMsgHandler inst; 60 | public static PluginMsgHandler getInst() { return inst; } 61 | 62 | private static bool sPluginInitialized = false; 63 | private int snCurReceiverIdx = 0; 64 | private Dictionary m_dictReceiver = new Dictionary(); 65 | 66 | private static StreamWriter fileWriter = null; 67 | 68 | public delegate void ShowKeyboardDelegate(bool bKeyboardShow, int nKeyHeight); 69 | public ShowKeyboardDelegate OnShowKeyboard = null; 70 | 71 | private static string MSG_SHOW_KEYBOARD = "ShowKeyboard"; 72 | private static string DEFAULT_NAME = "NativeEditPluginHandler"; 73 | private static bool ENABLE_WRITE_LOG = false; 74 | 75 | void Awake() 76 | { 77 | int tempRandom = (int) UnityEngine.Random.Range(0, 10000.0f); 78 | this.name = DEFAULT_NAME + tempRandom.ToString(); 79 | 80 | if (ENABLE_WRITE_LOG) 81 | { 82 | string fileName = Application.persistentDataPath + "/unity_app.log"; 83 | fileWriter = File.CreateText(fileName); 84 | fileWriter.WriteLine("[LogWriter] Initialized"); 85 | Debug.Log(string.Format("log location {0}", fileName)); 86 | } 87 | inst = this; 88 | this.InitializeHandler(); 89 | } 90 | 91 | void OnDestory() 92 | { 93 | FileLog("Application closed"); 94 | if (fileWriter != null) fileWriter.Close(); 95 | fileWriter = null; 96 | this.FinalizeHandler(); 97 | } 98 | 99 | public int RegisterAndGetReceiverId(PluginMsgReceiver receiver) 100 | { 101 | snCurReceiverIdx++; 102 | 103 | m_dictReceiver[snCurReceiverIdx] = receiver; 104 | return snCurReceiverIdx; 105 | } 106 | 107 | public void RemoveReceiver(int nReceiverId) 108 | { 109 | m_dictReceiver.Remove(nReceiverId); 110 | } 111 | 112 | public void FileLog(string strLog, string strTag = "NativeEditBoxLog") 113 | { 114 | string strOut = string.Format("[!] {0} {1} [{2}]",strTag, strLog, DateTime.Now.ToLongTimeString()); 115 | 116 | if (fileWriter != null) 117 | { 118 | fileWriter.WriteLine(strOut); 119 | fileWriter.Flush(); 120 | } 121 | 122 | Debug.Log(strOut); 123 | } 124 | public void FileLogError(string strLog) 125 | { 126 | string strOut = string.Format("[!ERROR!] {0} [{1}]", strLog, DateTime.Now.ToLongTimeString()); 127 | if (fileWriter != null) 128 | { 129 | fileWriter.WriteLine(strOut); 130 | fileWriter.Flush(); 131 | } 132 | Debug.Log(strOut); 133 | } 134 | public PluginMsgReceiver GetReceiver(int nSenderId) 135 | { 136 | return m_dictReceiver[nSenderId]; 137 | } 138 | 139 | private void OnMsgFromPlugin(string jsonPluginMsg) 140 | { 141 | if (jsonPluginMsg == null) return; 142 | 143 | JsonObject jsonMsg = new JsonObject(jsonPluginMsg); 144 | 145 | string msg = jsonMsg.GetString("msg"); 146 | 147 | if (msg.Equals(MSG_SHOW_KEYBOARD)) 148 | { 149 | bool bShow = jsonMsg.GetBool("show"); 150 | int nKeyHeight = (int)( jsonMsg.GetFloat("keyheight") * (float) Screen.height); 151 | //FileLog(string.Format("keyshow {0} height {1}", bShow, nKeyHeight)); 152 | if (OnShowKeyboard != null) 153 | { 154 | OnShowKeyboard(bShow, nKeyHeight); 155 | } 156 | } 157 | else 158 | { 159 | int nSenderId = jsonMsg.GetInt("senderId"); 160 | PluginMsgReceiver receiver = PluginMsgHandler.getInst().GetReceiver(nSenderId); 161 | receiver.OnPluginMsgDirect(jsonMsg); 162 | } 163 | } 164 | 165 | #if UNITY_IPHONE 166 | [DllImport ("__Internal")] 167 | private static extern void _iOS_InitPluginMsgHandler(string unityName); 168 | [DllImport ("__Internal")] 169 | private static extern string _iOS_SendUnityMsgToPlugin(int nSenderId, string strMsg); 170 | [DllImport ("__Internal")] 171 | private static extern void _iOS_ClosePluginMsgHandler(); 172 | 173 | public void InitializeHandler() 174 | { 175 | #if UNITY_EDITOR 176 | return; 177 | #endif 178 | if (sPluginInitialized) return; 179 | 180 | _iOS_InitPluginMsgHandler(this.name); 181 | sPluginInitialized = true; 182 | } 183 | 184 | public void FinalizeHandler() 185 | { 186 | #if UNITY_EDITOR 187 | return; 188 | #endif 189 | _iOS_ClosePluginMsgHandler(); 190 | } 191 | 192 | #elif UNITY_ANDROID 193 | 194 | private static AndroidJavaClass smAndroid; 195 | public void InitializeHandler() 196 | { 197 | #if UNITY_EDITOR 198 | return; 199 | #endif 200 | if (sPluginInitialized) return; 201 | 202 | smAndroid = new AndroidJavaClass("com.bkmin.android.NativeEditPlugin"); 203 | smAndroid.CallStatic("InitPluginMsgHandler", this.name); 204 | sPluginInitialized = true; 205 | } 206 | 207 | public void FinalizeHandler() 208 | { 209 | #if UNITY_EDITOR 210 | return; 211 | #endif 212 | smAndroid.CallStatic("ClosePluginMsgHandler"); 213 | } 214 | 215 | #else 216 | public void InitializeHandler() 217 | { 218 | } 219 | public void FinalizeHandler() 220 | { 221 | } 222 | 223 | #endif 224 | 225 | 226 | public JsonObject SendMsgToPlugin(int nSenderId, JsonObject jsonMsg) 227 | { 228 | #if UNITY_EDITOR 229 | return new JsonObject(); 230 | #endif 231 | 232 | jsonMsg["senderId"] = nSenderId; 233 | string strJson = jsonMsg.Serialize(); 234 | 235 | string strRet = ""; 236 | #if UNITY_IPHONE 237 | strRet = _iOS_SendUnityMsgToPlugin(nSenderId, strJson); 238 | #elif UNITY_ANDROID 239 | strRet = smAndroid.CallStatic("SendUnityMsgToPlugin", nSenderId, strJson); 240 | #endif 241 | 242 | JsonObject jsonRet = new JsonObject(strRet); 243 | return jsonRet; 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /src/androidProj/.gradle/2.2.1/taskArtifacts/cache.properties: -------------------------------------------------------------------------------- 1 | #Wed May 06 15:29:36 PDT 2015 2 | -------------------------------------------------------------------------------- /src/androidProj/.gradle/2.2.1/taskArtifacts/cache.properties.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/src/androidProj/.gradle/2.2.1/taskArtifacts/cache.properties.lock -------------------------------------------------------------------------------- /src/androidProj/.gradle/2.2.1/taskArtifacts/fileHashes.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/src/androidProj/.gradle/2.2.1/taskArtifacts/fileHashes.bin -------------------------------------------------------------------------------- /src/androidProj/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/src/androidProj/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin -------------------------------------------------------------------------------- /src/androidProj/.gradle/2.2.1/taskArtifacts/outputFileStates.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/src/androidProj/.gradle/2.2.1/taskArtifacts/outputFileStates.bin -------------------------------------------------------------------------------- /src/androidProj/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/src/androidProj/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin -------------------------------------------------------------------------------- /src/androidProj/.idea/.name: -------------------------------------------------------------------------------- 1 | androidProj -------------------------------------------------------------------------------- /src/androidProj/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/androidProj/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/androidProj/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/androidProj/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/androidProj/.idea/libraries/appcompat_v7_22_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/androidProj/.idea/libraries/classes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/androidProj/.idea/libraries/support_annotations_22_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/androidProj/.idea/libraries/support_v4_22_0_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/androidProj/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 1.8 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/androidProj/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/androidProj/.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /src/androidProj/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/androidProj/androidProj.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/androidProj/app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/androidProj/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.1.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/androidProj/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /src/androidProj/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/src/androidProj/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/androidProj/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /src/androidProj/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /src/androidProj/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/androidProj/local.properties: -------------------------------------------------------------------------------- 1 | ## This file is automatically generated by Android Studio. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file should *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | # 7 | # Location of the SDK. This is only used by Gradle. 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | sdk.dir=/Users/kyungminbang/Library/Android/sdk -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | minSdkVersion 9 9 | targetSdkVersion 21 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:22.0.0' 24 | } 25 | 26 | task clearJar(type: Delete) { 27 | delete 'build/outputs/nativeeditplugin.jar' 28 | } 29 | 30 | task makeJar(type: Copy) { 31 | from('build/intermediates/bundles/release/') 32 | into('build/outputs/') 33 | include('classes.jar') 34 | rename ('classes.jar', 'nativeeditplugin.jar') 35 | } 36 | 37 | makeJar.dependsOn(clearJar, build) -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/libs/classes.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmbang/UnityNativeEdit/ed0d364b8d101bc85397d141666376575ed75d79/src/androidProj/nativeeditplugin/libs/classes.jar -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/nativeeditplugin.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/kyungminbang/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/src/androidTest/java/com/bkmin/android/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.bkmin.android; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/src/main/java/com/bkmin/android/EditBox.java: -------------------------------------------------------------------------------- 1 | package com.bkmin.android; 2 | 3 | /** 4 | * Created by kyungminbang on 5/5/15. 5 | */ 6 | 7 | import org.json.JSONException; 8 | import org.json.JSONObject; 9 | 10 | import com.unity3d.player.UnityPlayer; 11 | import android.app.Activity; 12 | import android.graphics.Color; 13 | import android.graphics.Rect; 14 | import android.graphics.Typeface; 15 | 16 | import android.text.Editable; 17 | import android.text.InputType; 18 | import android.text.TextWatcher; 19 | import android.util.Log; 20 | import android.util.SparseArray; 21 | import android.util.TypedValue; 22 | import android.view.Gravity; 23 | import android.view.KeyEvent; 24 | import android.view.MotionEvent; 25 | import android.view.View; 26 | import android.view.inputmethod.InputMethodManager; 27 | import android.widget.EditText; 28 | import android.widget.RelativeLayout; 29 | 30 | /// UnityEditBox Plugin 31 | /// Written by bkmin 2015/5 (kmin.bang@gmail.com) 32 | 33 | public class EditBox { 34 | private EditText edit; 35 | private RelativeLayout layout; 36 | private int tag; 37 | private String unityName; 38 | public boolean isActive = false; 39 | 40 | private static SparseArray mapEditBox = null; 41 | private static String MSG_CREATE = "CreateEdit"; 42 | private static String MSG_REMOVE = "RemoveEdit"; 43 | private static String MSG_SET_TEXT = "SetText"; 44 | private static String MSG_GET_TEXT = "GetText"; 45 | private static String MSG_SET_RECT = "SetRect"; 46 | private static String MSG_SET_FOCUS = "SetFocus"; 47 | private static String MSG_SET_VISIBLE = "SetVisible"; 48 | private static String MSG_TEXT_CHANGE = "TextChange"; 49 | private static String MSG_TEXT_END_EDIT = "TextEndEdit"; 50 | private static String MSG_ANDROID_KEY_DOWN = "AndroidKeyDown"; 51 | 52 | public static JSONObject makeJsonRet(boolean isError, String strError) 53 | { 54 | JSONObject json = new JSONObject(); 55 | try 56 | { 57 | json.put("bError", isError); 58 | json.put("strError", strError); 59 | } 60 | catch(JSONException e) {} 61 | return json; 62 | } 63 | 64 | public static JSONObject processRecvJsonMsg(int nSenderId, final String strJson) 65 | { 66 | JSONObject jsonRet = null; 67 | 68 | if (mapEditBox == null) mapEditBox = new SparseArray(); 69 | 70 | try 71 | { 72 | JSONObject jsonMsg = new JSONObject(strJson); 73 | String msg = jsonMsg.getString("msg"); 74 | 75 | if (msg.equals(MSG_CREATE)) 76 | { 77 | EditBox nb = new EditBox(NativeEditPlugin.mainLayout); 78 | nb.Create(nSenderId, jsonMsg); 79 | mapEditBox.append(nSenderId, nb); 80 | jsonRet = makeJsonRet(false, ""); 81 | } 82 | else 83 | { 84 | EditBox eb = mapEditBox.get(nSenderId); 85 | if (eb != null) { 86 | jsonRet = eb.processJsonMsg(jsonMsg); 87 | } 88 | else 89 | { 90 | Log.e(NativeEditPlugin.LOG_TAG, "EditBox not found"); 91 | } 92 | } 93 | 94 | 95 | } catch (JSONException e) 96 | { 97 | } 98 | return jsonRet; 99 | } 100 | 101 | public EditBox(RelativeLayout mainLayout) 102 | { 103 | layout = mainLayout; 104 | edit = null; 105 | } 106 | 107 | public void showKeyboard(boolean isShow) 108 | { 109 | InputMethodManager imm = (InputMethodManager) NativeEditPlugin.unityActivity.getSystemService(Activity.INPUT_METHOD_SERVICE); 110 | if (isShow) 111 | { 112 | imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); 113 | } 114 | else 115 | { 116 | View rootView = NativeEditPlugin.unityActivity.getWindow().getDecorView(); 117 | rootView.clearFocus(); 118 | imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); 119 | } 120 | } 121 | 122 | public JSONObject processJsonMsg(JSONObject jsonMsg) 123 | { 124 | JSONObject jsonRet = makeJsonRet(false, ""); 125 | try 126 | { 127 | String msg = jsonMsg.getString("msg"); 128 | 129 | if (msg.equals(MSG_REMOVE)) 130 | { 131 | this.Remove(); 132 | } 133 | else if (msg.equals(MSG_SET_TEXT)) 134 | { 135 | String text = jsonMsg.getString("text"); 136 | this.SetText(text); 137 | } 138 | else if (msg.equals(MSG_GET_TEXT)) 139 | { 140 | String text = this.GetText(); 141 | jsonRet.put("text", text); 142 | } 143 | else if (msg.equals(MSG_SET_RECT)) 144 | { 145 | this.SetRect(jsonMsg); 146 | } 147 | else if (msg.equals(MSG_SET_FOCUS)) 148 | { 149 | boolean isFocus = jsonMsg.getBoolean("isFocus"); 150 | this.SetFocus(isFocus); 151 | } 152 | else if (msg.equals(MSG_SET_VISIBLE)) 153 | { 154 | boolean isVisible = jsonMsg.getBoolean("isVisible"); 155 | this.SetVisible(isVisible); 156 | } 157 | else if (msg.equals(MSG_ANDROID_KEY_DOWN)) 158 | { 159 | String strKey = jsonMsg.getString("key"); 160 | this.OnForceAndroidKeyDown(strKey); 161 | } 162 | 163 | } catch (JSONException e) 164 | { 165 | } 166 | return jsonRet; 167 | } 168 | 169 | public void SendJsonToUnity(JSONObject jsonToUnity) 170 | { 171 | try 172 | { 173 | jsonToUnity.put("senderId", this.tag); 174 | } 175 | catch(JSONException e) {} 176 | NativeEditPlugin.SendUnityMessage(jsonToUnity); 177 | } 178 | 179 | public void Create(int _tag, JSONObject jsonObj) 180 | { 181 | this.tag = _tag; 182 | 183 | try { 184 | String placeHolder = jsonObj.getString("placeHolder"); 185 | 186 | String font = jsonObj.getString("font"); 187 | double fontSize = jsonObj.getDouble("fontSize"); 188 | 189 | double x = jsonObj.getDouble("x") * (double) layout.getWidth(); 190 | double y = jsonObj.getDouble("y") * (double) layout.getHeight(); 191 | double width = jsonObj.getDouble("width") * (double) layout.getWidth(); 192 | double height = jsonObj.getDouble("height") * (double) layout.getHeight(); 193 | 194 | int textColor_r = (int) (255.0f * jsonObj.getDouble("textColor_r")); 195 | int textColor_g = (int) (255.0f * jsonObj.getDouble("textColor_g")); 196 | int textColor_b = (int) (255.0f * jsonObj.getDouble("textColor_b")); 197 | int textColor_a = (int) (255.0f * jsonObj.getDouble("textColor_a")); 198 | int backColor_r = (int) (255.0f * jsonObj.getDouble("backColor_r")); 199 | int backColor_g = (int) (255.0f * jsonObj.getDouble("backColor_g")); 200 | int backColor_b = (int) (255.0f * jsonObj.getDouble("backColor_b")); 201 | int backColor_a = (int) (255.0f * jsonObj.getDouble("backColor_a")); 202 | 203 | String contentType = jsonObj.getString("contentType"); 204 | String alignment = jsonObj.getString("align"); 205 | boolean withDoneButton = jsonObj.getBoolean("withDoneButton"); 206 | boolean multiline = jsonObj.getBoolean("multiline"); 207 | 208 | edit = new EditText(NativeEditPlugin.unityActivity.getApplicationContext()); 209 | edit.setId(0); 210 | edit.setText(""); 211 | edit.setHint(placeHolder); 212 | 213 | Rect rect = new Rect((int) x, (int) y, (int) (x + width), (int) (y + height)); 214 | RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(rect.width(), rect.height()); 215 | lp.setMargins(rect.left, rect.top, 0, 0); 216 | edit.setLayoutParams(lp); 217 | edit.setPadding(0, 0, 0, 0); 218 | 219 | int inputType = edit.getInputType(); 220 | if (contentType.equals("Autocorrected")) { 221 | inputType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; 222 | } else if (contentType.equals("IntegerNumber")) { 223 | inputType |= InputType.TYPE_NUMBER_VARIATION_NORMAL; 224 | } else if (contentType.equals("DecimalNumber")) { 225 | inputType |= InputType.TYPE_NUMBER_FLAG_DECIMAL; 226 | } else if (contentType.equals("Alphanumeric")) { 227 | // inputType |= InputType. 228 | } else if (contentType.equals("Name")) { 229 | inputType |= InputType.TYPE_TEXT_VARIATION_PERSON_NAME; 230 | } else if (contentType.equals("EmailAddress")) { 231 | inputType |= InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; 232 | } else if (contentType.equals("Password")) { 233 | inputType |= InputType.TYPE_TEXT_VARIATION_PASSWORD; 234 | } else if (contentType.equals("Pin")) { 235 | inputType |= InputType.TYPE_TEXT_VARIATION_PHONETIC; 236 | } 237 | edit.setInputType(inputType); 238 | 239 | int gravity = 0; 240 | if (alignment.equals("UpperLeft")) 241 | { 242 | gravity = Gravity.TOP | Gravity.LEFT; 243 | } 244 | else if (alignment.equals("UpperCenter")) 245 | { 246 | gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; 247 | } 248 | else if (alignment.equals("UpperRight")) 249 | { 250 | gravity = Gravity.TOP | Gravity.RIGHT; 251 | } 252 | else if (alignment.equals("MiddleLeft")) 253 | { 254 | gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT; 255 | } 256 | else if (alignment.equals("MiddleCenter")) 257 | { 258 | gravity = Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL; 259 | } 260 | else if (alignment.equals("MiddleRight")) 261 | { 262 | gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT; 263 | } 264 | else if (alignment.equals("LowerLeft")) 265 | { 266 | gravity = Gravity.BOTTOM | Gravity.LEFT; 267 | } 268 | else if (alignment.equals("LowerCenter")) 269 | { 270 | gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; 271 | } 272 | else if (alignment.equals("LowerRight")) 273 | { 274 | gravity = Gravity.BOTTOM | Gravity.RIGHT; 275 | } 276 | edit.setGravity(gravity); 277 | 278 | 279 | edit.setTextSize(TypedValue.COMPLEX_UNIT_PX, (float) fontSize); 280 | edit.setTextColor(Color.argb(textColor_a, textColor_r, textColor_g, textColor_b)); 281 | edit.setBackgroundColor(Color.argb(backColor_a, backColor_r, backColor_g, backColor_b)); 282 | 283 | Typeface tf = Typeface.create(font, Typeface.NORMAL); 284 | edit.setTypeface(tf); 285 | edit.setSingleLine(!multiline); 286 | 287 | final EditBox eb = this; 288 | 289 | edit.setOnFocusChangeListener(new View.OnFocusChangeListener() { 290 | @Override 291 | public void onFocusChange(View v, boolean hasFocus) { 292 | if (!hasFocus) { 293 | // your action here 294 | JSONObject jsonToUnity = new JSONObject(); 295 | try 296 | { 297 | jsonToUnity.put("msg", MSG_TEXT_END_EDIT); 298 | jsonToUnity.put("text", eb.GetText()); 299 | } 300 | catch(JSONException e) {} 301 | eb.SendJsonToUnity(jsonToUnity); 302 | eb.showKeyboard(false); 303 | } 304 | } 305 | }); 306 | 307 | edit.addTextChangedListener(new TextWatcher() { 308 | public void afterTextChanged(Editable s) 309 | { 310 | JSONObject jsonToUnity = new JSONObject(); 311 | try 312 | { 313 | jsonToUnity.put("msg", MSG_TEXT_CHANGE); 314 | jsonToUnity.put("text", s.toString()); 315 | } 316 | catch(JSONException e) {} 317 | eb.SendJsonToUnity(jsonToUnity); 318 | } 319 | 320 | @Override 321 | public void beforeTextChanged(CharSequence s, int start, 322 | int count, int after) { 323 | // TODO Auto-generated method stub 324 | 325 | } 326 | 327 | @Override 328 | public void onTextChanged(CharSequence s, int start, 329 | int before, int count) { 330 | // TODO Auto-generated method stub 331 | 332 | } 333 | }); 334 | 335 | layout.setFocusableInTouchMode(true); 336 | layout.setClickable(true); 337 | layout.addView(edit); 338 | 339 | } catch (JSONException e) 340 | { 341 | Log.i(NativeEditPlugin.LOG_TAG, String.format("Create editbox error %s", e.getMessage())); 342 | return; 343 | } 344 | } 345 | 346 | public void Remove() 347 | { 348 | layout.removeView(edit); 349 | edit = null; 350 | } 351 | 352 | public void SetText(String newText) 353 | { 354 | edit.setText(newText); 355 | } 356 | public String GetText() 357 | { 358 | return edit.getText().toString(); 359 | } 360 | 361 | public boolean isFocused() 362 | { 363 | return edit.isFocused(); 364 | } 365 | 366 | public void SetFocus(boolean isFocus) 367 | { 368 | if (isFocus) 369 | { 370 | edit.requestFocus(); 371 | } 372 | else 373 | { 374 | edit.clearFocus(); 375 | 376 | } 377 | this.showKeyboard(isFocus); 378 | } 379 | 380 | public void SetRect(JSONObject jsonRect) 381 | { 382 | try 383 | { 384 | double x = jsonRect.getDouble("x") * (double) layout.getWidth(); 385 | double y = jsonRect.getDouble("y") * (double) layout.getHeight(); 386 | double width = jsonRect.getDouble("width") * (double) layout.getWidth(); 387 | double height = jsonRect.getDouble("height") * (double) layout.getHeight(); 388 | 389 | Rect rect = new Rect((int) x, (int) y, (int) (x + width), (int) (y + height)); 390 | RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(rect.width(), rect.height()); 391 | lp.setMargins(rect.left, rect.top, 0, 0); 392 | edit.setLayoutParams(lp); 393 | 394 | } catch (JSONException e) 395 | { 396 | return; 397 | } 398 | } 399 | 400 | public void SetVisible(boolean bVisible) 401 | { 402 | edit.setEnabled(bVisible); 403 | edit.setVisibility(bVisible ? View.VISIBLE : View.INVISIBLE); 404 | } 405 | 406 | public void OnForceAndroidKeyDown(String strKey) 407 | { 408 | if (!this.isFocused()) return; 409 | 410 | // Need to force fire key event of backspace and enter because Unity eats them and never return back to plugin. 411 | int keyCode = -1; 412 | if (strKey.equalsIgnoreCase("backspace")) 413 | { 414 | keyCode = KeyEvent.KEYCODE_DEL; 415 | } 416 | else if (strKey.equalsIgnoreCase("enter")) 417 | { 418 | keyCode = KeyEvent.KEYCODE_ENTER; 419 | } 420 | if (keyCode > 0) 421 | { 422 | KeyEvent ke = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode); 423 | Log.i(NativeEditPlugin.LOG_TAG, String.format("Force fire KEY EVENT %d", keyCode)); 424 | edit.onKeyDown(keyCode, ke); 425 | } 426 | } 427 | } 428 | -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/src/main/java/com/bkmin/android/NativeEditPlugin.java: -------------------------------------------------------------------------------- 1 | package com.bkmin.android; 2 | import com.unity3d.player.*; 3 | 4 | import android.app.Activity; 5 | import android.graphics.Rect; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.view.ViewTreeObserver; 10 | import android.widget.RelativeLayout; 11 | 12 | import org.json.JSONException; 13 | import org.json.JSONObject; 14 | 15 | import java.util.concurrent.atomic.AtomicBoolean; 16 | 17 | /// UnityEditBox Plugin 18 | /// Written by bkmin 2015/5 (kmin.bang@gmail.com) 19 | 20 | public class NativeEditPlugin { 21 | public static Activity unityActivity; 22 | public static RelativeLayout mainLayout; 23 | private static ViewGroup topViewGroup; 24 | private static boolean pluginInitialized = false; 25 | private static final Object Lock = new Object() {}; 26 | private static int keyboardHeight = 0; 27 | private static String unityName = ""; 28 | private static String MSG_SHOW_KEYBOARD = "ShowKeyboard"; 29 | 30 | public static String LOG_TAG = "NativeEditPlugin"; 31 | 32 | private static View getLeafView(View view) { 33 | if (view instanceof ViewGroup) { 34 | ViewGroup vg = (ViewGroup)view; 35 | for (int i = 0; i < vg.getChildCount(); ++i) { 36 | View chview = vg.getChildAt(i); 37 | View result = getLeafView(chview); 38 | if (result != null) 39 | return result; 40 | } 41 | return null; 42 | } 43 | else { 44 | Log.i(LOG_TAG, "Found leaf view"); 45 | return view; 46 | } 47 | } 48 | 49 | private static void SetInitialized() 50 | { 51 | synchronized(Lock) 52 | { 53 | pluginInitialized = true; 54 | } 55 | } 56 | 57 | public static boolean IsPluginInitialized() 58 | { 59 | synchronized(Lock) 60 | { 61 | return pluginInitialized; 62 | } 63 | } 64 | 65 | public static void InitPluginMsgHandler(final String _unityName) 66 | { 67 | unityActivity = UnityPlayer.currentActivity; 68 | unityName = _unityName; 69 | 70 | unityActivity.runOnUiThread(new Runnable() { 71 | public void run() { 72 | final ViewGroup rootView = (ViewGroup) unityActivity.findViewById (android.R.id.content); 73 | View topMostView = getLeafView(rootView); 74 | topViewGroup = (ViewGroup) topMostView.getParent(); 75 | mainLayout = new RelativeLayout(unityActivity); 76 | RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams( 77 | RelativeLayout.LayoutParams.MATCH_PARENT, 78 | RelativeLayout.LayoutParams.MATCH_PARENT); 79 | topViewGroup.addView(mainLayout, rlp); 80 | SetInitialized(); 81 | 82 | rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 83 | @Override 84 | public void onGlobalLayout() { 85 | 86 | Rect r = new Rect(); 87 | rootView.getWindowVisibleDisplayFrame(r); 88 | int screenHeight = rootView.getRootView().getHeight(); 89 | 90 | // r.bottom is the position above soft keypad or device button. 91 | // if keypad is shown, the r.bottom is smaller than that before. 92 | keyboardHeight = screenHeight - r.bottom; 93 | boolean bKeyOpen = (keyboardHeight > screenHeight * 0.15); 94 | 95 | float fKeyHeight = (float) keyboardHeight / (float) screenHeight; 96 | 97 | JSONObject json = new JSONObject(); 98 | try { 99 | json.put("msg", MSG_SHOW_KEYBOARD); 100 | json.put("show", bKeyOpen); 101 | json.put("keyheight", fKeyHeight); 102 | } catch (JSONException e) { 103 | } 104 | SendUnityMessage(json); 105 | } 106 | }); 107 | Log.i(LOG_TAG, "InitEditBoxPlugin okay"); 108 | } 109 | }); 110 | } 111 | 112 | public static void ClosePluginMsgHandler() 113 | { 114 | unityActivity.runOnUiThread(new Runnable() { 115 | public void run() { 116 | topViewGroup.removeView(mainLayout); 117 | } 118 | }); 119 | } 120 | 121 | public static void SendUnityMessage(JSONObject jsonMsg) 122 | { 123 | UnityPlayer.UnitySendMessage(unityName, "OnMsgFromPlugin", jsonMsg.toString()); 124 | } 125 | 126 | static JSONObject jsonStaticRet = null; 127 | public static String SendUnityMsgToPlugin(final int nSenderId, final String jsonMsg) { 128 | final Runnable task = new Runnable() { 129 | public void run() { 130 | jsonStaticRet = EditBox.processRecvJsonMsg(nSenderId, jsonMsg); 131 | synchronized (this) { 132 | this.notify(); 133 | } 134 | } 135 | }; 136 | synchronized (task) { 137 | unityActivity.runOnUiThread(task); 138 | try 139 | { 140 | task.wait(); 141 | } 142 | catch ( InterruptedException e ) 143 | { 144 | e.printStackTrace(); 145 | } 146 | } 147 | 148 | return jsonStaticRet.toString(); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/androidProj/nativeeditplugin/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | nativeeditplugin 3 | 4 | -------------------------------------------------------------------------------- /src/androidProj/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':nativeeditplugin' 2 | --------------------------------------------------------------------------------