Game Development Community

Display iPhone OS Keyboard - Solved

by Michael Perry · in iTorque 2D · 02/22/2009 (12:08 pm) · 60 replies

Hey everyone. So, while working with Ecliptic to get the camera/screenshot functionality of an iPhone into iTGB, I had to figure out how to send a message from iTGB to the iPhone SDK.

This is opposite of how input works, as the iPhone SDK detects a touch, creates a TGB mouse event, and sends that to the TGB system.

Fortunately, I have an iTGE demo that does just that! When the user clicks on a text edit control, the iPhone OS keyboard pops up. I had to start digging through the code, and found wrapper that performs this functionality.
#21
02/23/2009 (10:22 am)
Make these changes to the TextEntryController.mm to get it to auto update the keyboards position for you. You might have to creat another layout of your xib file. This works and is tested.

#import "TextEntryController.h"


@implementation TextEntryController

@synthesize textField;
@synthesize finished;
@synthesize userCanceled;

- (void)dealloc
{
	[textField release];
    [super dealloc];
}

- (IBAction)onCancelClicked: (id)sender
{
	userCanceled = true;
	finished = true;
}

- (IBAction)onCommitClicked: (id)sender
{
	finished = true;
}

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
	return YES;
}


@end

Let me know what you come up with. I have a iPhone I can test the results with. I just need to pay the $99 when ever Apple gets with me. I have been waiting for awhile now, maybe I should call them today.

*Edit*

I have created a xib file for you guys that will rotate and work properly with the above code. I am uploading it now.. Wait for the next post!
#22
02/23/2009 (10:51 am)
Ok the file you guys need is this one here Click Here to download TextEntry.zip


You need to go to your Xcode project and add a folder named UI and add this file to it. Then add it to your project underneath Resources along with your iTGB game. All credit is due to Michael for this!

Have fun with the keyboad guys!
Dane
#23
02/23/2009 (11:07 am)
*Correction* - 3 way split of credit for you (inspiration, collaboration), me (porting, weekend support), and the iTorque devs (actual code to make it happen) =)

All in all, glad we have this up and running.
#24
02/23/2009 (11:18 am)
This is definitely a nice asset to have for users who need a keyboard for their application! The great thing is that it supports either landscape or potrait mode due to its ability to rotate. So you have a perfect setup for whatever you need!

I might have to play around with adding some keyboard functions in my game now =).
#25
02/23/2009 (8:06 pm)
Hey Michael. I am just messing with the keyboard some more... It looks like when you open the keyboard and cancel, then reopen again the xib loads differently.. If you rotate the phone it will then fix itself. Are you experience this as well?

Also I can not get the function to return a text string to my variable. Let me know if you had a chance to play around with it any more.

Thanks
:)
#26
02/28/2009 (12:07 pm)
@Ecliptic - Can you debug the engine and set a break point in the ConsoleFunction you are using?

Check the value that char* ret before it gets returned: return ret;

