Drawing table borders in libgdx (Table.drawDebug()) - libgdx

I tried using this method to show debug lines:
table.debug();
Table.drawDebug(stage);
except Table.drawDebug expects a parameter of type: ShapeRenderer.
any direction would be great

You may just use a new ShapeRender() as parameter if your code doesn't contain one.

You don't need to call table.drawDebug(), just table.debug() is enough

I think you're looking for this?
Table table;
Stage stage;
public void show() {
table = new Table();
table.debug();
...
stage = new Stage(...);
stage.add(table);
}
public void render(float delta) {
Table.drawDebug(stage);
}
You debug draw the entire stage, but only the elements where debug() was called initially to mark them for debugging.
I hope this helps you.
P.S. btw this is from the official TableLayout docs here which is a must read if you're gonna mess around with Tables (if you haven't done so already).

Related

Is it possible in LibGDX's `scene2d` API to have the same Actor instance in multiple Stages?

I am making a program using the amazing libGDX+scene2d API and I structured it as follows:
I have a single MyGame instance, holding a single PolygonSpriteBatch instance.
There is an abstract MyScreen class, holding a MyStage class (see below)
Then there are lots of different screen classes that inherit from MyScreen, and instantiate each other at will.
(in all cases, removing the "My" gives you the name of the respective library class that it extends)
This model worked fine, until I encountered some problems to perform actions between screens using the Action system. I decided then that it would be a good idea to have a single OmnipresentActor belonging to MyGame that, as the name says, is present in every scene. So I modified MyStage to look more or less like this:
public class MyStage extends Stage {
public MyStage(MyGame g) {
super(new FitViewport(MyGame.WIDTH, MyGame.HEIGHT), g.batch);
addActor(game.omnipresentInvisibleActor);
}
#Override
public void clear() {
unfocusAll();
getRoot().clearActions();
getRoot().clearListeners();
removeActorsButNotListenersNorActions();
}
public void removeActorsButNotListenersNorActions() {
for (Actor a : getActors()) if (a.getClass()!= OmnipresentInvisibleActor.class) a.remove();
}
It followed a painful debugging phase, until I found out the following:
public PresentationScreen(MyGame g) {
// super() call and other irrelevant/already debugged code
System.out.println("PRINT_BEFORE: "+ stage.getActors().toString()); // OmnipresentActor is there
mainMenuScreen = new MainMenuScreen(game);
System.out.println("PRINT_AFTER: "+ stage.getActors().toString()); // OmnipresentActor is not there anymore, but was added to the mainMenuScreen
the "PRINT_BEFORE" statement shows that the stage holds the omnipresentActor. In "PRINT_AFTER" it isn't there anymore, whereas mainMenuScreen is indeed holding it. So my question, now more precise:
does scene2d prevent this to happen, or am I doing something wrong here?
Answers much appreciated! Cheers
An actor can only be a member of one stage: Thanks to #Tenfour04 for confirming that. The explanation is quite clear after doing a little research:
Stage.addActor() looks like this:
(here the github code of Stage.java)
/** Adds an actor to the root of the stage.
* #see Group#addActor(Actor) */
public void addActor (Actor actor) {
root.addActor(actor);
}
whereas root is simply initialized as a group in the Stage constructor: root = new Group();.
And Group.addActor() looks like this:
(here the github code of Group.java)
/** Adds an actor as a child of this group. The actor is first removed from its parent group, if any. */
public void addActor (Actor actor) {
if (actor.parent != null) actor.parent.removeActor(actor, false);
children.add(actor);
actor.setParent(this);
actor.setStage(getStage());
childrenChanged();
}
So in the tree first lines is the answer: when creating the new stage, if the actor to add already has a parent, it is removed from its current parent. So, There are two possible solutions to the problem I enounced:
SOLUTION 1: Override addActor removing the if statement, or any other alteration of the library, which I'm not sure if it would work. I rather think this could be very problematic, for instance it could prevent the stages from disposing correctly
SOLUTION 2: Change the design so you don't need an omnipresent actor, nor changing/reimplementing the libraries. For the moment this is what I've done based on this answer, it isn't very clean but it works so far:
1) In the MyScreen class added the following fields:
private boolean watchingTemp;
private Actor watchActorTemp;
private Action actionTemp;
2) Then added this method:
public void addActionOnStageAfterActorEndsHisActions(Actor actor, Action action) {
watchActorTemp = actor;
actionTemp = action;
watchingTemp = true;
}
3) then in the render method, I added the following:
if (watchingTemp && !watchActorTemp.hasActions()) {
watchingTemp = false;
stage.addAction(actionTemp);
}
4) finally, when wishing to perform an action at a screen transition (and eventually disposing the first one), you can do something like this: I use something similar when clicking on a door between screens
public void movePlayerTHENgotoNewScreen(float xPos, float yPos, whatever else...) {
game.player.walkToAnyPoint(xPos, yPos);
yourFavoriteScreen.addActionOnStageAfterActorEndsHisActions(game.player, gotoNewScreen(wathever else...));
}
Hope it helps!

