Example #1
0
  /**
   * @param group an empty group to be the parent
   * @return the group with the current selection
   */
  public Group createGroup(Group group) {
    // New group has the same transformation as this
    group.setBounds(getX(), getY(), getWidth(), getHeight());
    group.setOrigin(getOriginX(), getOriginY());
    group.setRotation(getRotation());
    group.setScale(getScaleX(), getScaleY());

    // Each children in the group must be contained by the new group
    Array<Actor> children = getChildren();
    children.sort(
        new Comparator<Actor>() {
          @Override
          public int compare(Actor actor, Actor actor2) {
            return ((SelectionGhost) actor).getRepresentedActor().getZIndex()
                - ((SelectionGhost) actor2).getRepresentedActor().getZIndex();
          }
        });

    for (Actor actor : children) {
      SelectionGhost ghost = (SelectionGhost) actor;
      Actor representedActor = ghost.getRepresentedActor();
      representedActor.setPosition(ghost.getX(), ghost.getY());
      representedActor.setRotation(ghost.getRotation());
      representedActor.setScale(ghost.getScaleX(), ghost.getScaleY());
      group.addActor(representedActor);
    }
    return group;
  }
Example #2
0
  private void updateTransform() {
    Matrix3 temp = worldTransform;

    float originX = getOriginX();
    float originY = getOriginY();
    float rotation = getRotation();
    float scaleX = getScaleX();
    float scaleY = getScaleY();

    if (originX != 0 || originY != 0) localTransform.setToTranslation(originX, originY);
    else localTransform.idt();
    if (rotation != 0) localTransform.mul(temp.setToRotation(rotation));
    if (scaleX != 1 || scaleY != 1) localTransform.mul(temp.setToScaling(scaleX, scaleY));
    if (originX != 0 || originY != 0) localTransform.mul(temp.setToTranslation(-originX, -originY));
    localTransform.trn(getX(), getY());

    // Find the first parent that transforms.
    Group parentGroup = getParent();
    while (parentGroup != null) {
      if (parentGroup.transform) break;
      parentGroup = parentGroup.getParent();
    }

    if (parentGroup != null) {
      worldTransform.set(parentGroup.worldTransform);
      worldTransform.mul(localTransform);
    } else {
      worldTransform.set(localTransform);
    }

    batchTransform.set(worldTransform);
  }
  public void testBoundaries() {
    Project project = new Project(getContext(), "testProject");
    Group parentGroup = new Group();

    Sprite firstSprite = new Sprite("firstSprite");
    parentGroup.addActor(firstSprite.look);
    project.addSprite(firstSprite);

    for (int i = 0; i < 10; i++) {
      Sprite sprite = new Sprite("testSprite" + i);
      parentGroup.addActor(sprite.look);
      sprite.look.setZIndex(Integer.MAX_VALUE);
      project.addSprite(sprite);
    }

    ProjectManager.getInstance().setProject(project);

    ComeToFrontAction action = ExtendedActions.comeToFront(firstSprite);
    firstSprite.look.addAction(action);
    action.act(1.0f);

    assertEquals(
        "An Integer overflow occured during ComeToFrontBrick Execution",
        getZMaxValue(firstSprite),
        firstSprite.look.getZIndex());
  }
Example #4
0
  /**
   * Applies a touch down event to the stage and returns true if an actor in the scene {@link
   * Event#handle() handled} the event.
   */
  public boolean touchDown(int screenX, int screenY, int pointer, int button) {
    if (screenX < viewport.getScreenX()
        || screenX >= viewport.getScreenX() + viewport.getScreenWidth()) return false;
    if (Gdx.graphics.getHeight() - screenY < viewport.getScreenY()
        || Gdx.graphics.getHeight() - screenY >= viewport.getScreenY() + viewport.getScreenHeight())
      return false;

    pointerTouched[pointer] = true;
    pointerScreenX[pointer] = screenX;
    pointerScreenY[pointer] = screenY;

    screenToStageCoordinates(tempCoords.set(screenX, screenY));

    InputEvent event = Pools.obtain(InputEvent.class);
    event.setType(Type.touchDown);
    event.setStage(this);
    event.setStageX(tempCoords.x);
    event.setStageY(tempCoords.y);
    event.setPointer(pointer);
    event.setButton(button);

    Actor target = hit(tempCoords.x, tempCoords.y, true);
    if (target == null) {
      if (root.getTouchable() == Touchable.enabled) root.fire(event);
    } else {
      target.fire(event);
    }

    boolean handled = event.isHandled();
    Pools.free(event);
    return handled;
  }
