CCEAGLView-ios.mm 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. /*
  2. ===== IMPORTANT =====
  3. This is sample code demonstrating API, technology or techniques in development.
  4. Although this sample code has been reviewed for technical accuracy, it is not
  5. final. Apple is supplying this information to help you plan for the adoption of
  6. the technologies and programming interfaces described herein. This information
  7. is subject to change, and software implemented based on this sample code should
  8. be tested with final operating system software and final documentation. Newer
  9. versions of this sample code may be provided with future seeds of the API or
  10. technology. For information about updates to this and other developer
  11. documentation, view the New & Updated sidebars in subsequent documentation
  12. seeds.
  13. =====================
  14. File: EAGLView.m
  15. Abstract: Convenience class that wraps the CAEAGLLayer from CoreAnimation into a
  16. UIView subclass.
  17. Version: 1.3
  18. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
  19. ("Apple") in consideration of your agreement to the following terms, and your
  20. use, installation, modification or redistribution of this Apple software
  21. constitutes acceptance of these terms. If you do not agree with these terms,
  22. please do not use, install, modify or redistribute this Apple software.
  23. In consideration of your agreement to abide by the following terms, and subject
  24. to these terms, Apple grants you a personal, non-exclusive license, under
  25. Apple's copyrights in this original Apple software (the "Apple Software"), to
  26. use, reproduce, modify and redistribute the Apple Software, with or without
  27. modifications, in source and/or binary forms; provided that if you redistribute
  28. the Apple Software in its entirety and without modifications, you must retain
  29. this notice and the following text and disclaimers in all such redistributions
  30. of the Apple Software.
  31. Neither the name, trademarks, service marks or logos of Apple Inc. may be used
  32. to endorse or promote products derived from the Apple Software without specific
  33. prior written permission from Apple. Except as expressly stated in this notice,
  34. no other rights or licenses, express or implied, are granted by Apple herein,
  35. including but not limited to any patent rights that may be infringed by your
  36. derivative works or by other works in which the Apple Software may be
  37. incorporated.
  38. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
  39. WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
  40. WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  41. PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
  42. COMBINATION WITH YOUR PRODUCTS.
  43. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
  44. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  45. GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  46. ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
  47. DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
  48. CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
  49. APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  50. Copyright (C) 2008 Apple Inc. All Rights Reserved.
  51. */
  52. #include "platform/CCPlatformConfig.h"
  53. #if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
  54. #import "platform/ios/CCEAGLView-ios.h"
  55. #import <QuartzCore/QuartzCore.h>
  56. #import "base/CCDirector.h"
  57. #import "base/CCTouch.h"
  58. #import "base/CCIMEDispatcher.h"
  59. #import "platform/ios/CCGLViewImpl-ios.h"
  60. #import "platform/ios/CCES2Renderer-ios.h"
  61. #import "platform/ios/OpenGL_Internal-ios.h"
  62. //CLASS IMPLEMENTATIONS:
  63. #define IOS_MAX_TOUCHES_COUNT 10
  64. @interface CCEAGLView (Private)
  65. - (BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup;
  66. - (unsigned int) convertPixelFormat:(NSString*) pixelFormat;
  67. @end
  68. @implementation CCEAGLView
  69. @synthesize surfaceSize=size_;
  70. @synthesize pixelFormat=pixelformat_, depthFormat=depthFormat_;
  71. @synthesize context=context_;
  72. @synthesize multiSampling=multiSampling_;
  73. @synthesize isKeyboardShown=isKeyboardShown_;
  74. @synthesize keyboardShowNotification = keyboardShowNotification_;
  75. + (Class) layerClass
  76. {
  77. return [CAEAGLLayer class];
  78. }
  79. + (id) viewWithFrame:(CGRect)frame
  80. {
  81. return [[[self alloc] initWithFrame:frame] autorelease];
  82. }
  83. + (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format
  84. {
  85. return [[[self alloc]initWithFrame:frame pixelFormat:format] autorelease];
  86. }
  87. + (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth
  88. {
  89. return [[[self alloc] initWithFrame:frame pixelFormat:format depthFormat:depth preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0] autorelease];
  90. }
  91. + (id) viewWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)multisampling numberOfSamples:(unsigned int)samples
  92. {
  93. return [[[self alloc]initWithFrame:frame pixelFormat:format depthFormat:depth preserveBackbuffer:retained sharegroup:sharegroup multiSampling:multisampling numberOfSamples:samples] autorelease];
  94. }
  95. - (id) initWithFrame:(CGRect)frame
  96. {
  97. return [self initWithFrame:frame pixelFormat:kEAGLColorFormatRGB565 depthFormat:0 preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0];
  98. }
  99. - (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format
  100. {
  101. return [self initWithFrame:frame pixelFormat:format depthFormat:0 preserveBackbuffer:NO sharegroup:nil multiSampling:NO numberOfSamples:0];
  102. }
  103. - (id) initWithFrame:(CGRect)frame pixelFormat:(NSString*)format depthFormat:(GLuint)depth preserveBackbuffer:(BOOL)retained sharegroup:(EAGLSharegroup*)sharegroup multiSampling:(BOOL)sampling numberOfSamples:(unsigned int)nSamples
  104. {
  105. if((self = [super initWithFrame:frame]))
  106. {
  107. isUseUITextField = YES;
  108. pixelformat_ = format;
  109. depthFormat_ = depth;
  110. multiSampling_ = sampling;
  111. requestedSamples_ = nSamples;
  112. preserveBackbuffer_ = retained;
  113. markedText_ = nil;
  114. if( ! [self setupSurfaceWithSharegroup:sharegroup] ) {
  115. [self release];
  116. return nil;
  117. }
  118. originalRect_ = self.frame;
  119. self.keyboardShowNotification = nil;
  120. self.autocorrectionType = UITextAutocorrectionTypeNo;
  121. if ([self respondsToSelector:@selector(setContentScaleFactor:)])
  122. {
  123. self.contentScaleFactor = [[UIScreen mainScreen] scale];
  124. }
  125. }
  126. return self;
  127. }
  128. -(id) initWithCoder:(NSCoder *)aDecoder
  129. {
  130. if( (self = [super initWithCoder:aDecoder]) ) {
  131. CAEAGLLayer* eaglLayer = (CAEAGLLayer*)[self layer];
  132. pixelformat_ = kEAGLColorFormatRGB565;
  133. depthFormat_ = 0; // GL_DEPTH_COMPONENT24_OES;
  134. multiSampling_= NO;
  135. requestedSamples_ = 0;
  136. size_ = [eaglLayer bounds].size;
  137. markedText_ = nil;
  138. if( ! [self setupSurfaceWithSharegroup:nil] ) {
  139. [self release];
  140. return nil;
  141. }
  142. }
  143. return self;
  144. }
  145. - (void)didMoveToWindow
  146. {
  147. #if !defined(CC_TARGET_OS_TVOS)
  148. [[NSNotificationCenter defaultCenter] addObserver:self
  149. selector:@selector(onUIKeyboardNotification:)
  150. name:UIKeyboardWillShowNotification object:nil];
  151. [[NSNotificationCenter defaultCenter] addObserver:self
  152. selector:@selector(onUIKeyboardNotification:)
  153. name:UIKeyboardDidShowNotification object:nil];
  154. [[NSNotificationCenter defaultCenter] addObserver:self
  155. selector:@selector(onUIKeyboardNotification:)
  156. name:UIKeyboardWillHideNotification object:nil];
  157. [[NSNotificationCenter defaultCenter] addObserver:self
  158. selector:@selector(onUIKeyboardNotification:)
  159. name:UIKeyboardDidHideNotification object:nil];
  160. #endif
  161. }
  162. -(int) getWidth
  163. {
  164. CGSize bound = [self bounds].size;
  165. return (int)bound.width * self.contentScaleFactor;
  166. }
  167. -(int) getHeight
  168. {
  169. CGSize bound = [self bounds].size;
  170. return (int)bound.height * self.contentScaleFactor;
  171. }
  172. -(BOOL) setupSurfaceWithSharegroup:(EAGLSharegroup*)sharegroup
  173. {
  174. CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
  175. eaglLayer.opaque = YES;
  176. eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
  177. [NSNumber numberWithBool:preserveBackbuffer_], kEAGLDrawablePropertyRetainedBacking,
  178. pixelformat_, kEAGLDrawablePropertyColorFormat, nil];
  179. renderer_ = [[CCES2Renderer alloc] initWithDepthFormat:depthFormat_
  180. withPixelFormat:[self convertPixelFormat:pixelformat_]
  181. withSharegroup:sharegroup
  182. withMultiSampling:multiSampling_
  183. withNumberOfSamples:requestedSamples_];
  184. NSAssert(renderer_, @"OpenGL ES 2.O is required.");
  185. if (!renderer_)
  186. return NO;
  187. context_ = [renderer_ context];
  188. #if GL_EXT_discard_framebuffer == 1
  189. discardFramebufferSupported_ = YES;
  190. #else
  191. discardFramebufferSupported_ = NO;
  192. #endif
  193. CHECK_GL_ERROR();
  194. return YES;
  195. }
  196. - (void) dealloc
  197. {
  198. [[NSNotificationCenter defaultCenter] removeObserver:self]; // remove keyboard notification
  199. [renderer_ release];
  200. self.keyboardShowNotification = nullptr; // implicit release
  201. [super dealloc];
  202. }
  203. - (void) layoutSubviews
  204. {
  205. if (!cocos2d::Director::getInstance()->isValid())
  206. {
  207. return;
  208. }
  209. [renderer_ resizeFromLayer:(CAEAGLLayer*)self.layer];
  210. size_ = [renderer_ backingSize];
  211. // Issue #914 #924
  212. // Director *director = [Director sharedDirector];
  213. // [director reshapeProjection:size_];
  214. cocos2d::Size size;
  215. size.width = size_.width;
  216. size.height = size_.height;
  217. //cocos2d::Director::getInstance()->reshapeProjection(size);
  218. // Avoid flicker. Issue #350
  219. //[director performSelectorOnMainThread:@selector(drawScene) withObject:nil waitUntilDone:YES];
  220. if ([NSThread isMainThread])
  221. {
  222. cocos2d::Director::getInstance()->drawScene();
  223. }
  224. }
  225. - (void) swapBuffers
  226. {
  227. // IMPORTANT:
  228. // - preconditions
  229. // -> context_ MUST be the OpenGL context
  230. // -> renderbuffer_ must be the RENDER BUFFER
  231. #ifdef __IPHONE_4_0
  232. if (multiSampling_)
  233. {
  234. /* Resolve from msaaFramebuffer to resolveFramebuffer */
  235. //glDisable(GL_SCISSOR_TEST);
  236. glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, [renderer_ msaaFrameBuffer]);
  237. glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, [renderer_ defaultFrameBuffer]);
  238. glResolveMultisampleFramebufferAPPLE();
  239. }
  240. if(discardFramebufferSupported_)
  241. {
  242. if (multiSampling_)
  243. {
  244. if (depthFormat_)
  245. {
  246. GLenum attachments[] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT};
  247. glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, attachments);
  248. }
  249. else
  250. {
  251. GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
  252. glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 1, attachments);
  253. }
  254. glBindRenderbuffer(GL_RENDERBUFFER, [renderer_ colorRenderBuffer]);
  255. }
  256. // not MSAA
  257. else if (depthFormat_ ) {
  258. GLenum attachments[] = { GL_DEPTH_ATTACHMENT};
  259. glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
  260. }
  261. }
  262. #endif // __IPHONE_4_0
  263. if(![context_ presentRenderbuffer:GL_RENDERBUFFER])
  264. {
  265. // CCLOG(@"cocos2d: Failed to swap renderbuffer in %s\n", __FUNCTION__);
  266. }
  267. #if COCOS2D_DEBUG
  268. CHECK_GL_ERROR();
  269. #endif
  270. // We can safely re-bind the framebuffer here, since this will be the
  271. // 1st instruction of the new main loop
  272. if( multiSampling_ )
  273. glBindFramebuffer(GL_FRAMEBUFFER, [renderer_ msaaFrameBuffer]);
  274. }
  275. - (unsigned int) convertPixelFormat:(NSString*) pixelFormat
  276. {
  277. // define the pixel format
  278. GLenum pFormat;
  279. if([pixelFormat isEqualToString:@"EAGLColorFormat565"])
  280. pFormat = GL_RGB565;
  281. else
  282. pFormat = GL_RGBA8_OES;
  283. return pFormat;
  284. }
  285. #pragma mark CCEAGLView - Point conversion
  286. - (CGPoint) convertPointFromViewToSurface:(CGPoint)point
  287. {
  288. CGRect bounds = [self bounds];
  289. CGPoint ret;
  290. ret.x = (point.x - bounds.origin.x) / bounds.size.width * size_.width;
  291. ret.y = (point.y - bounds.origin.y) / bounds.size.height * size_.height;
  292. return ret;
  293. }
  294. - (CGRect) convertRectFromViewToSurface:(CGRect)rect
  295. {
  296. CGRect bounds = [self bounds];
  297. CGRect ret;
  298. ret.origin.x = (rect.origin.x - bounds.origin.x) / bounds.size.width * size_.width;
  299. ret.origin.y = (rect.origin.y - bounds.origin.y) / bounds.size.height * size_.height;
  300. ret.size.width = rect.size.width / bounds.size.width * size_.width;
  301. ret.size.height = rect.size.height / bounds.size.height * size_.height;
  302. return ret;
  303. }
  304. -(void) handleTouchesAfterKeyboardShow
  305. {
  306. NSArray *subviews = self.subviews;
  307. for(UIView* view in subviews)
  308. {
  309. if([view isKindOfClass:NSClassFromString(@"UITextView")] ||
  310. [view isKindOfClass:NSClassFromString(@"UITextField")])
  311. {
  312. if ([view isFirstResponder])
  313. {
  314. [view resignFirstResponder];
  315. return;
  316. }
  317. }
  318. }
  319. }
  320. // Pass the touches to the superview
  321. #pragma mark CCEAGLView - Touch Delegate
  322. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  323. {
  324. if (isKeyboardShown_)
  325. {
  326. [self handleTouchesAfterKeyboardShow];
  327. }
  328. UITouch* ids[IOS_MAX_TOUCHES_COUNT] = {0};
  329. float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  330. float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  331. int i = 0;
  332. for (UITouch *touch in touches) {
  333. ids[i] = touch;
  334. xs[i] = [touch locationInView: [touch view]].x * self.contentScaleFactor;
  335. ys[i] = [touch locationInView: [touch view]].y * self.contentScaleFactor;
  336. ++i;
  337. }
  338. auto glview = cocos2d::Director::getInstance()->getOpenGLView();
  339. glview->handleTouchesBegin(i, (intptr_t*)ids, xs, ys);
  340. }
  341. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
  342. {
  343. UITouch* ids[IOS_MAX_TOUCHES_COUNT] = {0};
  344. float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  345. float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  346. float fs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  347. float ms[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  348. int i = 0;
  349. for (UITouch *touch in touches) {
  350. ids[i] = touch;
  351. xs[i] = [touch locationInView: [touch view]].x * self.contentScaleFactor;
  352. ys[i] = [touch locationInView: [touch view]].y * self.contentScaleFactor;
  353. #if defined(__IPHONE_9_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0)
  354. // running on iOS 9.0 or higher version
  355. if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 9.0f) {
  356. fs[i] = touch.force;
  357. ms[i] = touch.maximumPossibleForce;
  358. }
  359. #endif
  360. ++i;
  361. }
  362. auto glview = cocos2d::Director::getInstance()->getOpenGLView();
  363. glview->handleTouchesMove(i, (intptr_t*)ids, xs, ys, fs, ms);
  364. }
  365. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
  366. {
  367. UITouch* ids[IOS_MAX_TOUCHES_COUNT] = {0};
  368. float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  369. float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  370. int i = 0;
  371. for (UITouch *touch in touches) {
  372. ids[i] = touch;
  373. xs[i] = [touch locationInView: [touch view]].x * self.contentScaleFactor;
  374. ys[i] = [touch locationInView: [touch view]].y * self.contentScaleFactor;
  375. ++i;
  376. }
  377. auto glview = cocos2d::Director::getInstance()->getOpenGLView();
  378. glview->handleTouchesEnd(i, (intptr_t*)ids, xs, ys);
  379. }
  380. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
  381. {
  382. UITouch* ids[IOS_MAX_TOUCHES_COUNT] = {0};
  383. float xs[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  384. float ys[IOS_MAX_TOUCHES_COUNT] = {0.0f};
  385. int i = 0;
  386. for (UITouch *touch in touches) {
  387. ids[i] = touch;
  388. xs[i] = [touch locationInView: [touch view]].x * self.contentScaleFactor;
  389. ys[i] = [touch locationInView: [touch view]].y * self.contentScaleFactor;
  390. ++i;
  391. }
  392. auto glview = cocos2d::Director::getInstance()->getOpenGLView();
  393. glview->handleTouchesCancel(i, (intptr_t*)ids, xs, ys);
  394. }
  395. #pragma mark - UIView - Responder
  396. - (BOOL)canBecomeFirstResponder
  397. {
  398. if (nil != markedText_) {
  399. [markedText_ release];
  400. }
  401. markedText_ = nil;
  402. if (isUseUITextField)
  403. {
  404. return NO;
  405. }
  406. return YES;
  407. }
  408. - (BOOL)becomeFirstResponder
  409. {
  410. isUseUITextField = NO;
  411. return [super becomeFirstResponder];
  412. }
  413. - (BOOL)resignFirstResponder
  414. {
  415. isUseUITextField = YES;
  416. return [super resignFirstResponder];
  417. }
  418. #pragma mark - UIKeyInput protocol
  419. - (BOOL)hasText
  420. {
  421. return NO;
  422. }
  423. - (void)insertText:(NSString *)text
  424. {
  425. if (nil != markedText_) {
  426. [markedText_ release];
  427. markedText_ = nil;
  428. }
  429. const char * pszText = [text cStringUsingEncoding:NSUTF8StringEncoding];
  430. cocos2d::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText));
  431. }
  432. - (void)deleteBackward
  433. {
  434. if (nil != markedText_) {
  435. [markedText_ release];
  436. markedText_ = nil;
  437. }
  438. cocos2d::IMEDispatcher::sharedDispatcher()->dispatchDeleteBackward();
  439. }
  440. #pragma mark - UITextInputTrait protocol
  441. -(UITextAutocapitalizationType) autocapitalizationType
  442. {
  443. return UITextAutocapitalizationTypeNone;
  444. }
  445. #pragma mark - UITextInput protocol
  446. #pragma mark UITextInput - properties
  447. @synthesize beginningOfDocument;
  448. @synthesize endOfDocument;
  449. @synthesize inputDelegate;
  450. @synthesize markedTextRange;
  451. @synthesize markedTextStyle;
  452. // @synthesize selectedTextRange; // must implement
  453. @synthesize tokenizer;
  454. @synthesize autocorrectionType;
  455. /* Text may have a selection, either zero-length (a caret) or ranged. Editing operations are
  456. * always performed on the text from this selection. nil corresponds to no selection. */
  457. - (void)setSelectedTextRange:(UITextRange *)aSelectedTextRange
  458. {
  459. CCLOG("UITextRange:setSelectedTextRange");
  460. }
  461. - (UITextRange *)selectedTextRange
  462. {
  463. return [[[UITextRange alloc] init] autorelease];
  464. }
  465. #pragma mark UITextInput - Replacing and Returning Text
  466. - (NSString *)textInRange:(UITextRange *)range
  467. {
  468. CCLOG("textInRange");
  469. return @"";
  470. }
  471. - (void)replaceRange:(UITextRange *)range withText:(NSString *)theText
  472. {
  473. CCLOG("replaceRange");
  474. }
  475. #pragma mark UITextInput - Working with Marked and Selected Text
  476. /* If text can be selected, it can be marked. Marked text represents provisionally
  477. * inserted text that has yet to be confirmed by the user. It requires unique visual
  478. * treatment in its display. If there is any marked text, the selection, whether a
  479. * caret or an extended range, always resides within.
  480. *
  481. * Setting marked text either replaces the existing marked text or, if none is present,
  482. * inserts it from the current selection. */
  483. - (void)setMarkedTextRange:(UITextRange *)markedTextRange
  484. {
  485. CCLOG("setMarkedTextRange");
  486. }
  487. - (UITextRange *)markedTextRange
  488. {
  489. CCLOG("markedTextRange");
  490. return nil; // Nil if no marked text.
  491. }
  492. - (void)setMarkedTextStyle:(NSDictionary *)markedTextStyle
  493. {
  494. CCLOG("setMarkedTextStyle");
  495. }
  496. - (NSDictionary *)markedTextStyle
  497. {
  498. CCLOG("markedTextStyle");
  499. return nil;
  500. }
  501. - (void)setMarkedText:(NSString *)markedText selectedRange:(NSRange)selectedRange
  502. {
  503. CCLOG("setMarkedText");
  504. if (markedText == markedText_) {
  505. return;
  506. }
  507. if (nil != markedText_) {
  508. [markedText_ release];
  509. }
  510. markedText_ = markedText;
  511. [markedText_ retain];
  512. }
  513. - (void)unmarkText
  514. {
  515. CCLOG("unmarkText");
  516. if (nil == markedText_)
  517. {
  518. return;
  519. }
  520. const char * pszText = [markedText_ cStringUsingEncoding:NSUTF8StringEncoding];
  521. cocos2d::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText));
  522. [markedText_ release];
  523. markedText_ = nil;
  524. }
  525. #pragma mark Methods for creating ranges and positions.
  526. - (UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition
  527. {
  528. CCLOG("textRangeFromPosition");
  529. return nil;
  530. }
  531. - (UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset
  532. {
  533. CCLOG("positionFromPosition");
  534. return nil;
  535. }
  536. - (UITextPosition *)positionFromPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction offset:(NSInteger)offset
  537. {
  538. CCLOG("positionFromPosition");
  539. return nil;
  540. }
  541. /* Simple evaluation of positions */
  542. - (NSComparisonResult)comparePosition:(UITextPosition *)position toPosition:(UITextPosition *)other
  543. {
  544. CCLOG("comparePosition");
  545. return (NSComparisonResult)0;
  546. }
  547. - (NSInteger)offsetFromPosition:(UITextPosition *)from toPosition:(UITextPosition *)toPosition
  548. {
  549. CCLOG("offsetFromPosition");
  550. return 0;
  551. }
  552. - (UITextPosition *)positionWithinRange:(UITextRange *)range farthestInDirection:(UITextLayoutDirection)direction
  553. {
  554. CCLOG("positionWithinRange");
  555. return nil;
  556. }
  557. - (UITextRange *)characterRangeByExtendingPosition:(UITextPosition *)position inDirection:(UITextLayoutDirection)direction
  558. {
  559. CCLOG("characterRangeByExtendingPosition");
  560. return nil;
  561. }
  562. #pragma mark Writing direction
  563. - (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
  564. {
  565. CCLOG("baseWritingDirectionForPosition");
  566. return UITextWritingDirectionNatural;
  567. }
  568. - (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range
  569. {
  570. CCLOG("setBaseWritingDirection");
  571. }
  572. #pragma mark Geometry
  573. /* Geometry used to provide, for example, a correction rect. */
  574. - (CGRect)firstRectForRange:(UITextRange *)range
  575. {
  576. CCLOG("firstRectForRange");
  577. return CGRectNull;
  578. }
  579. - (CGRect)caretRectForPosition:(UITextPosition *)position
  580. {
  581. CCLOG("caretRectForPosition");
  582. return caretRect_;
  583. }
  584. #pragma mark Hit testing
  585. /* JS - Find the closest position to a given point */
  586. - (UITextPosition *)closestPositionToPoint:(CGPoint)point
  587. {
  588. CCLOG("closestPositionToPoint");
  589. return nil;
  590. }
  591. - (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range
  592. {
  593. CCLOG("closestPositionToPoint");
  594. return nil;
  595. }
  596. - (UITextRange *)characterRangeAtPoint:(CGPoint)point
  597. {
  598. CCLOG("characterRangeAtPoint");
  599. return nil;
  600. }
  601. - (NSArray *)selectionRectsForRange:(UITextRange *)range
  602. {
  603. CCLOG("selectionRectsForRange");
  604. return nil;
  605. }
  606. #pragma mark - UIKeyboard notification
  607. #if !defined(CC_TARGET_OS_TVOS)
  608. - (void)onUIKeyboardNotification:(NSNotification *)notif
  609. {
  610. NSString * type = notif.name;
  611. NSDictionary* info = [notif userInfo];
  612. CGRect begin = [self convertRect:
  613. [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]
  614. fromView:self];
  615. CGRect end = [self convertRect:
  616. [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]
  617. fromView:self];
  618. double aniDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
  619. CGSize viewSize = self.frame.size;
  620. CGFloat tmp;
  621. switch (getFixedOrientation([[UIApplication sharedApplication] statusBarOrientation]))
  622. {
  623. case UIInterfaceOrientationPortrait:
  624. begin.origin.y = viewSize.height - begin.origin.y - begin.size.height;
  625. end.origin.y = viewSize.height - end.origin.y - end.size.height;
  626. break;
  627. case UIInterfaceOrientationPortraitUpsideDown:
  628. begin.origin.x = viewSize.width - (begin.origin.x + begin.size.width);
  629. end.origin.x = viewSize.width - (end.origin.x + end.size.width);
  630. break;
  631. case UIInterfaceOrientationLandscapeLeft:
  632. std::swap(begin.size.width, begin.size.height);
  633. std::swap(end.size.width, end.size.height);
  634. std::swap(viewSize.width, viewSize.height);
  635. tmp = begin.origin.x;
  636. begin.origin.x = begin.origin.y;
  637. begin.origin.y = viewSize.height - tmp - begin.size.height;
  638. tmp = end.origin.x;
  639. end.origin.x = end.origin.y;
  640. end.origin.y = viewSize.height - tmp - end.size.height;
  641. break;
  642. case UIInterfaceOrientationLandscapeRight:
  643. std::swap(begin.size.width, begin.size.height);
  644. std::swap(end.size.width, end.size.height);
  645. std::swap(viewSize.width, viewSize.height);
  646. tmp = begin.origin.x;
  647. begin.origin.x = begin.origin.y;
  648. begin.origin.y = tmp;
  649. tmp = end.origin.x;
  650. end.origin.x = end.origin.y;
  651. end.origin.y = tmp;
  652. break;
  653. default:
  654. break;
  655. }
  656. auto glview = cocos2d::Director::getInstance()->getOpenGLView();
  657. float scaleX = glview->getScaleX();
  658. float scaleY = glview->getScaleY();
  659. // Convert to pixel coordinate
  660. begin = CGRectApplyAffineTransform(begin, CGAffineTransformScale(CGAffineTransformIdentity, self.contentScaleFactor, self.contentScaleFactor));
  661. end = CGRectApplyAffineTransform(end, CGAffineTransformScale(CGAffineTransformIdentity, self.contentScaleFactor, self.contentScaleFactor));
  662. float offestY = glview->getViewPortRect().origin.y;
  663. if (offestY < 0.0f)
  664. {
  665. begin.origin.y += offestY;
  666. begin.size.height -= offestY;
  667. end.size.height -= offestY;
  668. }
  669. // Convert to design coordinate
  670. begin = CGRectApplyAffineTransform(begin, CGAffineTransformScale(CGAffineTransformIdentity, 1.0f/scaleX, 1.0f/scaleY));
  671. end = CGRectApplyAffineTransform(end, CGAffineTransformScale(CGAffineTransformIdentity, 1.0f/scaleX, 1.0f/scaleY));
  672. cocos2d::IMEKeyboardNotificationInfo notiInfo;
  673. notiInfo.begin = cocos2d::Rect(begin.origin.x,
  674. begin.origin.y,
  675. begin.size.width,
  676. begin.size.height);
  677. notiInfo.end = cocos2d::Rect(end.origin.x,
  678. end.origin.y,
  679. end.size.width,
  680. end.size.height);
  681. notiInfo.duration = (float)aniDuration;
  682. cocos2d::IMEDispatcher* dispatcher = cocos2d::IMEDispatcher::sharedDispatcher();
  683. if (UIKeyboardWillShowNotification == type)
  684. {
  685. self.keyboardShowNotification = notif; // implicit copy
  686. dispatcher->dispatchKeyboardWillShow(notiInfo);
  687. }
  688. else if (UIKeyboardDidShowNotification == type)
  689. {
  690. //CGSize screenSize = self.window.screen.bounds.size;
  691. dispatcher->dispatchKeyboardDidShow(notiInfo);
  692. caretRect_ = end;
  693. int fontSize = [UIFont smallSystemFontSize];
  694. caretRect_.origin.y = viewSize.height - (caretRect_.origin.y + caretRect_.size.height + fontSize);
  695. caretRect_.size.height = 0;
  696. isKeyboardShown_ = YES;
  697. }
  698. else if (UIKeyboardWillHideNotification == type)
  699. {
  700. dispatcher->dispatchKeyboardWillHide(notiInfo);
  701. }
  702. else if (UIKeyboardDidHideNotification == type)
  703. {
  704. caretRect_ = CGRectZero;
  705. dispatcher->dispatchKeyboardDidHide(notiInfo);
  706. isKeyboardShown_ = NO;
  707. }
  708. }
  709. #endif
  710. #if !defined(CC_TARGET_OS_TVOS)
  711. UIInterfaceOrientation getFixedOrientation(UIInterfaceOrientation statusBarOrientation)
  712. {
  713. if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
  714. {
  715. statusBarOrientation = UIInterfaceOrientationPortrait;
  716. }
  717. return statusBarOrientation;
  718. }
  719. #endif
  720. -(void) doAnimationWhenKeyboardMoveWithDuration:(float)duration distance:(float)dis
  721. {
  722. [UIView beginAnimations:nil context:nullptr];
  723. [UIView setAnimationDelegate:self];
  724. [UIView setAnimationDuration:duration];
  725. [UIView setAnimationBeginsFromCurrentState:YES];
  726. //NSLog(@"[animation] dis = %f, scale = %f \n", dis, cocos2d::GLView::getInstance()->getScaleY());
  727. if (dis < 0.0f) dis = 0.0f;
  728. auto glview = cocos2d::Director::getInstance()->getOpenGLView();
  729. dis *= glview->getScaleY();
  730. dis /= self.contentScaleFactor;
  731. #if defined(CC_TARGET_OS_TVOS)
  732. self.frame = CGRectMake(originalRect_.origin.x, originalRect_.origin.y - dis, originalRect_.size.width, originalRect_.size.height);
  733. #else
  734. switch (getFixedOrientation([[UIApplication sharedApplication] statusBarOrientation]))
  735. {
  736. case UIInterfaceOrientationPortrait:
  737. self.frame = CGRectMake(originalRect_.origin.x, originalRect_.origin.y - dis, originalRect_.size.width, originalRect_.size.height);
  738. break;
  739. case UIInterfaceOrientationPortraitUpsideDown:
  740. self.frame = CGRectMake(originalRect_.origin.x, originalRect_.origin.y + dis, originalRect_.size.width, originalRect_.size.height);
  741. break;
  742. case UIInterfaceOrientationLandscapeLeft:
  743. self.frame = CGRectMake(originalRect_.origin.x - dis, originalRect_.origin.y , originalRect_.size.width, originalRect_.size.height);
  744. break;
  745. case UIInterfaceOrientationLandscapeRight:
  746. self.frame = CGRectMake(originalRect_.origin.x + dis, originalRect_.origin.y , originalRect_.size.width, originalRect_.size.height);
  747. break;
  748. default:
  749. break;
  750. }
  751. #endif
  752. [UIView commitAnimations];
  753. }
  754. -(void) doAnimationWhenAnotherEditBeClicked
  755. {
  756. if (self.keyboardShowNotification != nil)
  757. {
  758. [[NSNotificationCenter defaultCenter]postNotification:self.keyboardShowNotification];
  759. }
  760. }
  761. @end
  762. #endif // CC_PLATFORM_IOS