Junit testing in java for void methods

How to write test case for this function in a binary search tree ?
void insert(String key){
root=insertRec(root,key);
}
Your method does something. It obviously changes the state of the object by inserting a rec(ord?) and somehow re-evaluating what the root is. So, to test it, you should somehow be able to determine the new state, for example...
public void insert_should_create_new_record_and_set_root() {
assertThat( myObject.getRec( originalRoot) ).isNull();
Object originalRoot = myObject.getRoot();
myObject.insert("xyz");
assertThat( myObject.getRec( originalRoot) ).isEqualTo( "xyz"); // using AssertJ style here
assertThat( myObject.getRoot().value() ).isNotEqualTo( originalRoot );
}
If, on the other hand, you have no way to check the state from the outside, then you'll have a problem. But somehow your class has to communicate to the outside, hasn't it? If you really think that you cannot check the new state, then you'll have to provide more code of this class, as this answer is, of course, very general (which means "guessing", here).

Actionscript 3 - can't open multiple navigateToURL() instances at the same time

I am new to AS3, I want to open multiple browser tabs with flash.
I'm trying to simply start multiple instances of navigateToURL().
for each (var str:String in arrayofrequests)
{
[...]
try { navigateToURL(request, "_blank");}
[...]
}
but only the last instance of navigateToURL gets executed in the browser.
I searched online and someone pointed out callLater could solve this issue.
But every time I try to use callLater I get
Error: Call to a possibly undefined method callLater.
I analyzed adobe documentation here: http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7b06.html
All objects that inherit from the UIComponent class can open the callLater() method.
How I do this? I tried to change my code to something like this
public class Main extends UIComponent
but it isn't working.
To start, UIComponent class is the base class for all visual components used in Flex ( like Label, Progressbar, ...), but I think that your are using Flash, so it's not the good way.
Really I don't know why you want to open many urls in the browser in the same time ( and I think that your final user may be will not like that ), but you have to use some intervals between every navigateToURL() calls using a Timer object for example :
var urls:Array = [
'http://www.wikipedia.org',
'http://www.ubuntu.com',
'http://www.stackoverflow.com'
];
var timer:Timer = new Timer(300, urls.length);
timer.addEventListener(TimerEvent.TIMER, onTimer);
function onTimer(e:TimerEvent):void {
navigateToURL(new URLRequest(urls[timer.currentCount - 1]), '_blank');
}
timer.start();
Hope that can help.

GameStateManager LibGDX