Example #5
0
  private void drawRecursive(Actor actor) {
    if (!invisibleActors && !actor.isVisible()) return;

    if (allActors) actor.debug();

    if (actor.getDebug()) {
      actor.getDebugRects(debugRects);
      for (DebugRect debugRect : debugRects) drawRect(actor, debugRect);
      debugRects.clear();
      debugRectPool.freeAll(usedRects);
      usedRects.clear();
    }

    boolean draw = true;
    Rectangle scissorBounds = null;
    if (actor instanceof Group) scissorBounds = ((Group) actor).getScissorBounds();
    if (scissorBounds != null) {
      shapes.flush();
      draw = ScissorStack.pushScissors(scissorBounds);
    }
    if (draw) {
      // Children are still rendered, even if the group has no debugging enabled.
      if (actor instanceof Group) {
        Group group = (Group) actor;
        for (Actor child : group.getChildren()) drawRecursive(child);
      }

      if (scissorBounds != null) {
        shapes.flush();
        ScissorStack.popScissors();
      }
    }
  }
Example #6
0
  private static void createNavigationGroup() {
    navigationGroup = new Group();
    navigationGroup.setVisible(false);
    Skin skin = AbstractScreen.skin;
    final ToolbarButton navigationButton = new ToolbarButton(skin.getDrawable("ic_menu"), skin);
    navigationButton.setBounds(
        0,
        AbstractScreen.stageh - NAVIGATION_BUTTON_WIDTH_HEIGHT,
        NAVIGATION_BUTTON_WIDTH_HEIGHT,
        NAVIGATION_BUTTON_WIDTH_HEIGHT);

    final NavigationPanel p = new NavigationPanel(AbstractScreen.skin, "default", navigationButton);
    p.setName(NAVIGATION_PANEL_NAME);
    p.setModal(false);
    navigationButton.addListener(
        new ClickListener() {
          @Override
          public void clicked(InputEvent event, float x, float y) {
            // event.cancel();
            if (!p.isVisible()) {
              AbstractScreen.mockupController.show(p);
            } else {
              AbstractScreen.mockupController.hide(p);
            }
          }
        });

    navigationGroup.addActor(p);
    navigationGroup.addActor(navigationButton);
  }
Example #7
0
  private static void createOptionsGroup() {
    optionsGroup = new Group();
    optionsGroup.setVisible(false);
    final OptionsPanel p = new OptionsPanel(AbstractScreen.skin, "dialog");
    p.setName(OPTIONS_PANEL_NAME);
    final Button options = new ImageButton(AbstractScreen.skin, "ic_settings");
    options.setBounds(
        AbstractScreen.stagew - OPTIONS_BUTTON_WIDTH_HEIGHT,
        AbstractScreen.stageh - OPTIONS_BUTTON_WIDTH_HEIGHT,
        OPTIONS_BUTTON_WIDTH_HEIGHT,
        OPTIONS_BUTTON_WIDTH_HEIGHT);
    options.addListener(
        new ClickListener() {
          @Override
          public void clicked(InputEvent event, float x, float y) {
            if (!p.isVisible()) {
              AbstractScreen.mockupController.show(p);
            } else {
              AbstractScreen.mockupController.hide(p);
            }
          }
        });
    TextureRegion t = AbstractScreen.skin.getRegion("ic_logo");

    Image i = new Image(t);
    i.setTouchable(Touchable.disabled);
    i.setX(AbstractScreen.halfstagew - t.getRegionWidth() / 2f);
    i.setY(AbstractScreen.halfstageh * 1.1f - t.getRegionHeight() / 2f);

    optionsGroup.addActor(i);
    optionsGroup.addActor(p);
    optionsGroup.addActor(options);
  }
Example #8
0
 /**
  * Sets the z-index of this actor. The z-index is the index into the parent's {@link
  * Group#getChildren() children}, where a lower index is below a higher index. Setting a z-index
  * higher than the number of children will move the child to the front. Setting a z-index less
  * than zero is invalid.
  */
 public void setZIndex(int index) {
   if (index < 0) throw new IllegalArgumentException("ZIndex cannot be < 0.");
   Group parent = getParent();
   if (parent == null) return;
   Array<Actor> children = parent.getChildren();
   if (children.size == 1) return;
   if (!children.removeValue(this, true)) return;
   if (index >= children.size) children.add(this);
   else children.insert(index, this);
 }
