I am getting some weird some weird behaviour with my code.
My bodies with the same MASK and CATEGORY when overlapping and touchDragged, recreate the previous mouseJoints.
//collision
final short CATEGORY_PLAYER = 0x0001; // 0000000000000001 in binary
final short CATEGORY_SCENERY = 0x0004; // 0000000000000100 in binary
final short MASK_PLAYER = CATEGORY_SCENERY; // or ~CATEGORY_PLAYER
short MASK_SCENERY = -1;
Here is my MouseJoing implementation:
/**
* Creates the MouseJoint definition.
*
* #param body
* First body of the joint (i.e. ground, walls, etc.)
*/
private void createMouseJointDefinition(Body body) {
mouseJointDef = new MouseJointDef();
mouseJointDef.bodyA = body;
mouseJointDef.collideConnected = false;
mouseJointDef.maxForce = 500;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
/*
* Define a new QueryCallback. This callback will be used in
* world.QueryAABB method.
*/
QueryCallback queryCallback = new QueryCallback() {
#Override
public boolean reportFixture(Fixture fixture) {
boolean testResult;
/*
* If the hit point is inside the fixture of the body, create a
* new MouseJoint.
*/
if (testResult = fixture.testPoint(touchPosition.x,
touchPosition.y)) {
mouseJointDef.bodyB = fixture.getBody();
mouseJointDef.target.set(touchPosition.x, touchPosition.y);
mouseJoint = (MouseJoint) world.createJoint(mouseJointDef);
}
return testResult;
}
};
/* Translate camera point to world point */
camera.unproject(touchPosition.set(screenX, screenY, 0));
/*
* Query the world for all fixtures that potentially overlap the touched
* point.
*/
world.QueryAABB(queryCallback, touchPosition.x, touchPosition.y,
touchPosition.x, touchPosition.y);
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
/* Whether the input was processed */
boolean processed = false;
/* If a MouseJoint is defined, destroy it */
if (mouseJoint != null) {
world.destroyJoint(mouseJoint);
mouseJoint = null;
processed = true;
}
return processed;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
/* Whether the input was processed */
boolean processed = false;
/*
* If a MouseJoint is defined, update its target with current position.
*/
if (mouseJoint != null) {
/* Translate camera point to world point */
camera.unproject(touchPosition.set(screenX, screenY, 0));
mouseJoint.setTarget(new Vector2(touchPosition.x, touchPosition.y));
}
return processed;
}
Thanks for your time....
Fixed by iterating all created jointsworld.getJoints(worldJoints);and destroying the old ones. .
Related
I am doing a sample on Map and in this i want to show marker along with text.
for that i used below code.
MapContainer mapContainer = new MapContainer("xxxxxxxxxxxxxxxxxxxxxx");
Coord coord = new Coord(latitude,longitude);
mapContainer.setCameraPosition(coord);
mapContainer.addMarker(EncodedImage.createFromImage(image,false), mapContainer.getCameraPosition(), "Text", "Text", null);
but this code helps me to displaying the marker but not along with the text. so if anyone have idea to display marker with text please suggest/help me to achieve this.
Thanks in Advance.
here is the code using MapContainer and MapLayout(Below Answer)..
if(BrowserComponent.isNativeBrowserSupported()) {
MapContainer mc = new MapContainer("AIzaSyDLIu4RfdXVQPvRqOYLP6N8ocCQpPNqtIk");
mapDemo.add(mc);
Container markers = new Container();
markers.setLayout(new MapLayout(mc, markers));
mapDemo.add(markers);
Coord moscone = new Coord(37.7831, -122.401558);
Button mosconeButton = new Button("");
FontImage.setMaterialIcon(mosconeButton, FontImage.MATERIAL_PLACE);
markers.add(moscone, mosconeButton);
Coord moscone1 = new Coord(36.6139, -120.2090);
Button mosconeButton1 = new Button("");
FontImage.setMaterialIcon(mosconeButton1, FontImage.MATERIAL_PLACE);
markers.add(moscone1, mosconeButton1);
mc.zoom(moscone1, 5);
} else {
// iOS Screenshot process...
mapDemo.add(new Label("Loading, please wait...."));
}
This is a revised answer see the original answer for reference below:
With the new update this should work better, you will need to update the cn1lib for Google Maps too if you have an older version. We've also revised the MapLayout class again and added some features such as alignment:
public class MapLayout extends Layout implements MapListener {
private static final String COORD_KEY = "$coord";
private static final String POINT_KEY = "$point";
private static final String HORIZONTAL_ALIGNMENT = "$align";
private static final String VERTICAL_ALIGNMENT = "$valign";
private final MapContainer map;
private final Container actual;
private boolean inUpdate;
private Runnable nextUpdate;
private int updateCounter;
public static enum HALIGN {
LEFT {
#Override
int convert(int x, int width) {
return x;
}
},
CENTER {
#Override
int convert(int x, int width) {
return x - width / 2;
}
},
RIGHT {
#Override
int convert(int x, int width) {
return x - width;
}
};
abstract int convert(int x, int width);
}
public static enum VALIGN {
TOP {
#Override
int convert(int y, int height) {
return y;
}
},
MIDDLE {
#Override
int convert(int y, int height) {
return y + height / 2;
}
},
BOTTOM {
#Override
int convert(int y, int height) {
return y + height;
}
};
abstract int convert(int y, int height);
}
public MapLayout(MapContainer map, Container actual) {
this.map = map;
this.actual = actual;
map.addMapListener(this);
}
#Override
public void addLayoutComponent(Object value, Component comp, Container c) {
comp.putClientProperty(COORD_KEY, (Coord) value);
}
#Override
public boolean isConstraintTracking() {
return true;
}
#Override
public Object getComponentConstraint(Component comp) {
return comp.getClientProperty(COORD_KEY);
}
#Override
public boolean isOverlapSupported() {
return true;
}
public static void setHorizontalAlignment(Component cmp, HALIGN a) {
cmp.putClientProperty(HORIZONTAL_ALIGNMENT, a);
}
public static void setVerticalAlignment(Component cmp, VALIGN a) {
cmp.putClientProperty(VERTICAL_ALIGNMENT, a);
}
#Override
public void layoutContainer(Container parent) {
int parentX = 0;
int parentY = 0;
for (Component current : parent) {
Coord crd = (Coord) current.getClientProperty(COORD_KEY);
Point p = (Point) current.getClientProperty(POINT_KEY);
if (p == null) {
p = map.getScreenCoordinate(crd);
current.putClientProperty(POINT_KEY, p);
}
HALIGN h = (HALIGN)current.getClientProperty(HORIZONTAL_ALIGNMENT);
if(h == null) {
h = HALIGN.LEFT;
}
VALIGN v = (VALIGN)current.getClientProperty(VERTICAL_ALIGNMENT);
if(v == null) {
v = VALIGN.TOP;
}
current.setSize(current.getPreferredSize());
current.setX(h.convert(p.getX() - parentX, current.getWidth()));
current.setY(v.convert(p.getY() - parentY, current.getHeight()));
}
}
#Override
public Dimension getPreferredSize(Container parent) {
return new Dimension(100, 100);
}
#Override
public void mapPositionUpdated(Component source, int zoom, Coord center) {
Runnable r = new Runnable() {
public void run() {
inUpdate = true;
try {
List<Coord> coords = new ArrayList<>();
List<Component> cmps = new ArrayList<>();
int len = actual.getComponentCount();
for (Component current : actual) {
Coord crd = (Coord) current.getClientProperty(COORD_KEY);
coords.add(crd);
cmps.add(current);
}
int startingUpdateCounter = ++updateCounter;
List<Point> points = map.getScreenCoordinates(coords);
if (startingUpdateCounter != updateCounter || len != points.size()) {
// Another update must have run while we were waiting for the bounding box.
// in which case, that update would be more recent than this one.
return;
}
for (int i=0; i<len; i++) {
Component current = cmps.get(i);
Point p = points.get(i);
current.putClientProperty(POINT_KEY, p);
}
actual.setShouldCalcPreferredSize(true);
actual.revalidate();
if (nextUpdate != null) {
Runnable nex = nextUpdate;
nextUpdate = null;
callSerially(nex);
}
} finally {
inUpdate = false;
}
}
};
if (inUpdate) {
nextUpdate = r;
} else {
nextUpdate = null;
callSerially(r);
}
}
}
Original Answer:
The marker will show the text when you tap on it. If you want things to appear differently you can just use any component and place it on top of the map. The upcoming Uber tutorial will cover this in depth but I explained the basic system in this blog post: https://www.codenameone.com/blog/tip-map-layout-manager.html
So hi to #ll this is my fist post/question on stackoverflow :D
I need help # following :
So i integrated the Facebook SDk sucessfully in my game but i´dont get the profile picture working ...
So i tryied it oldshool on Facebooks "Tutotial" Way and followed all steps to implement login functions and so on ...
I´ve downloaded the "friendsmash_start" Sample and implemented that Stuff ...
My Main Problem is i don´t get ahead with this problem and can´t figure out what i´m doing wrong so i´m hoping for help.
Here´s the complete Code from the MainMenu Script from the sample which is the only i´ve changed ... like in the tutorial ...
Unity shows me this Error -> "The name 'LoadPicture' does not exist in the current context ... so the errors are on these two parts of code :
"LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);" in the "OnLoggedIn" function
"LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);" in the "MyPictureCallback" function
I don´t understand it cause i searched myself in the script for this function "LoadPicture" and find nothing that was ... according to the "Tutorial" of facebook here :
https://developers.facebook.com/docs/games/unity/unity-tutorial?locale=de_DE
the function should be there cause they wrote there :
"Take a look at the LoadPicture method also in MainMenu.cs to see how we use the Unity WWW class to load the image returned by the graph API."
But i can´t find it :(
HOPE SOMEONE CAN HELP ME I DON´T GET IT ...
Have that problem unfortunately very long time ... thats enoying. :(
HERE`S THE FULL CODE OF MAINMENU.CS :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Facebook.MiniJSON;
using System;
public class MainMenu : MonoBehaviour
{
// Inspector tunable members //
public Texture ButtonTexture;
public Texture PlayTexture; // Texture for main menu button icons
public Texture BragTexture;
public Texture ChallengeTexture;
public Texture StoreTexture;
public Texture FullScreenTexture;
public Texture FullScreenActiveTexture;
public Texture ResourcesTexture;
public Vector2 CanvasSize; // size of window on canvas
public Rect LoginButtonRect; // Position of login button
public Vector2 ResourcePos; // position of resource indicators (not used yet)
public Vector2 ButtonStartPos; // position of first button in main menu
public float ButtonScale; // size of main menu buttons
public float ButtonYGap; // gap between buttons in main menu
public float ChallengeDisplayTime; // Number of seconds the request sent message is displayed for
public Vector2 ButtonLogoOffset; // Offset determining positioning of logo on buttons
public float TournamentStep; // Spacing between tournament entries
public float MouseScrollStep = 40; // Amount score table moves with each step of the mouse wheel
public PaymentDialog paymentDialog;
public GUISkin MenuSkin;
public int CoinBalance;
public int NumLives;
public int NumBombs;
public Texture[] CelebTextures;
public string [] CelebNames;
// Private members //
private static MainMenu instance;
private static List<object> friends = null;
private static Dictionary<string, string> profile = null;
private static List<object> scores = null;
private static Dictionary<string, Texture> friendImages = new Dictionary<string, Texture>();
private Vector2 scrollPosition = Vector2.zero;
private bool haveUserPicture = false;
private float tournamentLength = 0;
private int tournamentWidth = 512;
private int mainMenuLevel = 0; // Level index of main menu
private string popupMessage;
private float popupTime;
private float popupDuration;
void Awake()
{
Util.Log("Awake");
paymentDialog = ((PaymentDialog)(GetComponent("PaymentDialog")));
// allow only one instance of the Main Menu
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
#if UNITY_WEBPLAYER
// Execute javascript in iframe to keep the player centred
string javaScript = #"
window.onresize = function() {
var unity = UnityObject2.instances[0].getUnity();
var unityDiv = document.getElementById(""unityPlayerEmbed"");
var width = window.innerWidth;
var height = window.innerHeight;
var appWidth = " + CanvasSize.x + #";
var appHeight = " + CanvasSize.y + #";
unity.style.width = appWidth + ""px"";
unity.style.height = appHeight + ""px"";
unityDiv.style.marginLeft = (width - appWidth)/2 + ""px"";
unityDiv.style.marginTop = (height - appHeight)/2 + ""px"";
unityDiv.style.marginRight = (width - appWidth)/2 + ""px"";
unityDiv.style.marginBottom = (height - appHeight)/2 + ""px"";
}
window.onresize(); // force it to resize now";
Application.ExternalCall(javaScript);
#endif
DontDestroyOnLoad(gameObject);
instance = this;
// Initialize FB SDK
FB.Init(SetInit, OnHideUnity);
}
private void SetInit()
{
Util.Log("SetInit");
enabled = true; // "enabled" is a property inherited from MonoBehaviour
if (FB.IsLoggedIn)
{
Util.Log("Already logged in");
OnLoggedIn();
}
}
private void OnHideUnity(bool isGameShown)
{
Util.Log("OnHideUnity");
if (!isGameShown)
{
// pause the game - we will need to hide
Time.timeScale = 0;
}
else
{
// start the game back up - we're getting focus again
Time.timeScale = 1;
}
}
private void QueryScores()
{
FB.API("/app/scores?fields=score,user.limit(20)", Facebook.HttpMethod.GET, ScoresCallback);
}
private int getScoreFromEntry(object obj)
{
Dictionary<string,object> entry = (Dictionary<string,object>) obj;
return Convert.ToInt32(entry["score"]);
}
void ScoresCallback(FBResult result)
{
Util.Log("ScoresCallback");
if (result.Error != null)
{
Util.LogError(result.Error);
return;
}
scores = new List<object>();
List<object> scoresList = Util.DeserializeScores(result.Text);
foreach(object score in scoresList)
{
var entry = (Dictionary<string,object>) score;
var user = (Dictionary<string,object>) entry["user"];
string userId = (string)user["id"];
if (string.Equals(userId,FB.UserId))
{
// This entry is the current player
int playerHighScore = getScoreFromEntry(entry);
Util.Log("Local players score on server is " + playerHighScore);
if (playerHighScore < GameStateManager.Score)
{
Util.Log("Locally overriding with just acquired score: " + GameStateManager.Score);
playerHighScore = GameStateManager.Score;
}
entry["score"] = playerHighScore.ToString();
GameStateManager.HighScore = playerHighScore;
}
scores.Add(entry);
if (!friendImages.ContainsKey(userId))
{
// We don't have this players image yet, request it now
LoadPictureAPI(Util.GetPictureURL(userId, 128, 128),pictureTexture =>
{
if (pictureTexture != null)
{
friendImages.Add(userId, pictureTexture);
}
});
}
}
// Now sort the entries based on score
scores.Sort(delegate(object firstObj,
object secondObj)
{
return -getScoreFromEntry(firstObj).CompareTo(getScoreFromEntry(secondObj));
}
);
}
void OnApplicationFocus( bool hasFocus )
{
Util.Log ("hasFocus " + (hasFocus ? "Y" : "N"));
}
// Convenience function to check if mouse/touch is the tournament area
private bool IsInTournamentArea (Vector2 p)
{
return p.x > Screen.width-tournamentWidth;
}
// Scroll the tournament view by some delta
private void ScrollTournament(float delta)
{
scrollPosition.y += delta;
if (scrollPosition.y > tournamentLength - Screen.height)
scrollPosition.y = tournamentLength - Screen.height;
if (scrollPosition.y < 0)
scrollPosition.y = 0;
}
// variables for keeping track of scrolling
private Vector2 mouseLastPos;
private bool mouseDragging = false;
void Update()
{
if(Input.touches.Length > 0)
{
Touch touch = Input.touches[0];
if (IsInTournamentArea (touch.position) && touch.phase == TouchPhase.Moved)
{
// dragging
ScrollTournament (touch.deltaPosition.y*3);
}
}
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
ScrollTournament (MouseScrollStep);
}
else if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
ScrollTournament (-MouseScrollStep);
}
if (Input.GetMouseButton(0) && IsInTournamentArea(Input.mousePosition))
{
if (mouseDragging)
{
ScrollTournament (Input.mousePosition.y - mouseLastPos.y);
}
mouseLastPos = Input.mousePosition;
mouseDragging = true;
}
else
mouseDragging = false;
}
// Button drawing logic //
private Vector2 buttonPos; // Keeps track of where we've got to on the screen as we draw buttons
private void BeginButtons()
{
// start drawing buttons at the chosen start position
buttonPos = ButtonStartPos;
}
private bool DrawButton(string text, Texture texture)
{
// draw a single button and update our position
bool result = GUI.Button(new Rect (buttonPos.x,buttonPos.y, ButtonTexture.width * ButtonScale, ButtonTexture.height * ButtonScale),text,MenuSkin.GetStyle("menu_button"));
Util.DrawActualSizeTexture(ButtonLogoOffset*ButtonScale+buttonPos,texture,ButtonScale);
buttonPos.y += ButtonTexture.height*ButtonScale + ButtonYGap;
if (paymentDialog.DialogEnabled)
result = false;
return result;
}
void OnGUI()
{
GUI.skin = MenuSkin;
if (Application.loadedLevel != mainMenuLevel) return; // don't display anything except when in main menu
GUILayout.Box("", MenuSkin.GetStyle("panel_welcome"));
if (!FB.IsLoggedIn)
{
GUI.Label((new Rect(179, 11, 287, 160)), "Login to Facebook", MenuSkin.GetStyle("text_only"));
if (GUI.Button(LoginButtonRect, "", MenuSkin.GetStyle("button_login")))
{
FB.Login("email,publish_actions", LoginCallback);
}
}
if (FB.IsLoggedIn)
{
string panelText = "Welcome ";
panelText += (!string.IsNullOrEmpty(GameStateManager.Username)) ? string.Format("{0}!", GameStateManager.Username) : "Smasher!";
if (GameStateManager.UserTexture != null)
GUI.DrawTexture( (new Rect(8,10, 150, 150)), GameStateManager.UserTexture);
GUI.Label( (new Rect(179 , 11, 287, 160)), panelText, MenuSkin.GetStyle("text_only"));
}
string subTitle = "Let's smash some friends!";
if (GameStateManager.Score > 0)
{
subTitle = "Score: " + GameStateManager.Score.ToString();
}
if (!string.IsNullOrEmpty(subTitle))
{
GUI.Label( (new Rect(132, 28, 400, 160)), subTitle, MenuSkin.GetStyle("sub_title"));
}
BeginButtons();
if (DrawButton("Play",PlayTexture))
{
onPlayClicked();
}
if (FB.IsLoggedIn)
{
// Draw resources bar
Util.DrawActualSizeTexture(ResourcePos,ResourcesTexture);
Util.DrawSimpleText(ResourcePos + new Vector2(47,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",CoinBalance));
Util.DrawSimpleText(ResourcePos + new Vector2(137,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",NumBombs));
Util.DrawSimpleText(ResourcePos + new Vector2(227,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",NumLives));
}
#if UNITY_WEBPLAYER
if (Screen.fullScreen)
{
if (DrawButton("Full Screen",FullScreenActiveTexture))
SetFullscreenMode(false);
}
else
{
if (DrawButton("Full Screen",FullScreenTexture))
SetFullscreenMode(true);
}
#endif
DrawPopupMessage();
}
public void AddPopupMessage(string message, float duration)
{
popupMessage = message;
popupTime = Time.realtimeSinceStartup;
popupDuration = duration;
}
public void DrawPopupMessage()
{
if (popupTime != 0 && popupTime + popupDuration > Time.realtimeSinceStartup)
{
// Show message that we sent a request
Rect PopupRect = new Rect();
PopupRect.width = 800;
PopupRect.height = 100;
PopupRect.x = Screen.width / 2 - PopupRect.width / 2;
PopupRect.y = Screen.height / 2 - PopupRect.height / 2;
GUI.Box(PopupRect,"",MenuSkin.GetStyle("box"));
GUI.Label(PopupRect, popupMessage, MenuSkin.GetStyle("centred_text"));
}
}
void TournamentGui()
{
GUILayout.BeginArea(new Rect((Screen.width - 450),0,450,Screen.height));
// Title box
GUI.Box (new Rect(0, - scrollPosition.y, 100,200), "", MenuSkin.GetStyle("tournament_bar"));
GUI.Label (new Rect(121 , - scrollPosition.y, 100,200), "Tournament", MenuSkin.GetStyle("heading"));
Rect boxRect = new Rect();
if(scores != null)
{
var x = 0;
foreach(object scoreEntry in scores)
{
Dictionary<string,object> entry = (Dictionary<string,object>) scoreEntry;
Dictionary<string,object> user = (Dictionary<string,object>) entry["user"];
string name = ((string) user["name"]).Split(new char[]{' '})[0] + "\n";
string score = "Smashed: " + entry["score"];
boxRect = new Rect(0, 121+(TournamentStep*x)-scrollPosition.y , 100,128);
// Background box
GUI.Box(boxRect,"",MenuSkin.GetStyle("tournament_entry"));
// Text
GUI.Label (new Rect(24, 136 + (TournamentStep * x) - scrollPosition.y, 100,128), (x+1)+".", MenuSkin.GetStyle("tournament_position")); // Rank e.g. "1.""
GUI.Label (new Rect(250,145 + (TournamentStep * x) - scrollPosition.y, 300,100), name, MenuSkin.GetStyle("tournament_name")); // name
GUI.Label (new Rect(250,193 + (TournamentStep * x) - scrollPosition.y, 300,50), score, MenuSkin.GetStyle("tournament_score")); // score
Texture picture;
if (friendImages.TryGetValue((string) user["id"], out picture))
{
GUI.DrawTexture(new Rect(118,128+(TournamentStep*x)-scrollPosition.y,115,115), picture); // Profile picture
}
x++;
}
}
else GUI.Label (new Rect(180,270,512,200), "Loading...", MenuSkin.GetStyle("text_only"));
// Record length so we know how far we can scroll to
tournamentLength = boxRect.y + boxRect.height + scrollPosition.y;
GUILayout.EndArea();
}
// React to menu buttons //
private void onPlayClicked()
{
Util.Log("onPlayClicked");
if (friends != null && friends.Count > 0)
{
// Select a random friend and get their picture
Dictionary<string, string> friend = Util.RandomFriend(friends);
GameStateManager.FriendName = friend["first_name"];
GameStateManager.FriendID = friend["id"];
GameStateManager.CelebFriend = -1;
LoadPictureURL(friend["image_url"],FriendPictureCallback);
}
else
{
//We can't access friends
GameStateManager.CelebFriend = UnityEngine.Random.Range(0,CelebTextures.Length - 1);
GameStateManager.FriendName = CelebNames[GameStateManager.CelebFriend];
}
// Start the main game
Application.LoadLevel("GameStage");
GameStateManager.Instance.StartGame();
}
public void SetFullscreenMode (bool on)
{
if (on)
{
Screen.SetResolution (Screen.currentResolution.width, Screen.currentResolution.height, true);
}
else
{
Screen.SetResolution ((int)CanvasSize.x, (int)CanvasSize.y, false);
}
}
public static void FriendPictureCallback(Texture texture)
{
GameStateManager.FriendTexture = texture;
}
delegate void LoadPictureCallback (Texture texture);
IEnumerator LoadPictureEnumerator(string url, LoadPictureCallback callback)
{
WWW www = new WWW(url);
yield return www;
callback(www.texture);
}
void LoadPictureAPI (string url, LoadPictureCallback callback)
{
FB.API(url,Facebook.HttpMethod.GET,result =>
{
if (result.Error != null)
{
Util.LogError(result.Error);
return;
}
var imageUrl = Util.DeserializePictureURLString(result.Text);
StartCoroutine(LoadPictureEnumerator(imageUrl,callback));
});
}
void LoadPictureURL (string url, LoadPictureCallback callback)
{
StartCoroutine(LoadPictureEnumerator(url,callback));
}
void LoginCallback(FBResult result)
{
Util.Log("LoginCallback");
if (FB.IsLoggedIn)
{
OnLoggedIn();
}
}
void OnLoggedIn()
{
Util.Log("Logged in. ID: " + FB.UserId);
// Reqest player info and profile picture
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, APICallback);
LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);
}
void APICallback(FBResult result)
{
Util.Log("APICallback");
if (result.Error != null)
{
Util.LogError(result.Error);
// Let's just try again
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, APICallback);
return;
}
profile = Util.DeserializeJSONProfile(result.Text);
GameStateManager.Username = profile["first_name"];
friends = Util.DeserializeJSONFriends(result.Text);
}
void MyPictureCallback(Texture texture)
{
Util.Log("MyPictureCallback");
if (texture == null)
{
// Let's just try again
LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);
return;`
}
GameStateManager.UserTexture = texture;
}
}
change the word "LoadPicture" for "LoadPictureAPI".
For reference see:
https://github.com/fbsamples/friendsmash-unity/blob/master/friendsmash_payments_start/Assets/Scripts/MainMenu.cs
I used setString but the string is not updated, so I have to write a CCLabel to show the string, which I feel very weird because showing the user input should be part of the textfield.. Do I missed anything?
I read the test_input example, it uses a CCLabel to show the user input, which I think is a really bad design.
You don't need a Label to show user input.
I have edited the default HelloWorld file with added CCTextFieldttf working example.
This is how your HelloWorld.h file should look
class HelloWorld : public cocos2d::CCLayer, public cocos2d::CCTextFieldDelegate
{
public:
virtual bool init();
static cocos2d::CCScene* scene();
void createTF();
cocos2d::CCTextFieldTTF* tf;
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
virtual void registerWithTouchDispatcher();
//CCtextFieldttf delegate begin
virtual bool onTextFieldAttachWithIME(CCTextFieldTTF * pSender);
virtual bool onTextFieldDetachWithIME(CCTextFieldTTF * pSender);
virtual bool onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen);
virtual bool onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen);
virtual bool onDraw(CCTextFieldTTF * pSender);
//CCtextFieldttf delegate end
CREATE_FUNC(HelloWorld);
};
This is how your HelloWorld.cpp should be for minimum usage of CCTextFieldttf
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
if ( !CCLayer::init() )
{
return false;
}
this->setTouchEnabled(true);
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
createTF();
CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
// position the label on the center of the screen
pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - pLabel->getContentSize().height));
this->addChild(pLabel, 1);
return true;
}
void HelloWorld::createTF()
{
tf = CCTextFieldTTF::textFieldWithPlaceHolder("123", CCSizeMake(100, 100), kCCTextAlignmentCenter, "helvetica", 20);
tf->setColorSpaceHolder(ccWHITE);
tf->setPosition(ccp(200,200));
tf->setHorizontalAlignment(kCCTextAlignmentCenter);
tf->setVerticalAlignment(kCCVerticalTextAlignmentCenter);
tf->setDelegate(this);
addChild(tf);
}
void HelloWorld::registerWithTouchDispatcher()
{
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, false);
}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
CCLog("inside touchbegan");
return true;
}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
CCLog("inside touchend");
tf->attachWithIME();
}
bool HelloWorld::onTextFieldAttachWithIME(CCTextFieldTTF * pSender)
{
return false;
}
bool HelloWorld::onTextFieldDetachWithIME(CCTextFieldTTF * pSender)
{
return false;
}
bool HelloWorld::onTextFieldInsertText(CCTextFieldTTF * pSender, const char * text, int nLen)
{
return false;
}
bool HelloWorld::onTextFieldDeleteBackward(CCTextFieldTTF * pSender, const char * delText, int nLen)
{
return false;
}
bool HelloWorld::onDraw(CCTextFieldTTF * pSender)
{
return false;
}
The CCTextFieldDelegate methods are implemented to gain more control over what is entered into CCTextFieldTTF. The only thing that CCTextFieldttf lacks is you have to call CCTextFieldTTF's attachWithIME() method yourself like in the above code it is being called in "ccTouchEnded".
in header
class CustomMultiplayerScene : public PZGBaseMenuScene,public CCIMEDelegate
{
public:
void keyboardWillShow(cocos2d::CCIMEKeyboardNotificationInfo &info);
void keyboardWillHide(cocos2d::CCIMEKeyboardNotificationInfo &info);
void ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent);
};
in .cpp
CCTextFieldTTF *textfield = CCTextFieldTTF::textFieldWithPlaceHolder("Enter Name:", CCSize(480,30), kCCTextAlignmentCenter, "Arial", 12);
// textfield->setAnchorPoint(CCPointZero);
textfield->setPosition(ccp(screenSize.width/2,200));
textfield->setTag(100);
this->addChild(textfield,4);
CCLabelTTF *label = CCLabelTTF::create("ID : ", "", 12);
label->setPosition(ccp(screenSize.width/2,100));
label->setTag(200);
this->addChild(label,4);
implement methods in .cpp
void CustomMultiplayerScene::keyboardWillShow(CCIMEKeyboardNotificationInfo &info)
{
CCLOG("keyboardWillShow");
CCTextFieldTTF *textfield = (CCTextFieldTTF *)this->getChildByTag(100);
textfield->setString("");
}
void CustomMultiplayerScene::keyboardWillHide(CCIMEKeyboardNotificationInfo &info)
{
CCLog("keyboardWillHide");
CCTextFieldTTF *textfield = (CCTextFieldTTF *)this->getChildByTag(100);
CCLabelTTF *label = (CCLabelTTF *)this->getChildByTag(200);
label->setString(textfield->getString());
}
void CustomMultiplayerScene::ccTouchesBegan(cocos2d::CCSet *pTouches, cocos2d::CCEvent *pEvent)
{
CCTouch *pTouch = (CCTouch *)pTouches->anyObject();
CCPoint point = pTouch->getLocationInView();
point = CCDirector::sharedDirector()->convertToGL(point);
CCTextFieldTTF *textfield = (CCTextFieldTTF *)this->getChildByTag(100);
CCRect rect = textfield->boundingBox();
if(rect.containsPoint(point)) {
textfield->attachWithIME();
}
}
CCTextFieldTTF * pTextField = CCTextFieldTTF::textFieldWithPlaceHolder("click here for input",
"Thonburi",
20);
addChild(pTextField);
So, I'm able to load images into my JTable's cells now, but for some reason the graphics are all shifted to the right by one pixel, allowing me to see the JTable's background. Any ideas? Sorry if my formatting's off; still not entirely used to this markup.
public static void main(String[] args) {
final int rows = 16;
final int columns = 16;
final int dimTile = 32;
JFrame frame = new JFrame("test");
JTable table = new JTable(rows, columns);
table.setIntercellSpacing(new Dimension(0, 0));
table.setShowGrid(false);
table.setBackground(Color.cyan);
table.setTableHeader(null);
table.setRowHeight(dimTile);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setPreferredSize(new Dimension(rows * dimTile, columns * dimTile));
Tile tile = new Tile(0);
for(int i = 0; i < rows; i++) {
for(int j = 0; j < columns; j++) {
table.getColumnModel().getColumn(j).setCellRenderer(new MyRenderer());
table.setValueAy(tile, i, j);
}
}
JScrollPane scrollPane = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(BorderFactory.createEmptyBorder());
frame.getContentPane().add(scrollPane);
frame.setSize(512, 512);
frame.setVisible(true);
int adjustedSizeX = frame.getInsets().left + frame.getInsets().right + 512;
int adjustedSizeY = frame.getInsets().top + frame.getInsets().bottom + 512;
frame.setSize(adjustedSizeX, adjustedSizeY);
frame.pack();
...
}
public class MyRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Tile tile = (Tile) value;
setIcon(tile.getIcon());
return this;
}
}
public class Tile {
ImageIcon icon;
public Tile(int graphic) {
icon = new ImageIcon(PATH/TO/"...test.png");
}
public ImageIcon getIcon() {
return icon;
}
}
Not entirely sure what you mean by "one pixel off" - but achieve zero intercell spacing without any visual artefacts you have to both zero the margins and turn off the grid lines:
table.setIntercellSpacing(new Dimension(0, 0));
table.setShowGrid(false)
Edit
Okay, looking closer, there are several issues with your code
you do the column sizing indirectly instead of directly (and yet another nice example why to never-ever do a component.setPreferredSize :-)
the renderer's border takes some size
to fix the first, configure each column's width, table layout will automagically configure its itself
final int rows = 16;
final int columns = 16;
Tile tile = new Tile(0);
int tileHeight = tile.getIcon().getIconHeight();
int tileWidth = tile.getIcon().getIconWidth();
JTable table = new JTable(rows, columns);
// remove all margin
table.setIntercellSpacing(new Dimension(0, 0));
table.setShowGrid(false);
table.setTableHeader(null);
// set the rowHeight
table.setRowHeight(tileHeight);
// turn off auto-resize
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// configure each column with renderer and prefWidth
for (int j = 0; j < columns; j++) {
TableColumn column = table.getColumnModel().getColumn(j);
column.setCellRenderer(new MyRenderer());
column.setPreferredWidth(tileWidth);
}
for the second, null the border in each call:
public static class MyRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
setBorder(null);
Tile tile = (Tile) value;
setIcon(tile.getIcon());
return this;
}
}
I am having trouble implementing a custom cell renderer which will wrap message content when it extends past one line in length. The following is what I have:
public class MessageTable extends JTable
{
private static MessageTable messageTable;
private DefaultTableModel model = new DefaultTableModel();
private String[] emptyData = {};
private TreeMap<Integer, String> messages = null;
public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
this.setText((String)value);
this.setWrapStyleWord(true);
this.setLineWrap(true);
this.setBackground(Color.YELLOW);
int fontHeight = this.getFontMetrics(this.getFont()).getHeight();
int textLength = this.getText().length();
int lines = textLength / this.getColumns() +1;//+1, because we need at least 1 row.
int height = fontHeight * lines;
table.setRowHeight(row, height);
return this;
}
}
public MessageTable()
{
super();
messageTable = this;
this.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
model.addColumn("Message Number", emptyData);
model.addColumn("Message Content", emptyData);
this.setModel(model);
this.setFont(MappingView.theFont);
this.setDefaultRenderer(String.class, new LineWrapCellRenderer());
}
/**
* Set the current messages.
* #param messages
*/
public void setCurrentMessages(TreeMap<Integer, String> messages)
{
clearCurrentMessages();
this.messages = messages;
if (messages != null)
{
for (Integer key : messages.keySet())
{
String[] row = { key.toString(), messages.get(key).toString() };
model.addRow(row);
}
}
}
For some reason, the LineWrapCellRenderer is never used and the rows only ever contain one line of text.
What am I doing wrong?
Your cellrenderer is not used because the default table model returns Object.class for any column (it does not override AbstractTableModel's implementation):
public Class<?> getColumnClass(int columnIndex) {
return Object.class;
}
So either override the method yourself for the model or assign the renderer to Object.class.