I started a project with libgdx and I have a GameStateManager for my GameStates Menu and Play.
If I run the project it shows the Menu and then I can click a button to open the Play GameState.
The Problem is, that when I ended the Game it should show the Menu State again, but I get a black screen. I tested if the render() method is started (with System.out...) and the render() method in Menu is starting.
I am not shure why I get a black screen when I "reopen" the Menu state. Maybe its not working because I use Box2D in Play but I dont know.
Here some code:
This is the method in Play which should open the Menu if the player is at the end:
public void playerEnded() {
gsm.setState(GameStateManager.MENU);
}
Maybe you can tell me, if I have to end box2d things or so.
I hope someone can help me, and if you want more code - no problem.
Your custom GameStateManager should extend this class:
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/Game.html
To change screens you should be using Game.setScreen(Screen screen)
Each different screen should be an implementation of Screen.
So the way it works in my libGDX projects is such that GameScreen extends Screen, and MenuScreen extends Screen. That way I can change what draws on what screen.
This all goes back to interfaces and polymorphism, so if you don't get those concepts, just give it a quick google and you'll get an idea what you need to do.
Chances are that your are defining a
Stack<GameState> gameStates
in your GameStateManager to manage your GameStates.
If so, you could do some reading on using a Stack. Anyway, here's what could do to solve your problem:
I'm assuming you have the following structure in your GamestateManager;
public void setState(int state){
popState();
pushState(state);
}
public void pushState(int state){
gameStates.push(getState(state));
}
public void popState(){
GameState g = gameStates.pop();
g.dispose();
}
private GameState getState(int state){
if(state == MENU) return new Menu(this);
if(state == PLAY) return new Play(this);
return null;
}
When you click your start button in your Menu-GameState, you'll want to launch the Play-GameState.
Now, instead of using the setState method, which removes the top state (pop) and then pushes the new state. Try using only the pushState method. This will put your new Play-GameState on top of your Menu-GameState in the GameState-Stack.
When you're done playing, you can pop your Play-GameState and the Menu-GameState should reappear. But this time it won't instantiate a new Object, but reuse the one you used when you started the game.
// in the Menu-GameState:
public void startPlay() {
gsm.pushState(GameStateManager.PLAY);
}
// in the Play-GameState:
public void playerEnded() {
gsm.popState();
}
This won't affect gameplay performance as you would render and update your game with only the GameState that is on top of the Stack, like this:
public void update(float dt) {
gameStates.peek().update(dt);
}
public void render() {
gameStates.peek().render();
}
The peek method takes the GameState from the top of the Stack, but leaves it there.
The only downside is that the Menu-Gamestate would stay in-memory during your Play-State.
Also, if this method works, you could still do it your way, but you should check the way your Menu-GameState is instantiated and identify problems when it's instantiated twice.
I implemented a similar StageManager in my game. If you are using viewports/cameras in your game, then it is likely that when you go back to your menu state, the viewport is still set to the Game state's viewport.
For my app, I had my State class have an activate() method which would be called whenever a state became the active state:
public void activate(){
stage.getViewport().update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}

Drawing multiple lines on one chart in flex 4.5

I have a candleStickChart in flex 4.5 with a dateTimeAxis horizontal axis.
I wish to have a button that enables to draw a line on top of that chart.
I wrote a code that each time the button is click, a new CartesianDataCanvas is created. than I do a pretty standard line drawing by listening for the MOUSE_DOWN, MOUSE_MOVE, and MOUSE_UP to draw the line.
In the MOUSE_DOWN event I create the new CartesianDataCanvas, and update the annotaionArray as described in the following code: (candles is the candleStickChart's id)
public function startDrawing(event:MouseEvent):void
{
canvas = new CartesianDataCanvas;
annotationArray.addItem(canvas);
candles.annotationElements = annotationArray.toArray();
x1 = this.mouseX;
y1 = this.mouseY;
addEventListener(MouseEvent.MOUSE_MOVE, updateLine);
addEventListener(MouseEvent.MOUSE_UP, stopDrawing);
}
Everything is working fine in the first line that i'm drawing.
The problem is that when drawing the second line, the first line is disappeared. When I'm debugging the annotationArray i can see that it is indeed consist of 2 CartesianDataCanvas objects and for somereasoen it shows onlt the last one.
Does someone knows how can I fix this to show all the CartesianDataCanvas in the array at once?
I'm fairly new to flex so I defenetly might missed some basic stuff here. feel free to comment on basics too.
Thanks in advance
Ravid
Figured out the problem.
I needed to create a new class that derived from the cartesianCanvas and override its "updateDisplayList" function to redrew the line
override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
{
super.updateDisplayList( unscaledWidth, unscaledHeight );
drawLine();
}