Example #9
0
  public void detach() {
    getParent().addAction(new DetachComponentAction(this, this.getFixture()));
    Gdx.app.log("Test", "AboutToRemove");

    Group root = this.getStage().getRoot();
    this.remove();
    root.addActor(this);

    for (Hardpoint hp : hardpoints) {
      hp.detach();
    }
  }
Example #10
0
 /**
  * @param group will replace the internally managed group. All current children will be moved to
  *     this group.
  */
 @Override
 public void setActor(final WidgetGroup group) {
   if (group == null) {
     throw new IllegalArgumentException("Group cannot be null.");
   }
   final Group previousGroup = getActor();
   super.setActor(group);
   attachListener(); // Attaches draggable to all previous group children.
   for (final Actor child : previousGroup.getChildren()) {
     group.addActor(child); // No need to attach draggable, child was already in pane.
   }
 }
Example #11
0
  private void removeCard(Actor toRemove) {
    int removeIndex = cards.getChildren().indexOf(toRemove, true);

    // save the old positions of the cards
    SnapshotArray<Actor> currentCards = cards.getChildren();
    currentCards.removeIndex(removeIndex);
    List<Vector2> oldPositions = getPositions(currentCards);

    // Determine what the new positions would be
    // by adding them to a horizontal group and checking their positions
    HorizontalGroup newGroup =
        new HorizontalGroup()
            .space(calculateSpacing(cards.getChildren().size - 1, toRemove.getWidth()));
    newGroup.align(Align.bottom);
    cards.removeActor(toRemove);
    while (cards.getChildren().size > 0) {
      newGroup.addActor(cards.getChildren().get(0));
    }
    newGroup.layout();
    List<Vector2> newPositions = getPositions(newGroup.getChildren());

    // calculate what is needed to center the cards
    float centerOffset = UIConstants.WORLD_WIDTH / 2 - newGroup.getPrefWidth() / 2;
    // remove them from the horizontal group and add them back to the normal group so it doesn't try
    // to move them around
    while (newGroup.getChildren().size > 0) {
      cards.addActor(newGroup.getChildren().get(0));
    }

    interpolateActorPositions(
        cards.getChildren(), oldPositions, newPositions, centerOffset, Interpolation.pow2, 0.5f);
  }
    @Override
    public void clicked(InputEvent event, float x, float y) {
      Vector2 point = new Vector2(x, y);
      Group g = (Group) event.getListenerActor();
      if (g.isAscendantOf(ColorSelectorPopup.this)) {
        point = g.localToDescendantCoordinates(ColorSelectorPopup.this, point);

        if (ColorSelectorPopup.this.getParent() != null
            && ColorSelectorPopup.this.hit(point.x, point.y, true) == null) {
          ((BoardActor) (ColorSelectorPopup.this.getParent()))
              .removeFromActor(ColorSelectorPopup.this);
          event.getListenerActor().removeListener(this);
        }
      }
    }
Example #13
0
 /** unzooms the currently zoomed card */
 private void unzoom() {
   stopMakingSpace();
   zoomCard.setTouchable(Touchable.enabled);
   zoomCard.addAction(Actions.scaleTo(1.0f, 1.0f, 0.2f, Interpolation.pow2));
   addCard(zoomCard, zoomReturnIndex);
   zoomCard = null;
   for (Actor actor : getChildren()) {
     actor.setTouchable(Touchable.enabled);
   }
   for (Actor actor : cards.getChildren()) {
     actor.setTouchable(Touchable.enabled);
   }
   zoomGroup.setTouchable(Touchable.disabled);
   zoomGroup.setVisible(false);
 }
Example #14
0
 public void draw(SpriteBatch batch, float parentAlpha, Texture tex) {
   doAlter(batch, parentAlpha);
   if (!visibleForPlayer) return;
   batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
   batch.draw(
       tex,
       x,
       y,
       originX,
       originY,
       width,
       height,
       scaleX,
       scaleY,
       rotation,
       0,
       0,
       tex.getWidth(),
       tex.getHeight(),
       false,
       false);
   super.draw(batch, color.a * parentAlpha);
   // Log.i("", "DrawParam:"+ x+","+ y+"," +originX+","+ originY+","+ width+","+ height+","+
   // scaleX+",\n"+
   //	 scaleY+","+ rotation+","+ 0+","+ 0+","+ tex.getWidth()+","+  tex.getHeight()+","+  false+","
   // + false);
 }