That way we can see what the data is, which will help us isolate the problem.
#27
02/28/2009 (1:55 pm)
Ok, I will look into this in a bit. I just got back from running some errands. I set up a textGUI to be replaced with the returned value but it looks to be giving me an object ID(1003) instead of a text entry. So I will see what is being stored.
#28
02/28/2009 (2:49 pm)
When returning a value from a conSolefunction it's best to mak a buffer to put in using Con::getReturnBuffer( size ), otherwise your data can get trounced and whatever Torque uses that data for next will still be there when you check it in script.
#29
02/28/2009 (3:38 pm)
Right now I have the
char *ret = Con::getReturnBuffer(mTextBuffer.length()

Will this not work?
#30
02/28/2009 (6:34 pm)
That should get the right buffer, and as long as you copy the mTextBuffer data to ret it should work.
#31
02/28/2009 (9:39 pm)
Well placing a breakpoint before the char *ret it shows ret as not set yet, then when I step through it puts ret value of 0x180c000 Summary = 1302. 1302 is what is returned to the GUI i set in my scene.

I thought it might have been our commit and cancel area of code since it might not have known how to handle the return based on those options but I can see the commit section of code looks fine and weither I commit or cancel I get the same returned results.

Any luck on your end?
#32
03/01/2009 (11:55 am)
OK. I made a couple bonehead mistake about variable usage here.

As Mat pointed out, I never provide the functionality to copy the mTextBuffer data into our returning char* ret.

In Torque, we are usually working with StringTableEntry variables or straight char* declarations. I do not have much experience working with the StringBuffer class, but you cannot perform a standard string copy thoughtlessly.

Let's take another look at how GuiTextEditCtrl grabs the text data and uses it:

if (TextEntry::getUserText(mTextBuffer))
{
	Parent::setText(mTextBuffer.getPtr8());
	mCursorPos = mTextBuffer.length();   
}

We know this works, but how? Let's jump to the setText definition:
void GuiTextCtrl::setText(const char *txt)
{
   //make sure we don't call this before onAdd();

   if( !mProfile )
      return;

   if (txt)
      dStrncpy(mText, (UTF8*)txt, MAX_STRING_LENGTH);

   mText[MAX_STRING_LENGTH] = '[[62881d4568fb0]]';

So the function does take in a const char*. StringBuffer::getPtr8() returns a const UTF8*. UTF8 is just a char.

Our new ConsoleFuntion should look like this:
ConsoleFunction(getiPhoneKeyboardInput, const char *, 1, 1, "getiPhoneKeyboardInput() "
"Returns a string of text from the iPhone OS keyboard")
{
    argc;
	
    StringBuffer mTextBuffer;

    TextEntry::getUserText(mTextBuffer);

    char *ret = Con::getReturnBuffer(mTextBuffer.length());

    dStrcpy(ret, mTextBuffer.getPtr8());

    return ret;
}

Of course, we want to perform a safety check to make sure the user typed something in, and we are not copying bad data into our pointer. Still, that is how we get the actual string from our StringBuffer variable.
#33
03/01/2009 (12:10 pm)
Now, if we want to test this (which I'm doing now):

function echoKeyboardEntry()
{
   %keyboardEntry = getiPhoneKeyboardInput();
   
   keyboardButtonToggle.setText(%keyboardEntry);
   
   echo(%keyboardEntry);
}

keyboardButtonToggle is a new control I've added to mainScreenGui. Here is that entire file:

%guiContent = new GuiControl(mainScreenGui) {
   canSaveDynamicFields = "0";
   isContainer = "1";
   Profile = "GuiBlackContentProfile";
   HorizSizing = "width";
   VertSizing = "height";
   Position = "0 0";
   Extent = "640 480";
   MinExtent = "8 8";
   canSave = "1";
   Visible = "1";
   hovertime = "1000";

   new t2dSceneWindow(sceneWindow2d) {
      canSaveDynamicFields = "0";
      isContainer = "0";
      Profile = "GuiContentProfile";
      HorizSizing = "width";
      VertSizing = "height";
      Position = "0 0";
      Extent = "640 480";
      MinExtent = "8 8";
      canSave = "1";
      Visible = "1";
      hovertime = "1000";
      lockMouse = "0";
      useWindowMouseEvents = "1";
      useObjectMouseEvents = "1";
   };
   new GuiButtonCtrl(keyboardButtonToggle) {
      canSaveDynamicFields = "0";
      isContainer = "0";
      Profile = "GuiButtonProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      Position = "457 98";
      Extent = "140 30";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      Command = "echoKeyboardEntry();";
      hovertime = "1000";
      text = "Toggle Keyboard";
      groupNum = "-1";
      buttonType = "PushButton";
      useMouseEvents = "0";
   };
};

That version of the mainScreen.gui allows me to click on a button to toggle the keyboard. Since I cannot see my console, I set the button's text to what I enter. Testing now.

Edit - On a side note, Xcode message bubbles are annoying as Hell.
#34
03/01/2009 (12:12 pm)
Tested! Success!
#35
04/01/2009 (6:54 am)
Thanks, this is a major enhancement and I finally got it working :) Have you tried setting some kind of title on the TextEntry screen?
#36
04/01/2009 (7:58 am)
Well, adding a label and setting it from within the TextEntry:getUserText field wasn't that big a deal, now I need to figure out how to safely pass the actual string I really want to use.

[controller.screenLabel setText:@"Test Title"];
#37
04/01/2009 (9:24 am)
NM, Got it!
#38
06/15/2009 (1:33 pm)
I'm at work now with no access to iTGB... can anyone confirm that this is standardized in 1.2 or coming in 1.2.1? I tried to download Ecliptic's link for TextEntry.zip, but it's dead.
#39
06/21/2009 (11:18 am)
I just tried with iTGB 1.2. The change in the text edit control is absent and the TextEntry.xib is not added by default to the Xcode project, however it all works.
#40
06/24/2009 (8:31 am)
For those just jumping into the fray, can someone post a complete implementation in one post or resource? I'm staring at a bunch of bits of code here, some of which appear to be corrections of others, and many not specifically saying where to put the necessary changes.

Thanks in advance.