Example #15
0
 /**
  * If not {@link Debug#none}, debug is enabled only for the first ascendant of the actor under the
  * mouse that is a table. Can be combined with {@link #setDebugAll(boolean)}.
  *
  * @param debugTableUnderMouse May be null for {@link Debug#none}.
  */
 public void setDebugTableUnderMouse(Debug debugTableUnderMouse) {
   if (debugTableUnderMouse == null) debugTableUnderMouse = Debug.none;
   if (this.debugTableUnderMouse == debugTableUnderMouse) return;
   this.debugTableUnderMouse = debugTableUnderMouse;
   if (debugTableUnderMouse != Debug.none) debug = true;
   else root.setDebug(false, true);
 }
Example #16
0
 /** sets batch to game units to draw and then back to screen */
 @Override
 public void draw(SpriteBatch batch, float parentAlpha) {
   tmpMatrix4.set(batch.getProjectionMatrix());
   batch.setProjectionMatrix(cam.combined);
   super.draw(batch, parentAlpha);
   batch.setProjectionMatrix(tmpMatrix4);
 }
Example #17
0
 private boolean isInAction(final Group group) {
   for (final Actor actor : group.getChildren()) {
     if (actor.getActions().size > 0) return true;
     if (actor instanceof Group) return isInAction((Group) actor);
   }
   return false;
 }
Example #18
0
  public void draw() {
    Camera camera = viewport.getCamera();
    camera.update();

    if (!root.isVisible()) return;

    Batch batch = this.batch;
    if (batch != null) {
      batch.setProjectionMatrix(camera.combined);
      batch.begin();
      root.draw(batch, 1);
      batch.end();
    }

    if (debug) drawDebug();
  }
  public void testComeToFront() {
    Project project = new Project(getContext(), "testProject");
    Group parentGroup = new Group();

    Sprite bottomSprite = new Sprite("catroid");
    parentGroup.addActor(bottomSprite.look);
    assertEquals("Unexpected initial z position of bottomSprite", 0, bottomSprite.look.getZIndex());

    Sprite middleSprite = new Sprite("catroid cat");
    parentGroup.addActor(middleSprite.look);
    assertEquals("Unexpected initial z position of middleSprite", 1, middleSprite.look.getZIndex());

    Sprite topSprite = new Sprite("scratch");
    parentGroup.addActor(topSprite.look);
    assertEquals("Unexpected initial z position of topSprite", 2, topSprite.look.getZIndex());

    project.addSprite(bottomSprite);
    project.addSprite(middleSprite);
    project.addSprite(topSprite);
    ProjectManager.getInstance().setProject(project);

    checkIfEveryZIndexUsedOnlyOnceFromZeroToNMinus1(project);

    ComeToFrontAction action = ExtendedActions.comeToFront(middleSprite);
    middleSprite.look.addAction(action);
    action.act(1.0f);
    assertEquals(
        "bottomSprite z position should now be 2",
        middleSprite.look.getZIndex(),
        getZMaxValue(middleSprite));

    Sprite nextSprite = new Sprite("dog");
    parentGroup.addActor(nextSprite.look);
    project.addSprite(nextSprite);

    assertEquals("Unexpected initial z position of topSprite", 3, nextSprite.look.getZIndex());

    ComeToFrontAction action2 = ExtendedActions.comeToFront(bottomSprite);
    bottomSprite.look.addAction(action);
    action2.act(1.0f);
    assertEquals(
        "bottomSprite z position should now be 3",
        bottomSprite.look.getZIndex(),
        getZMaxValue(bottomSprite));

    checkIfEveryZIndexUsedOnlyOnceFromZeroToNMinus1(project);
  }
  private Zone createZone(int id) {
    final String nom; // Nom de la zone;
    final String filepath = "zones/zone" + id + ".data";
    boolean first = true;

    try {
      BufferedReader buff = Gdx.files.internal(filepath).reader(1024);
      String line;

      nom = buff.readLine();

      // Creation de la zone.
      Zone zone = new Zone(id, nom);

      while ((line = buff.readLine()) != null) {
        String tab[] = line.split(" ");

        if (tab.length == 3) {
          tab[0] = tab[0].replace('_', ' ');
          if (first) {
            Usine usine = new Usine(zone, tab[0], Integer.valueOf(tab[1]), Integer.valueOf(tab[2]));

            groupVilles.addActor(new VilleActor(usine));
            zone.addVille(usine);
            first = false;
          } else {
            Ville ville = new Ville(zone, tab[0], Integer.valueOf(tab[1]), Integer.valueOf(tab[2]));

            groupVilles.addActor(new VilleActor(ville));
            zone.addVille(ville);
          }
        } else {
          System.err.println("Erreur lecture " + filepath + "continue quand même...");
        }
      }

      buff.close();
      return zone;
    } catch (FileNotFoundException e) {
      System.err.println(
          "Fichier " + filepath + " introuvable ! Aucune ville chargée pour cette zone.");
    } catch (IOException e) {
      System.err.println("Erreur à la lecture de " + filepath + ".");
    }

    return null;
  }
Example #21
0
 @Override
 public void act(float delta) {
   super.act(delta);
   if (modified) {
     modifier.getHandles().readActorTransformation();
     modified = false;
   }
 }
Example #22
0
 @Override
 public void clear() {
   super.clear();
   setBounds(0, 0, 0, 0);
   setRotation(0);
   setScale(1, 1);
   setOrigin(0, 0);
 }
Example #23
0
  public void showMenu() {
    continua = new TextButton("CONTINUA", Assets.getInstance().getButtonStyle());
    continua.setPosition(100, 400);
    toMenu = new TextButton("MENIU", Assets.getInstance().getButtonStyle());
    group = new Group();
    group.setSize(100, 100);
    group.addActor(continua);
    group.addActor(toMenu);
    group.setPosition(100, 400);

    Table table = new Table();
    table.add(continua);
    table.setPosition(100, 400);
    // stage.addActor(table);

    // stage.addActor(continua);
  }
Example #24
0
  @Override
  public void create() {
    FileHandle fh = Gdx.files.internal("freud.txt");
    TextureAtlas atlas = new TextureAtlas(fh);
    stage = new Stage();

    // ======= フロイト ==========
    TextureAtlas.AtlasRegion fruedRegion = atlas.findRegion("nigaoe_freud");
    // Imageクラスにregionを食わせるらしい
    Image fruedImage = new Image(fruedRegion);
    fruedImage.setPosition(0, 0);

    // ステージにActorを突っ込む
    // Imageはextends Widget。
    // Widgetはextends Actor implementes Layout
    stage.addActor(fruedImage); // stageの直下に追加

    // ======= 始皇帝 ==========
    TextureAtlas.AtlasRegion shikouteiRegion = atlas.findRegion("nigaoe_shikoutei");
    Image shikouteiImage = new Image(shikouteiRegion);
    shikouteiImage.setPosition(200, 0);
    stage.addActor(shikouteiImage); // stageの直下に追加

    // グループを生成する
    // Groupもextends Actor implemnts Cullable
    // Cullableはよく分からん
    // 多分Groupのabilityなんだと思うんだが
    // 親子関係の描画操作かな
    Group group = new Group();
    group.setPosition(150, 200);
    group.setScale(0.5f);
    stage.addActor(group);

    // ======= 正岡子規 ==========
    TextureAtlas.AtlasRegion masaokaRegion = atlas.findRegion("nigaoe_masaoka_shiki");
    Image masaokaImage = new Image(masaokaRegion);
    masaokaImage.setPosition(0, 0);
    group.addActor(masaokaImage); // groupの下に追加

    // ======= 石川ゴエモン ==========
    TextureAtlas.AtlasRegion goemonRegion = atlas.findRegion("nigaoe_ishikawa_goemon");
    Image goemonImage = new Image(goemonRegion);
    goemonImage.setPosition(200, 0);
    group.addActor(goemonImage); // groupの下に追加
  }
Example #25
0
 @Override
 public void act(float delta) {
   super.act(delta);
   // If the grouper has been modified, transformation must be
   // transmitted to represented actors
   if (modified) {
     updateTransformation();
   }
 }
Example #26
0
  /**
   * Sets this actor as the event {@link Event#setTarget(Actor) target} and propagates the event to
   * this actor and ancestor actors as necessary. If this actor is not in the stage, the stage must
   * be set before calling this method.
   *
   * <p>Events are fired in 2 phases. The first phase notifies listeners on each actor starting at
   * the root and propagating downward to (and including) this actor. The second phase notifes
   * listeners on each actor starting at this actor and, if {@link Event#getBubbles()} is true,
   * propagating upward to the root. If the event is {@link Event#stop() stopped} at any time, it
   * will not propagate to the next actor.
   *
   * @return true of the event was {@link Event#cancel() cancelled}.
   */
  public boolean fire(Event event) {
    if (event.getStage() == null) event.setStage(getStage());
    event.setTarget(this);

    // Collect ancestors so event propagation is unaffected by hierarchy changes.
    Array<Group> ancestors = Pools.obtain(Array.class);
    Group parent = getParent();
    while (parent != null) {
      ancestors.add(parent);
      parent = parent.getParent();
    }

    try {
      // Notify all parent capture listeners, starting at the root. Ancestors may stop an event
      // before children receive it.
      for (int i = ancestors.size - 1; i >= 0; i--) {
        Group currentTarget = ancestors.get(i);
        currentTarget.notify(event, true);
        if (event.isStopped()) return event.isCancelled();
      }

      // Notify the target capture listeners.
      notify(event, true);
      if (event.isStopped()) return event.isCancelled();

      // Notify the target listeners.
      notify(event, false);
      if (!event.getBubbles()) return event.isCancelled();
      if (event.isStopped()) return event.isCancelled();

      // Notify all parent listeners, starting at the target. Children may stop an event before
      // ancestors receive it.
      for (int i = 0, n = ancestors.size; i < n; i++) {
        ancestors.get(i).notify(event, false);
        if (event.isStopped()) return event.isCancelled();
      }

      return event.isCancelled();
    } finally {
      ancestors.clear();
      Pools.free(ancestors);
    }
  }
 private void createEntities() {
   gameLogic = new GameLogic();
   Carte carte = new Carte(gameLogic);
   gameLogic.setCarte(carte);
   for (int i = 1; i <= 6; i++) {
     Zone zone = createZone(i);
     groupZones.addActor(new ZoneActor(zone));
     carte.addZone(zone);
   }
 }
Example #28
0
  @Override
  public void act(float delta) {

    // coordinate fix
    // TODO to STAGE COORDS for relativ coords

    float relativeX = getX();
    float relativeY = getY();
    float relativeRotation = 0;

    Group currParent = this.getParent();
    while (currParent != null) {
      relativeX += currParent.getX();
      relativeY += currParent.getY();
      relativeRotation += currParent.getRotation();
      currParent = currParent.getParent();
    }

    if (lightObject != null) {

      float yy = 0;
      float xx = 0;

      if (relativeRotation != 0) {
        xx =
            getX() * MathUtils.cosDeg(relativeRotation)
                - getY() * MathUtils.sinDeg(relativeRotation);
        yy =
            getY() * MathUtils.cosDeg(relativeRotation)
                + getX() * MathUtils.sinDeg(relativeRotation);
        yy = getY() - yy;
        xx = getX() - xx;
      }
      lightObject.setPosition(relativeX - xx, relativeY - yy);
    }
    if (dataVO.type == LightType.CONE) {
      lightObject.setDirection(direction + relativeRotation);
    }
    // debugImg.setX(relativeX);
    // debugImg.setY(relativeY);
    super.act(delta);
  }
Example #29
0
 @Override
 public void act(float delta) {
   totalTime += delta;
   accum += delta;
   if (accum > end) {
     accum = 0;
     if (end > .3f) end -= .01f;
     addActor(Pools.obtain(Mob.class).init(faceRegion, end * 10f));
   }
   super.act(delta);
 }
Example #30
0
  /**
   * Creates a stage with the specified viewport and batch. This can be used to avoid creating a new
   * batch (which can be somewhat slow) if multiple stages are used during an application's life
   * time.
   *
   * @param batch Will not be disposed if {@link #dispose()} is called, handle disposal yourself.
   */
  public Stage(Viewport viewport, Batch batch) {
    if (viewport == null) throw new IllegalArgumentException("viewport cannot be null.");
    if (batch == null) throw new IllegalArgumentException("batch cannot be null.");
    this.viewport = viewport;
    this.batch = batch;

    root = new Group();
    root.setStage(this);

    viewport.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
  }