0) {
+ propagateAlpha(sd, style.separatorColor);
+ sd.line(pointAtAngle(vector22, vector2, getInnerRadiusLength(), drawnRadianAngle),
+ pointAtAngle(vector23, vector2, getCurrentRadius(), drawnRadianAngle),
+ style.separatorWidth);
+ }
+ }
+
+ /**
+ * To get the coordinates of a point along a line traced from the center,
+ * along the designated angle, at the designated distance from the center.
+ *
+ * @param center center point of the Circle
+ * @param radius how far from the center the desired point is
+ * @param radian the angle along which the line is calculated
+ * @return the point associated with those parameters
+ */
+ public Vector2 pointAtAngle(Vector2 output, Vector2 center, float radius, float radian) {
+ output.set(center.x + radius * MathUtils.cos(radian), center.y + radius * MathUtils.sin(radian));
+ return output;
+ }
+
+ /**
+ * Determines the color of the slice in which resides the Actor designated
+ * by the {@code index} parameter. By default, the colors come from the way
+ * you have set up your Style (anything that extends {@link PieWidgetStyle}).
+ * Override this method when creating your Widget if you want to have control
+ * over those colors.
+ * Do not set the color of the {@link ShapeDrawer} in there: that is
+ * handled internally. Just return the desired Color.
+ * Here is an example:
+ *
+ * {@code
+ * RadialGroup myWidget = new RadialGroup(shapeDrawer, myStyle, 77) {
+ * public Color getColor(int index) {
+ * Color fader = super.getColor(index);
+ * // This will fade the slices' alpha value
+ * return new Color(fader.r, fader.g, fader.b, fader.a/index);
+ * }
+ * };
+ * }
+ *
+ *
+ * @param index index of the child whose slice is to be drawn with the returned Color.
+ * @return the Color to be used to draw the slice of the child with the given index.
+ */
+ public Color getColor(int index) {
+ if(style.alternateSliceColor != null
+ && index%2 == 1)
+ return style.alternateSliceColor;
+
+ if(style.sliceColor != null)
+ return style.sliceColor;
+
+ return TRANSPARENT;
+ }
+
+ protected void drawChild(Vector2 vector2, int index, float startAngle, float radian) {
+ propagateAlpha(sd, getColor(index));
+ sd.arc(vector2.x, vector2.y, (getCurrentRadius()+ getInnerRadiusLength())/2,
+ startAngle, radian, getCurrentRadius()- getInnerRadiusLength());
+
+ /* Circumferences */
+ drawChildCircumference(vector2, startAngle, radian, getCurrentRadius() - style.circumferenceWidth/2);
+ if(innerRadiusPercent > 0)
+ drawChildCircumference(vector2, startAngle, radian, getInnerRadiusLength() + style.circumferenceWidth/2);
+ }
+
+ protected void drawChildCircumference(Vector2 vector2, float startAngle, float radian, float radius) {
+ if(style.circumferenceColor != null && style.circumferenceWidth > 0) {
+ propagateAlpha(sd, style.circumferenceColor);
+ sd.arc(vector2.x, vector2.y, radius, startAngle, radian, style.circumferenceWidth);
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+ /*
+ =================================== STYLE ==================================
+ */
+
+
+ /**
+ * Returns the label's style. Modifying the returned style may not have an
+ * effect until {@link #setStyle(PieWidgetStyle)} is called.
+ * It's probable that your code will look like this (to give you an idea):
+ *
+ * {@code
+ * radialGroup.getStyle().whatYouWantToChange = someNewValue;
+ * radialGroup.setStyle(radialGroup.getStyle());
+ * }
+ *
+ *
+ * @return the Style that defines this Widget. This style contains information
+ * about what is the value of the radius or the width of the separators, for
+ * example.
+ */
+ public PieWidgetStyle getStyle() {
+ return style;
+ }
+
+
+ /**
+ * Runs checks before assigning the style to the Widget. Only a valid style
+ * will pass the test.
+ *
+ * @param style the style that will be checked before being assigned.
+ */
+ public void setStyle(PieWidgetStyle style) {
+ checkStyle(style);
+ this.style = style;
+ invalidate();
+ }
+
+ /**
+ * Ensures the input values for the given style are valid.
+ *
+ * @param style a style class you want to check properties of.
+ */
+ protected void checkStyle(PieWidgetStyle style) {
+ if(style == null)
+ throw new IllegalArgumentException("style cannot be null.");
+
+ if(style.separatorWidth < 0)
+ throw new IllegalArgumentException("separatorWidth cannot be negative.");
+
+ if(style.circumferenceWidth < 0)
+ throw new IllegalArgumentException("circumferenceWidth cannot be negative.");
+
+ if(style.sliceColor == null && style.alternateSliceColor != null)
+ throw new IllegalArgumentException("sliceColor must also be specified if you are defining alternateSliceColor. " +
+ "You can however only specify the sliceColor, if you want.");
+ }
+
+ /**
+ * Encompasses the characteristics that define the style of the Widget
+ * to be drawn.
+ */
+ public static class PieWidgetStyle {
+
+ /**
+ * Recommended. Optional.
+ * A background that will be drawn behind everything else within the Widget.
+ * Be mindful of the fact that this is unaffected by any of the other
+ * variables: it will be resized to fit in the whole region that
+ * represents the position, width and height of the widget.
+ */
+ public Drawable background;
+
+ /**
+ * Optional.
+ * A background color that, if provided, will be drawn over the
+ * background image and below everything else.
+ * It mostly acts as a quick set up option if you do not have an image
+ * for you background.
+ */
+ public Color backgroundColor;
+
+ /**
+ * Recommended. Optional.
+ * The color used by the separating lines between each item.
+ * It is recommended mostly for the case where you are not defining an
+ * {@link #alternateSliceColor}.
+ * If you do not define a {@link #separatorWidth} along with this value,
+ * no lines will be visible.
+ */
+ public Color separatorColor;
+
+ /**
+ * Recommended. Optional.
+ * The color used to fill the "pie sectors" (i.e. slice) of each item.
+ * Consider using a fairly low alpha value if you are providing a
+ * {@link #background} {@link Drawable}.
+ */
+ public Color sliceColor;
+
+ /**
+ * Optional.
+ * If this color is set, the "pie sectors" will alternate between the
+ * {@link #sliceColor} and this one so that their defining region
+ * is more easily distinguished.
+ */
+ public Color alternateSliceColor;
+
+ /**
+ * Optional.
+ * The color used for the line that defines the circumference of the
+ * Widget. If the Widget is not a complete a circle, this will only be
+ * applied along the partial circumference.
+ * If you have set a non-zero {@link #innerRadiusPercent} value, this will
+ * also apply to the "inner radius" of your Widget.
+ * If you do not define a {@link #circumferenceWidth} along with this
+ * value, no circumference will be visible.
+ */
+ public Color circumferenceColor;
+
+ /**
+ * Recommended. Optional.
+ * Determines how wide the lines that separate each slice will be.
+ * If no {@link #separatorColor} was provided along with this value,
+ * no lines will be drawn.
+ */
+ public float separatorWidth;
+
+ /**
+ * Optional.
+ * Determines how wide the circumference line will be.
+ * If no {@link #circumferenceColor} was provided along with this value,
+ * no circumference will be drawn.
+ */
+ public float circumferenceWidth;
+
+
+ /**
+ * Encompasses the characteristics that define the style of the Widget
+ * to be drawn.
+ */
+ public PieWidgetStyle() {
+ }
+
+ /**
+ * Encompasses the characteristics that define the style of the Widget
+ * to be drawn.
+ *
+ * @param style a Style to copy the parameters from.
+ */
+ public PieWidgetStyle(PieWidgetStyle style) {
+ this.background = style.background;
+ this.circumferenceWidth = style.circumferenceWidth;
+ this.circumferenceColor = new Color(style.circumferenceColor);
+ this.separatorWidth = style.separatorWidth;
+ this.separatorColor = new Color(style.separatorColor);
+ this.sliceColor = new Color(style.sliceColor);
+ this.alternateSliceColor = new Color(style.alternateSliceColor);
+ this.backgroundColor = new Color(style.backgroundColor);
+ }
+ }
+
+
+
+
+
+
+
+
+
+ /*
+ =============================== GETTERS/SETTERS ============================
+ */
+
+
+ /**
+ * @return the ShapeDrawer used to draw everything but the contained Actors.
+ */
+ public ShapeDrawer getShapeDrawer() {
+ return sd;
+ }
+
+ /**
+ * You probably shouldn't be messing with this, but it's provided for
+ * convenience reasons.
+ * For example, it's possible that your widget will be so big that
+ * the {@link ShapeDrawer} will crash with an Exception while trying to
+ * draw it. You would then want to use this setter to provide a brand new
+ * instance which didn't override the {@code estimateSidesRequired(float, float)}
+ * method to try to increase the smoothness of the curves.
+ *
+ * @param sd the new instance of {@link ShapeDrawer} that you want to use.
+ */
+ public void setShapeDrawer(ShapeDrawer sd) {
+ this.sd = sd;
+ }
+}
diff --git a/src/main/java/com/payne/games/piemenu/RadialGroup.java b/src/main/java/com/payne/games/piemenu/RadialGroup.java
index b770694..a954e5f 100644
--- a/src/main/java/com/payne/games/piemenu/RadialGroup.java
+++ b/src/main/java/com/payne/games/piemenu/RadialGroup.java
@@ -1,58 +1,45 @@
package com.payne.games.piemenu;
import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.graphics.Color;
-import com.badlogic.gdx.graphics.g2d.Batch;
-import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Touchable;
-import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
-import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
-import com.badlogic.gdx.scenes.scene2d.utils.TransformDrawable;
import com.badlogic.gdx.utils.Align;
+import com.payne.games.piemenu.PieWidget.PieWidgetStyle;
import space.earlygrey.shapedrawer.ShapeDrawer;
/**
* A RadialGroup aims at providing the user with a simple way to lay out
- * the contained Actors in a circular fashion.
+ * the contained Actors in a circular fashion. It does not use a
+ * {@link ShapeDrawer} in any way. Thus, no Style whatsoever is required.
*
* @author Jérémi Grenier-Berthiaume (aka "payne")
*/
public class RadialGroup extends WidgetGroup {
- /**
- * Used to draw on the screen many elements of the style.
- */
- protected ShapeDrawer sd;
-
- /**
- * Defines the way the widget looks.
- */
- private RadialGroupStyle style;
-
/**
* Required.
* The radius that defines how big the Widget will be (in terms of scene2d,
* this is actually half the "minimal size" this widget will ever take).
* It must be bigger than {@value #BUFFER}.
*/
- protected float minRadius;
+ protected float preferredRadius;
/**
* Optional.
- * If provided, the {@link RadialGroupStyle#sliceColor} will only fill
- * the region defined between the {@link #minRadius} and its percentage
+ * If provided, the {@link PieWidgetStyle#sliceColor} will only fill
+ * the region defined between the {@link #preferredRadius} and its percentage
* value coming from this.
- * For example, having a {@link #minRadius} of 80 and a
+ * For example, having a {@link #preferredRadius} of 80 and a
* {@link #innerRadiusPercent} of 0.5 will mean that the inner-radius will
* stand at 40 pixels from the center.
* A hole will be left into the middle of the Widget, like a doughnut, and
- * if a {@link RadialGroupStyle#background} or a
- * {@link RadialGroupStyle#backgroundColor} was provided, it will be visible
+ * if a {@link PieWidgetStyle#background} or a
+ * {@link PieWidgetStyle#backgroundColor} was provided, it will be visible
* in the middle.
* Actors inserted into the Widget are by default placed in the middle
* between the inner-radius and the radius.
@@ -94,277 +81,63 @@ public class RadialGroup extends WidgetGroup {
/* For internal use (optimization). */
private float lastRadius = 0;
protected static final float BUFFER = 1;
- protected static final Color TRANSPARENT = new Color(0,0,0,0);
private static Vector2 vector2 = new Vector2();
- private static Vector2 vector22 = new Vector2();
- private static Vector2 vector23 = new Vector2();
-
-
-
+ /** Used internally for the shared properties among constructors of RadialWidgets. */
protected void constructorsCommon() {
setTouchable(Touchable.childrenOnly);
}
- /**
- * Used internally for the shared properties among constructors of RadialWidgets.
- */
- protected RadialGroup(final Batch batch, final TextureRegion whitePixel, float minRadius) {
- this.sd = new ShapeDrawer(batch, whitePixel) {
- /* OPTIONAL: Ensuring a certain smoothness. */
- @Override
- protected int estimateSidesRequired(float radiusX, float radiusY) {
- return 200;
- }
- };
- setMinRadius(minRadius);
- constructorsCommon();
- }
-
- /**
- * Used internally for the shared properties among constructors of RadialWidgets.
- */
- protected RadialGroup(final Batch batch, final TextureRegion whitePixel,
- float minRadius, float innerRadiusPercent) {
- this(batch, whitePixel, minRadius);
- setInnerRadiusPercent(innerRadiusPercent);
- }
-
- /**
- * Used internally for the shared properties among constructors of RadialWidgets.
- */
- protected RadialGroup(final Batch batch, final TextureRegion whitePixel,
- float minRadius, float innerRadiusPercent, float startDegreesOffset) {
- this(batch, whitePixel, minRadius, innerRadiusPercent);
- setStartDegreesOffset(startDegreesOffset);
- }
-
- /**
- * Used internally for the shared properties among constructors of RadialWidgets.
- */
- protected RadialGroup(final Batch batch, final TextureRegion whitePixel,
- float minRadius, float innerRadiusPercent,
- float startDegreesOffset, float totalDegreesDrawn) {
- this(batch, whitePixel, minRadius, innerRadiusPercent, startDegreesOffset);
- setTotalDegreesDrawn(totalDegreesDrawn);
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param style defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- RadialGroupStyle style, float minRadius) {
- this(batch, whitePixel, minRadius);
- setStyle(style);
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param style defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- * @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
- * the percentage of the radius that is cut off,
- * starting from the center of the widget.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- RadialGroupStyle style, float minRadius,
- float innerRadiusPercent) {
- this(batch, whitePixel, minRadius, innerRadiusPercent);
- setStyle(style);
- }
/**
* See {@link RadialGroup} for a description.
*
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param style defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- * @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
- * the percentage of the radius that is cut off,
- * starting from the center of the widget.
- * @param startDegreesOffset the {@link #startDegreesOffset} that defines
- * how far from the origin the drawing begins.
+ * @param preferredRadius the {@link #preferredRadius} that defines the
+ * size of the widget.
*/
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- RadialGroupStyle style, float minRadius,
- float innerRadiusPercent, float startDegreesOffset) {
- this(batch, whitePixel, minRadius, innerRadiusPercent, startDegreesOffset);
- setStyle(style);
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param style defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- * @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
- * the percentage of the radius that is cut off,
- * starting from the center of the widget.
- * @param startDegreesOffset the {@link #startDegreesOffset} that defines
- * how far from the origin the drawing begins.
- * @param totalDegreesDrawn the {@link #totalDegreesDrawn} that defines how
- * many degrees the widget will span, starting from
- * its {@link #startDegreesOffset}.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- RadialGroupStyle style, float minRadius,
- float innerRadiusPercent, float startDegreesOffset, float totalDegreesDrawn) {
- this(batch, whitePixel, minRadius, innerRadiusPercent, startDegreesOffset, totalDegreesDrawn);
- setStyle(style);
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, float minRadius) {
- this(batch, whitePixel, minRadius);
- setStyle(skin.get(RadialGroupStyle.class));
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- * @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
- * the percentage of the radius that is cut off,
- * starting from the center of the widget.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, float minRadius,
- float innerRadiusPercent) {
- this(batch, whitePixel, minRadius, innerRadiusPercent);
- setStyle(skin.get(RadialGroupStyle.class));
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- * @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
- * the percentage of the radius that is cut off,
- * starting from the center of the widget.
- * @param startDegreesOffset the {@link #startDegreesOffset} that defines
- * how far from the origin the drawing begins.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, float minRadius,
- float innerRadiusPercent, float startDegreesOffset) {
- this(batch, whitePixel, minRadius, innerRadiusPercent, startDegreesOffset);
- setStyle(skin.get(RadialGroupStyle.class));
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- * @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
- * the percentage of the radius that is cut off,
- * starting from the center of the widget.
- * @param startDegreesOffset the {@link #startDegreesOffset} that defines
- * how far from the origin the drawing begins.
- * @param totalDegreesDrawn the {@link #totalDegreesDrawn} that defines how
- * many degrees the widget will span, starting from
- * its {@link #startDegreesOffset}.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, float minRadius,
- float innerRadiusPercent, float startDegreesOffset, float totalDegreesDrawn) {
- this(batch, whitePixel, minRadius, innerRadiusPercent, startDegreesOffset, totalDegreesDrawn);
- setStyle(skin.get(RadialGroupStyle.class));
- }
-
- /**
- * See {@link RadialGroup} for a description.
- *
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param style the name of the style to be extracted from the skin.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
- */
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, String style, float minRadius) {
- this(batch, whitePixel, minRadius);
- setStyle(skin.get(style, RadialGroupStyle.class));
+ public RadialGroup(float preferredRadius) {
+ setPreferredRadius(preferredRadius);
+ constructorsCommon();
}
-
/**
* See {@link RadialGroup} for a description.
*
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param style the name of the style to be extracted from the skin.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
+ * @param preferredRadius the {@link #preferredRadius} that defines the
+ * size of the widget.
* @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
* the percentage of the radius that is cut off,
* starting from the center of the widget.
*/
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, String style, float minRadius,
- float innerRadiusPercent) {
- this(batch, whitePixel, minRadius, innerRadiusPercent);
- setStyle(skin.get(style, RadialGroupStyle.class));
+ public RadialGroup(float preferredRadius, float innerRadiusPercent) {
+ this(preferredRadius);
+ setInnerRadiusPercent(innerRadiusPercent);
}
/**
* See {@link RadialGroup} for a description.
*
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param style the name of the style to be extracted from the skin.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
+ * @param preferredRadius the {@link #preferredRadius} that defines the
+ * size of the widget.
* @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
* the percentage of the radius that is cut off,
* starting from the center of the widget.
* @param startDegreesOffset the {@link #startDegreesOffset} that defines
* how far from the origin the drawing begins.
*/
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, String style, float minRadius,
- float innerRadiusPercent, float startDegreesOffset) {
- this(batch, whitePixel, minRadius, innerRadiusPercent, startDegreesOffset);
- setStyle(skin.get(style, RadialGroupStyle.class));
+ public RadialGroup(float preferredRadius, float innerRadiusPercent,
+ float startDegreesOffset) {
+ this(preferredRadius, innerRadiusPercent);
+ setStartDegreesOffset(startDegreesOffset);
}
/**
* See {@link RadialGroup} for a description.
*
- * @param batch used to draw everything but the contained actors.
- * @param whitePixel a 1x1 white pixel.
- * @param skin defines the way the widget looks like.
- * @param style the name of the style to be extracted from the skin.
- * @param minRadius the {@link #minRadius} that defines the size of the widget.
+ * @param preferredRadius the {@link #preferredRadius} that defines the
+ * size of the widget.
* @param innerRadiusPercent the {@link #innerRadiusPercent} that defines
* the percentage of the radius that is cut off,
* starting from the center of the widget.
@@ -374,11 +147,10 @@ public RadialGroup(final Batch batch, final TextureRegion whitePixel,
* many degrees the widget will span, starting from
* its {@link #startDegreesOffset}.
*/
- public RadialGroup(final Batch batch, final TextureRegion whitePixel,
- Skin skin, String style, float minRadius,
- float innerRadiusPercent, float startDegreesOffset, float totalDegreesDrawn) {
- this(batch, whitePixel, minRadius, innerRadiusPercent, startDegreesOffset, totalDegreesDrawn);
- setStyle(skin.get(style, RadialGroupStyle.class));
+ public RadialGroup(float preferredRadius, float innerRadiusPercent,
+ float startDegreesOffset, float totalDegreesDrawn) {
+ this(preferredRadius, innerRadiusPercent, startDegreesOffset);
+ setTotalDegreesDrawn(totalDegreesDrawn);
}
@@ -390,50 +162,49 @@ public RadialGroup(final Batch batch, final TextureRegion whitePixel,
-
-
/**
* The current diameter of the widget.
- * This might not be twice the {@link #minRadius}.
+ * This might not be twice the {@link #preferredRadius}.
*
* @return {@code Math.min(getWidth(), getHeight())}
*/
- protected float getMaxDiameter() {
+ protected float getCurrentDiameter() {
return Math.min(getWidth(), getHeight());
}
/**
* The current radius of the widget.
- * This might not be {@link #minRadius}.
+ * This might not be {@link #preferredRadius}.
*
* @return {@code Math.min(getWidth(), getHeight()) / 2}
*/
- protected float getMaxRadius() {
- return getMaxDiameter()/2;
+ protected float getCurrentRadius() {
+ return getCurrentDiameter()/2;
}
@Override
public float getPrefWidth() {
- return getMaxDiameter();
+ return getCurrentDiameter();
}
@Override
public float getPrefHeight() {
- return getMaxDiameter();
+ return getCurrentDiameter();
}
@Override
public float getMinWidth() {
- return minRadius * 2;
+ return preferredRadius * 2;
}
@Override
public float getMinHeight() {
- return minRadius * 2;
+ return preferredRadius * 2;
}
@Override
public void addActor(Actor actor) {
+ // todo: this might not need to be Overriden
if(actor == null) throw new IllegalArgumentException("actor cannot be null.");
super.addActor(actor);
invalidate();
@@ -475,7 +246,7 @@ public boolean removeActor(Actor actor) {
* @return distance of this Actor's center from the center of the widget.
*/
public float getActorDistanceFromCenter(Actor actor) {
- return (getMaxRadius() + getInnerRadiusLength())/2;
+ return (getCurrentRadius() + getInnerRadiusLength())/2;
}
/**
@@ -505,7 +276,7 @@ public float getActorDistanceFromCenter(Actor actor) {
* positioned from the center of the widget.
*/
public void modifyActor(Actor actor, float degreesPerChild, float actorDistanceFromCenter) {
-
+ // todo: possibly add a default resize-value for `Image` instances here?
}
/**
@@ -534,7 +305,7 @@ public void modifyActor(Actor actor, float degreesPerChild, float actorDistanceF
*/
public float getEstimatedRadiusAt(float degreesPerChild, float actorDistanceFromCenter) {
float tmp1 = actorDistanceFromCenter * MathUtils.sinDeg(degreesPerChild/2);
- float tmp2 = getMaxRadius() - actorDistanceFromCenter;
+ float tmp2 = getCurrentRadius() - actorDistanceFromCenter;
float tmp3 = actorDistanceFromCenter - getInnerRadiusLength();
return Math.min(Math.min(tmp1, tmp2), tmp3);
}
@@ -569,167 +340,9 @@ protected void updateOrigin() {
setOrigin(getWidth()/2, getHeight()/2); // to support rotations around the center
}
- @Override
- public void draw(Batch batch, float parentAlpha) {
- drawWithShapeDrawer(batch, parentAlpha, totalDegreesDrawn);
- drawMe(batch, parentAlpha);
- }
-
- @Deprecated
- protected void drawMe(Batch batch, float parentAlpha) {
- super.draw(batch, parentAlpha);
- }
-
- /**
- * Used to propagate the parent's alpha value to the children.
- * Changes the {@link ShapeDrawer}'s color.
- *
- * @param sd the {@link ShapeDrawer} whose color will be changed.
- * @param input the {@link Color} to be copying RGB values from.
- */
- protected void propagateAlpha(ShapeDrawer sd, Color input) {
- sd.setColor(input.r, input.g, input.b, input.a * globalAlphaMultiplier);
- }
-
/**
- * Takes care of drawing everything that {@link #layout()} didn't.
- * (Basically everything but the children Actors.)
- *
- * @param batch a Batch used to draw Drawables. The {@link #sd} is used to
- * draw everything else.
- * @param parentAlpha the inherited parent alpha.
- * @param degreesToDraw how many degrees from the offset should be drawn.
- */
- protected void drawWithShapeDrawer(Batch batch, float parentAlpha, float degreesToDraw) {
-
- /* Pre-calculating */
- float bgRadian = MathUtils.degreesToRadians*degreesToDraw;
- float tmpOffset = MathUtils.degreesToRadians*(startDegreesOffset + getRotation());
- final int SIZE = getAmountOfChildren();
- float tmpRad = bgRadian / SIZE;
-
- /* Background image */
- if(style.background != null) {
- Color bc = batch.getColor();
- float restoreAlpha = bc.a;
- batch.setColor(bc.r, bc.g, bc.b, bc.a * globalAlphaMultiplier);
- if(style.background instanceof TransformDrawable) {
- ((TransformDrawable)(style.background)).draw(batch,
- getX(Align.center) - getMaxRadius(), getY(Align.center) - getMaxRadius(),
- getMaxRadius(), getMaxRadius(),
- getMaxDiameter(), getMaxDiameter(),
- getScaleX(), getScaleY(),
- getRotation());
- } else {
- style.background.draw(batch,
- getX(Align.center) - getMaxRadius(),
- getY(Align.center) - getMaxRadius(),
- getMaxDiameter(), getMaxDiameter());
- }
- batch.setColor(bc.r, bc.g, bc.b, restoreAlpha);
- }
-
- /* Rest of background */
- if(style.backgroundColor != null) {
- propagateAlpha(sd, style.backgroundColor);
- sd.sector(getX(Align.center), getY(Align.center),
- getMaxRadius()-BUFFER, tmpOffset, bgRadian); // buffer to prevent bg from sticking out from below children
- }
-
- /* Children */
- vector2.set(getX(Align.center), getY(Align.center));
- for(int i=0; i 0) {
- propagateAlpha(sd, style.separatorColor);
- sd.line(pointAtAngle(vector22, vector2, getInnerRadiusLength(), drawnRadianAngle),
- pointAtAngle(vector23, vector2, getMaxRadius(), drawnRadianAngle),
- style.separatorWidth);
- }
- }
-
- /**
- * Determines the color of the slice in which resides the Actor designated
- * by the {@code index} parameter. By default, the colors come from the way
- * you have set up your Style (anything that extends {@link RadialGroupStyle}).
- * Override this method when creating your Widget if you want to have control
- * over those colors.
- * Do not set the color of the {@link ShapeDrawer} in there: that is
- * handled internally. Just return the desired Color.
- * Here is an example:
- *
- * {@code
- * RadialGroup myWidget = new RadialGroup(shapeDrawer, myStyle, 77) {
- * public Color getColor(int index) {
- * Color fader = super.getColor(index);
- * // This will fade the slices' alpha value
- * return new Color(fader.r, fader.g, fader.b, fader.a/index);
- * }
- * };
- * }
- *
- *
- * @param index index of the child whose slice is to be drawn with the returned Color.
- * @return the Color to be used to draw the slice of the child with the given index.
- */
- public Color getColor(int index) {
- if(style.alternateSliceColor != null
- && index%2 == 1)
- return style.alternateSliceColor;
-
- if(style.sliceColor != null)
- return style.sliceColor;
-
- return TRANSPARENT;
- }
-
- protected void drawChild(Vector2 vector2, int index, float startAngle, float radian) {
- propagateAlpha(sd, getColor(index));
- sd.arc(vector2.x, vector2.y, (getMaxRadius()+ getInnerRadiusLength())/2,
- startAngle, radian, getMaxRadius()- getInnerRadiusLength());
-
- /* Circumferences */
- drawChildCircumference(vector2, startAngle, radian, getMaxRadius() - style.circumferenceWidth/2);
- if(innerRadiusPercent > 0)
- drawChildCircumference(vector2, startAngle, radian, getInnerRadiusLength() + style.circumferenceWidth/2);
- }
-
- protected void drawChildCircumference(Vector2 vector2, float startAngle, float radian, float radius) {
- if(style.circumferenceColor != null && style.circumferenceWidth > 0) {
- propagateAlpha(sd, style.circumferenceColor);
- sd.arc(vector2.x, vector2.y, radius, startAngle, radian, style.circumferenceWidth);
- }
- }
-
-
- /**
- * To get the coordinates of a point along a line traced from the center,
- * along the designated angle, at the designated distance from the center.
- *
- * @param center center point of the Circle
- * @param radius how far from the center the desired point is
- * @param radian the angle along which the line is calculated
- * @return the point associated with those parameters
- */
- public Vector2 pointAtAngle(Vector2 output, Vector2 center, float radius, float radian) {
- output.set(center.x + radius * MathUtils.cos(radian), center.y + radius * MathUtils.sin(radian));
- return output;
- }
-
- /**
- * @param x x-coordinate relative to the origin (bottom left) of the widget
- * @param y y-coordinate relative to the origin (bottom left) of the widget
+ * @param x x-coordinate relative to the bottom-left of the widget.
+ * @param y y-coordinate relative to the bottom-left of the widget.
* @param touchable if {@code true}, hit detection will respect the
* {@link #setTouchable(Touchable) touchability}.
* @return deepest child's hit at (x,y). Else, the widget itself if it's
@@ -740,23 +353,43 @@ public Actor hit(float x, float y, boolean touchable) {
if (touchable && getTouchable() == Touchable.disabled) return null;
if (!isVisible()) return null;
- localToStageCoordinates(vector2.set(x,y));
- int childIndex = findChildIndexAtStage(vector2.x,vector2.y);
- if (isValidIndex(childIndex)) {
- Actor child = getChildren().get(childIndex);
+ /* Checking all children first to catch the ones extending beyond the widget. */
+ for (Actor child : getChildren()) {
if(child.getTouchable() == Touchable.disabled)
- return this;
- child.parentToLocalCoordinates(vector2.set(x, y));
+ continue;
+ child.parentToLocalCoordinates(vector2.set(x,y));
Actor hit = child.hit(vector2.x, vector2.y, touchable);
if(hit != null)
return hit;
- else
- return this;
}
+ /* Then we want to consider the widget's boundaries itself. */
+ localToStageCoordinates(vector2.set(x,y));
+ int childIndex = findChildIndexAtStage(vector2.x,vector2.y);
+ if(isValidIndex(childIndex))
+ return this;
+
+ /* And ultimately whether some background element is hit. */
+ if(isBackgroundHit(x,y))
+ return this;
+
return null;
}
+ /**
+ * Determines whether or not the background is being hit.
+ *
+ * @see #hit(float, float, boolean)
+ * @param x x-coordinate relative to the bottom-left of the widget.
+ * @param y y-coordinate relative to the bottom-left of the widget.
+ * @return {@code true} only if some background element of the widget
+ * is being hit. (For example, if there are no background
+ * image or color, then this always returns {@code false}.)
+ */
+ public boolean isBackgroundHit(float x, float y) {
+ return false;
+ }
+
/**
* Given a coordinate, find the index of the child (if any).
*
@@ -768,7 +401,7 @@ public Actor hit(float x, float y, boolean touchable) {
public int findChildIndexAtStage(float x, float y) {
int childIndex = findIndexFromAngle(angleAtStage(x,y));
stageToLocalCoordinates(vector2.set(x,y));
- return isWithinRadii(vector2.x - getMaxRadius(), vector2.y - getMaxRadius())
+ return isWithinRadii(vector2.x - getWidth()/2, vector2.y - getHeight()/2)
? childIndex
: getAmountOfChildren(); // "getAmountOfChildren" is equivalent to "invalid"
}
@@ -801,10 +434,28 @@ public float angleAtStage(float x, float y) {
return normalizeAngle(
MathUtils.radiansToDegrees
* MathUtils.atan2(y - vector2.y, x - vector2.x)
- - getRotation() - startDegreesOffset
+ - getTotalRotation() - startDegreesOffset
);
}
+ /**
+ * To obtain the rotation value, including the rotation induced
+ * from the parent Groups.
+ * That is because calling {@link #getRotation()} in scene2d
+ * only returns the rotation value applied directly to the Actor.
+ * If a {@link Group} including this Actor is rotated, then even
+ * though the Actor appears rotated, the internal value will be 0.
+ *
+ * @return The total rotation value.
+ */
+ protected float getTotalRotation() {
+ float rotation = getRotation();
+ Group parent = getParent();
+ if(parent == null)
+ return rotation;
+ return rotation + parent.getRotation();
+ }
+
/**
* Used to ensure an angle is in between 0 and 360.
*
@@ -815,23 +466,50 @@ public float normalizeAngle(float angle) {
return ((angle % 360 + 360) % 360);
}
+ /**
+ * Given a child index, find whether or not it would be a valid candidate to
+ * highlight or select.
+ *
+ * @param index an integer that would usually be the output of
+ * {@link #findChildIndexAtStage(float, float)}.
+ * @return {@code true} only if the index is linked to a valid child sector.
+ */
+ public boolean isValidIndex(int index) {
+ return !(index <= -1 || index >= getAmountOfChildren());
+ }
+
/**
* Checks whether or not the input coordinate is in between (inclusively)
* the inner-radius and the current radius of the widget (which can
- * be bigger than {@link #minRadius} if you use {@link #setFillParent(boolean)},
- * for example).
+ * be bigger than {@link #preferredRadius} if you use
+ * {@link #setFillParent(boolean)}, for example).
*
- * @param x x-coordinate relative to the center of the widget's
- * @param y y-coordinate relative to the center of the widget's
+ * @param x x-coordinate relative to the center of the widget.
+ * @param y y-coordinate relative to the center of the widget.
* @return 'true' only if the coordinates fall within the widget's radii.
*/
public boolean isWithinRadii(float x, float y) {
float distance = pow2(x) + pow2(y);
float innerRadSquared = pow2(getInnerRadiusLength());
- float radSquared = pow2(getMaxRadius());
+ float radSquared = pow2(getCurrentRadius());
return distance >= innerRadSquared && distance <= radSquared;
}
+ /**
+ * Checks whether or not the input coordinate is within (exclusively)
+ * the inner-radius.
+ *
+ * @param x x-coordinate relative to the center of the widget.
+ * @param y y-coordinate relative to the center of the widget.
+ * @return 'true' only if the coordinates fall within the widget's
+ * inner radius.
+ */
+ public boolean isWithinInnerRadius(float x, float y) {
+ float distance = pow2(x) + pow2(y);
+ float innerRadSquared = pow2(getInnerRadiusLength());
+ return distance < innerRadSquared;
+ }
+
/**
* Returns the input to the power of 2.
*
@@ -865,19 +543,8 @@ public void centerOnScreen() {
public void centerOnActor(Actor actor) {
if(actor == null)
return;
- setPosition(actor.getX(Align.center), actor.getY(Align.center), Align.center);
- }
-
- /**
- * Given a child index, find whether or not it would be a valid candidate to
- * highlight or select.
- *
- * @param index an integer that would usually be the output of
- * {@link #findChildIndexAtStage(float, float)}.
- * @return {@code true} only if the index is linked to a valid child sector.
- */
- public boolean isValidIndex(int index) {
- return !(index <= -1 || index >= getAmountOfChildren());
+ actor.localToStageCoordinates(vector2.set(actor.getWidth()/2, actor.getHeight()/2));
+ setPosition(vector2.x, vector2.y, Align.center);
}
@@ -891,167 +558,6 @@ public void drawRudimentaryDebug() {
- /*
- =================================== STYLE ==================================
- */
-
-
- /**
- * Returns the label's style. Modifying the returned style may not have an
- * effect until {@link #setStyle(RadialGroupStyle)} is called.
- * It's probable that your code will look like this (to give you an idea):
- *
- * {@code
- * radialGroup.getStyle().whatYouWantToChange = someNewValue;
- * radialGroup.setStyle(radialGroup.getStyle());
- * }
- *
- *
- * @return the Style that defines this Widget. This style contains information
- * about what is the value of the radius or the width of the separators, for
- * example.
- */
- public RadialGroupStyle getStyle() {
- return style;
- }
-
-
- /**
- * Runs checks before assigning the style to the Widget. Only a valid style
- * will pass the test.
- *
- * @param style the style that will be checked before being assigned.
- */
- public void setStyle(RadialGroupStyle style) {
- checkStyle(style);
- this.style = style;
- invalidate();
- }
-
- /**
- * Ensures the input values for the given style are valid.
- *
- * @param style a style class you want to check properties of.
- */
- protected void checkStyle(RadialGroupStyle style) {
- if(style == null)
- throw new IllegalArgumentException("style cannot be null.");
-
- if(style.separatorWidth < 0)
- throw new IllegalArgumentException("separatorWidth cannot be negative.");
-
- if(style.circumferenceWidth < 0)
- throw new IllegalArgumentException("circumferenceWidth cannot be negative.");
-
- if(style.sliceColor == null && style.alternateSliceColor != null)
- throw new IllegalArgumentException("sliceColor must also be specified if you are defining alternateSliceColor. " +
- "You can however only specify the sliceColor, if you want.");
- }
-
- /**
- * Encompasses the characteristics that define the style of the Widget
- * to be drawn.
- */
- public static class RadialGroupStyle {
-
- /**
- * Recommended. Optional.
- * A background that will be drawn behind everything else within the Widget.
- * Be mindful of the fact that this is unaffected by any of the other
- * variables: it will be resized to fit in the whole region that
- * represents the position, width and height of the widget.
- */
- public Drawable background;
-
- /**
- * Optional.
- * A background color that, if provided, will be drawn over the
- * background image and below everything else.
- * It mostly acts as a quick set up option if you do not have an image
- * for you background.
- */
- public Color backgroundColor;
-
- /**
- * Recommended. Optional.
- * The color used by the separating lines between each item.
- * It is recommended mostly for the case where you are not defining an
- * {@link #alternateSliceColor}.
- * If you do not define a {@link #separatorWidth} along with this value,
- * no lines will be visible.
- */
- public Color separatorColor;
-
- /**
- * Recommended. Optional.
- * The color used to fill the "pie sectors" (i.e. slice) of each item.
- * Consider using a fairly low alpha value if you are providing a
- * {@link #background} {@link Drawable}.
- */
- public Color sliceColor;
-
- /**
- * Optional.
- * If this color is set, the "pie sectors" will alternate between the
- * {@link #sliceColor} and this one so that their defining region
- * is more easily distinguished.
- */
- public Color alternateSliceColor;
-
- /**
- * Optional.
- * The color used for the line that defines the circumference of the
- * Widget. If the Widget is not a complete a circle, this will only be
- * applied along the partial circumference.
- * If you have set a non-zero {@link #innerRadiusPercent} value, this will
- * also apply to the "inner radius" of your Widget.
- * If you do not define a {@link #circumferenceWidth} along with this
- * value, no circumference will be visible.
- */
- public Color circumferenceColor;
-
- /**
- * Recommended. Optional.
- * Determines how wide the lines that separate each slice will be.
- * If no {@link #separatorColor} was provided along with this value,
- * no lines will be drawn.
- */
- public float separatorWidth;
-
- /**
- * Optional.
- * Determines how wide the circumference line will be.
- * If no {@link #circumferenceColor} was provided along with this value,
- * no circumference will be drawn.
- */
- public float circumferenceWidth;
-
-
- /**
- * Encompasses the characteristics that define the style of the Widget
- * to be drawn.
- */
- public RadialGroupStyle() {
- }
-
- /**
- * Encompasses the characteristics that define the style of the Widget
- * to be drawn.
- *
- * @param style a Style to copy the parameters from.
- */
- public RadialGroupStyle(RadialGroupStyle style) {
- this.background = style.background;
- this.circumferenceWidth = style.circumferenceWidth;
- this.circumferenceColor = new Color(style.circumferenceColor);
- this.separatorWidth = style.separatorWidth;
- this.separatorColor = new Color(style.separatorColor);
- this.sliceColor = new Color(style.sliceColor);
- this.alternateSliceColor = new Color(style.alternateSliceColor);
- this.backgroundColor = new Color(style.backgroundColor);
- }
- }
-
@@ -1070,29 +576,6 @@ public int getAmountOfChildren() {
return getChildren().size;
}
-
- /**
- * @return the ShapeDrawer used to draw everything but the contained Actors.
- */
- public ShapeDrawer getShapeDrawer() {
- return sd;
- }
-
- /**
- * You probably shouldn't be messing with this, but it's provided for
- * convenience reasons.
- * For example, it's possible that your widget will be so big that
- * the {@link ShapeDrawer} will crash with an Exception while trying to
- * draw it. You would then want to use this setter to provide a brand new
- * instance which didn't override the {@code estimateSidesRequired(float, float)}
- * method to try to increase the smoothness of the curves.
- *
- * @param sd the new instance of {@link ShapeDrawer} that you want to use.
- */
- public void setShapeDrawer(ShapeDrawer sd) {
- this.sd = sd;
- }
-
/**
* @return the multiplier's value which is applied to all the alpha values
* of the things contained by the widget (slices, lines, drawables, etc.)
@@ -1115,32 +598,35 @@ public void setGlobalAlphaMultiplier(float globalAlphaMultiplier) {
}
/**
- * @see #minRadius
+ * @see #preferredRadius
* @return The radius that defines how big the Widget will be.
*/
- public float getMinRadius() {
- return minRadius;
+ public float getPreferredRadius() {
+ return preferredRadius;
}
/**
* Required.
* The radius that defines how big the Widget will be.
- * This is used as the minimal radius value if anything such as a
+ * This is generally used as the minimal radius value if anything such as a
* {@link com.badlogic.gdx.scenes.scene2d.ui.Table} ends up modifying the
* size of the widget. {@link #setFillParent(boolean)} will also end up
- * using that radius value as a minimum.
+ * using that radius value as a minimum.
+ * However, be aware that this value is not respected by the use of
+ * {@link #setWidth(float)} or {@link #setHeight(float)}. In other words, it
+ * is possible to set the size of your widget to a smaller value.
*
- * @param minRadius The value must be bigger than {@value #BUFFER}.
+ * @param preferredRadius The value must be bigger than {@value #BUFFER}.
* If the value is smaller than the current
* {@link #innerRadiusPercent} then the
* {@link #innerRadiusPercent} is set to a smaller value.
*/
- public void setMinRadius(float minRadius) {
- if(minRadius < BUFFER)
+ public void setPreferredRadius(float preferredRadius) {
+ if(preferredRadius < BUFFER)
throw new IllegalArgumentException("radius cannot be smaller than " + BUFFER + ".");
- if(minRadius != lastRadius) {
- this.minRadius = minRadius;
- lastRadius = minRadius;
+ if(preferredRadius != lastRadius) {
+ this.preferredRadius = preferredRadius;
+ lastRadius = preferredRadius;
setSize(getMinWidth(), getMinHeight()); // for orphan widgets (no parent)
@@ -1165,24 +651,24 @@ public float getInnerRadiusPercent() {
* @return {@code minRadius * innerRadiusPercent}.
*/
public float getInnerRadiusLength() {
- return getMaxRadius() * innerRadiusPercent;
+ return getCurrentRadius() * innerRadiusPercent;
}
/**
* Optional.
- * If provided, the {@link RadialGroupStyle#sliceColor} will only fill
- * the slice defined between the {@link #minRadius} and its percentage
+ * If provided, the {@link PieWidgetStyle#sliceColor} will only fill
+ * the slice defined between the {@link #preferredRadius} and its percentage
* value coming from this. A hole will be left into the middle of the Widget,
- * like a doughnut, and if a {@link RadialGroupStyle#background} or a
- * {@link RadialGroupStyle#backgroundColor} was provided, it will be visible
+ * like a doughnut, and if a {@link PieWidgetStyle#background} or a
+ * {@link PieWidgetStyle#backgroundColor} was provided, it will be visible
* in the middle.
* Actors inserted into the Widget are placed in the middle between the
- * innerRadius and the {@link #minRadius}. That is only the default behavior,
+ * innerRadius and the {@link #preferredRadius}. That is only the default behavior,
* if you want to change that, see {@link #getActorDistanceFromCenter(Actor)}.
*
* @param innerRadiusPercent How far from the center do the slices start
* being drawn, in terms of percentage of the
- * {@link #minRadius}.
+ * {@link #preferredRadius}.
* The value must be between 0 (inclusive)
* and 1 (exclusive).
*/
diff --git a/src/test/java/com/payne/games/piemenu/Demonstration.java b/src/test/java/com/payne/games/piemenu/Demonstration.java
index 605006f..a4a0665 100644
--- a/src/test/java/com/payne/games/piemenu/Demonstration.java
+++ b/src/test/java/com/payne/games/piemenu/Demonstration.java
@@ -15,7 +15,11 @@
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
-import com.badlogic.gdx.scenes.scene2d.ui.*;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
@@ -37,7 +41,7 @@ public class Demonstration extends ApplicationAdapter {
private PieMenu middleMousePie;
private PieMenu.PieMenuStyle midStyle1;
private PieMenu.PieMenuStyle midStyle2;
- private AnimatedRadialGroup radial;
+ private AnimatedPieWidget radial;
private float midStyle1InnerRadius = 24f/80;
private float midStyle2InnerRadius = 27f/80;
@@ -94,11 +98,11 @@ public void create () {
private void setUpRadialWidget(Table root) {
/* Setting up and creating the widget. */
- RadialGroup.RadialGroupStyle style = new RadialGroup.RadialGroupStyle();
+ PieWidget.PieWidgetStyle style = new PieWidget.PieWidgetStyle();
style.backgroundColor = new Color(1,1,1,1);
style.sliceColor = new Color(.4f,.4f,.4f,1);
style.alternateSliceColor = new Color(.6f,0,0,1);
- radial = new AnimatedRadialGroup(batch, whitePixel, style, 100, .5f, 0, 180);
+ radial = new AnimatedPieWidget(whitePixel, style, 100, .5f, 0, 180);
/* Populating the widget. */
for (int i = 0; i < INITIAL_CHILDREN_AMOUNT; i++) {
@@ -132,7 +136,7 @@ private void setUpButtonDragPieMenu(Table root) {
style.selectedColor = new Color(.7f,.3f,.5f,1);
style.sliceColor = new Color(0,.7f,0,1);
style.alternateSliceColor = new Color(.7f,0,0,1);
- dragPie = new AnimatedPieMenu(batch, whitePixel, style, 130, 50f/130, 180, 320);
+ dragPie = new AnimatedPieMenu(whitePixel, style, 130, 50f/130, 180, 320);
/* Customizing the behavior. */
dragPie.setInfiniteSelectionRange(true);
@@ -187,7 +191,7 @@ public void changed(ChangeEvent event, Actor actor) {
* To be used to get the user to transition directly into
* {@link InputListener#touchDragged(InputEvent, float, float, int)}
* as if he had triggered
- * {@link InputListener#touchDown(InputEvent, float, float, int, int)}.
+ * {@link InputListener#touchDown(InputEvent, float, float, int, int)}.
* I am not certain this is the recommended way of doing this, but for the
* purposes of this demonstration, it works!
*
@@ -209,7 +213,7 @@ private void setUpRightMousePieMenu() {
style.separatorColor = new Color(.1f,.1f,.1f,1);
style.downColor = new Color(.5f,.5f,.5f,1);
style.sliceColor = new Color(.33f,.33f,.33f,1);
- rightMousePie = new PieMenu(batch, whitePixel, style, 80);
+ rightMousePie = new PieMenu(whitePixel, style, 80);
/* Customizing the behavior. */
rightMousePie.setInfiniteSelectionRange(true);
@@ -268,7 +272,7 @@ private void setUpMiddleMousePieMenu() {
midStyle1 = new PieMenu.PieMenuStyle();
midStyle1.selectedColor = new Color(1,.5f,.5f,.5f);
midStyle1.background = new TextureRegionDrawable(new Texture(Gdx.files.internal("rael_pie.png")));
- middleMousePie = new PieMenu(batch, whitePixel, midStyle1, 80, midStyle1InnerRadius, 30) {
+ middleMousePie = new PieMenu(whitePixel, midStyle1, 80, midStyle1InnerRadius, 30) {
/* Since we are using Images, we want to resize them to fit within each sector. */
@Override
public void modifyActor(Actor actor, float degreesPerChild, float actorDistanceFromCenter) {
@@ -321,7 +325,7 @@ private void setUpPermaPieMenu() {
style.sliceColor = new Color(.33f,.33f,.33f,1);
style.alternateSliceColor = new Color(.25f,.25f,.25f,1);
style.circumferenceColor = new Color(0,0,0,1);
- permaPie = new PieMenu(batch, whitePixel, style, 80, 20f/80, 0 ,180);
+ permaPie = new PieMenu(whitePixel, style, 80, 20f/80, 0 ,180);
/* Adding a selection-listener. */
permaPie.addListener(new ChangeListener() {
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/CenterOnActor.java b/src/test/java/com/payne/games/piemenu/genericTests/CenterOnActor.java
new file mode 100644
index 0000000..933efc9
--- /dev/null
+++ b/src/test/java/com/payne/games/piemenu/genericTests/CenterOnActor.java
@@ -0,0 +1,116 @@
+package com.payne.games.piemenu.genericTests;
+
+import com.badlogic.gdx.ApplicationAdapter;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.scenes.scene2d.Group;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+import com.payne.games.piemenu.PieWidget;
+
+
+public class CenterOnActor extends ApplicationAdapter {
+ private Skin skin;
+ private Stage stage;
+ private Texture tmpTex;
+ private Batch batch;
+ private Label testLabel;
+ private PieWidget widget;
+
+ @Override
+ public void create() {
+
+ /* Setting up the Stage. */
+ skin = new Skin(Gdx.files.internal("skin.json"));
+ batch = new PolygonSpriteBatch();
+ stage = new Stage(new ScreenViewport(), batch);
+ Gdx.input.setInputProcessor(stage);
+ stage.setDebugAll(true);
+
+ /* Setting up the WhitePixel. */
+ Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
+ pixmap.setColor(1, 1, 1, 1);
+ pixmap.fill();
+ tmpTex = new Texture(pixmap);
+ pixmap.dispose();
+ TextureRegion whitePixel = new TextureRegion(tmpTex);
+
+
+
+
+
+ /* Adding the demo widgets. */
+ PieWidget.PieWidgetStyle style1 = new PieWidget.PieWidgetStyle();
+// style1.sliceColor = Color.ORANGE;
+// style1.alternateSliceColor = new Color(.8f, .5f, .2f, 1);
+ style1.circumferenceWidth = 2;
+ style1.circumferenceColor = Color.BLACK;
+ style1.separatorWidth = 2;
+ style1.separatorColor = Color.BLACK;
+ widget = new PieWidget(whitePixel, style1, 200, 0.9f);
+
+ for(int i=0 ; i<4 ; i++) {
+ TextButton tmp = new TextButton("XXX", skin);
+ widget.addActor(tmp);
+ }
+
+ stage.addActor(widget);
+
+
+ /* The Group to test coordinates with. */
+ Group group = new Group();
+ Table table = new Table(skin);
+ table.add(new Label("Bobbbbbbbbbbbb", skin));
+ testLabel = new Label("Test", skin);
+ table.add(testLabel);
+ group.addActor(table);
+ stage.addActor(group);
+ group.setPosition(250,250);
+ }
+
+ @Override
+ public void render() {
+
+ /* Clearing the screen and filling up the background. */
+ Gdx.gl.glClearColor(.4f, .4f, .4f, 1);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+
+ /* Updating and drawing the Stage. */
+ stage.act();
+ stage.draw();
+
+ widget.centerOnActor(testLabel);
+
+ if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
+ widget.rotateBy(Gdx.graphics.getDeltaTime() * 100);
+ System.out.println(widget.getRotation());
+ }
+
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ stage.getViewport().update(width, height, true);
+ }
+
+ @Override
+ public void dispose() {
+
+ /* Disposing is good practice! */
+ skin.dispose();
+ stage.dispose();
+ batch.dispose();
+ tmpTex.dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/DifferentActorsWidget.java b/src/test/java/com/payne/games/piemenu/genericTests/DifferentActorsWidget.java
index df6311a..4f98de0 100644
--- a/src/test/java/com/payne/games/piemenu/genericTests/DifferentActorsWidget.java
+++ b/src/test/java/com/payne/games/piemenu/genericTests/DifferentActorsWidget.java
@@ -45,12 +45,12 @@ public void create () {
style.hoverColor = Color.RED;
style.selectedColor = Color.BLUE;
style.backgroundColor = Color.ORANGE;
- menu = new PieMenu(batch, whitePixel, style, 400) {
+ menu = new PieMenu(whitePixel, style, 400) {
@Override
public float getActorDistanceFromCenter(Actor actor) {
invalidate();
return getAmountOfChildren() > 1
- ? getMaxRadius() - getChild(0).getWidth()
+ ? getCurrentRadius() - getChild(0).getWidth()
: 0;
}
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/HitInfiniteMiddle.java b/src/test/java/com/payne/games/piemenu/genericTests/HitInfiniteMiddle.java
new file mode 100644
index 0000000..04ad786
--- /dev/null
+++ b/src/test/java/com/payne/games/piemenu/genericTests/HitInfiniteMiddle.java
@@ -0,0 +1,108 @@
+package com.payne.games.piemenu.genericTests;
+
+import com.badlogic.gdx.ApplicationAdapter;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+import com.payne.games.piemenu.PieMenu;
+import com.payne.games.piemenu.PieMenu.PieMenuStyle;
+
+
+public class HitInfiniteMiddle extends ApplicationAdapter {
+ private Skin skin;
+ private Stage stage;
+ private Texture tmpTex;
+ private Batch batch;
+ private PieMenu containerWidget;
+
+ @Override
+ public void create() {
+
+ /* Setting up the Stage. */
+ skin = new Skin(Gdx.files.internal("skin.json"));
+ batch = new PolygonSpriteBatch();
+ stage = new Stage(new ScreenViewport(), batch);
+ Gdx.input.setInputProcessor(stage);
+ stage.setDebugAll(true);
+
+ /* Setting up the WhitePixel. */
+ Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
+ pixmap.setColor(1, 1, 1, 1);
+ pixmap.fill();
+ tmpTex = new Texture(pixmap);
+ pixmap.dispose();
+ TextureRegion whitePixel = new TextureRegion(tmpTex);
+
+
+
+
+
+ /* Adding the demo widgets. */
+ PieMenuStyle style1 = new PieMenuStyle();
+// style1.sliceColor = Color.ORANGE;
+// style1.alternateSliceColor = new Color(.8f, .5f, .2f, 1);
+ style1.circumferenceWidth = 2;
+ style1.circumferenceColor = Color.BLACK;
+ style1.separatorWidth = 2;
+ style1.separatorColor = Color.BLACK;
+
+ containerWidget = new PieMenu(whitePixel, style1, 200, 0.9f);
+ containerWidget.setName("MAIN");
+ containerWidget.setInfiniteSelectionRange(true);
+ containerWidget.setMiddleCancel(true);
+
+ for(int i=0 ; i<5 ; i++) {
+ TextButton tmp = new TextButton("@@@@@@@@@@@@@@@@@@", skin);
+ containerWidget.addActor(tmp);
+ }
+
+
+ stage.addActor(containerWidget);
+ containerWidget.setFillParent(true);
+ }
+
+ @Override
+ public void render() {
+
+ /* Clearing the screen and filling up the background. */
+ Gdx.gl.glClearColor(.4f, .4f, .4f, 1);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+
+ /* Updating and drawing the Stage. */
+ stage.act();
+ stage.draw();
+
+ containerWidget.centerOnScreen();
+
+ if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
+ containerWidget.rotateBy(Gdx.graphics.getDeltaTime() * 100);
+ System.out.println(containerWidget.getRotation());
+ }
+
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ stage.getViewport().update(width, height, true);
+ }
+
+ @Override
+ public void dispose() {
+
+ /* Disposing is good practice! */
+ skin.dispose();
+ stage.dispose();
+ batch.dispose();
+ tmpTex.dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/HitOutside.java b/src/test/java/com/payne/games/piemenu/genericTests/HitOutside.java
new file mode 100644
index 0000000..1d9fc1e
--- /dev/null
+++ b/src/test/java/com/payne/games/piemenu/genericTests/HitOutside.java
@@ -0,0 +1,104 @@
+package com.payne.games.piemenu.genericTests;
+
+import com.badlogic.gdx.ApplicationAdapter;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+import com.payne.games.piemenu.PieWidget;
+
+
+public class HitOutside extends ApplicationAdapter {
+ private Skin skin;
+ private Stage stage;
+ private Texture tmpTex;
+ private Batch batch;
+ private PieWidget containerWidget;
+
+ @Override
+ public void create() {
+
+ /* Setting up the Stage. */
+ skin = new Skin(Gdx.files.internal("skin.json"));
+ batch = new PolygonSpriteBatch();
+ stage = new Stage(new ScreenViewport(), batch);
+ Gdx.input.setInputProcessor(stage);
+ stage.setDebugAll(true);
+
+ /* Setting up the WhitePixel. */
+ Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
+ pixmap.setColor(1, 1, 1, 1);
+ pixmap.fill();
+ tmpTex = new Texture(pixmap);
+ pixmap.dispose();
+ TextureRegion whitePixel = new TextureRegion(tmpTex);
+
+
+
+
+
+ /* Adding the demo widgets. */
+ PieWidget.PieWidgetStyle style1 = new PieWidget.PieWidgetStyle();
+// style1.sliceColor = Color.ORANGE;
+// style1.alternateSliceColor = new Color(.8f, .5f, .2f, 1);
+ style1.circumferenceWidth = 2;
+ style1.circumferenceColor = Color.BLACK;
+ style1.separatorWidth = 2;
+ style1.separatorColor = Color.BLACK;
+ containerWidget = new PieWidget(whitePixel, style1, 200, 0.9f);
+ containerWidget.setName("MAIN");
+
+ for(int i=0 ; i<5 ; i++) {
+ TextButton tmp = new TextButton("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", skin);
+ containerWidget.addActor(tmp);
+ }
+
+
+ stage.addActor(containerWidget);
+// containerWidget.setFillParent(true);
+ }
+
+ @Override
+ public void render() {
+
+ /* Clearing the screen and filling up the background. */
+ Gdx.gl.glClearColor(.4f, .4f, .4f, 1);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+
+ /* Updating and drawing the Stage. */
+ stage.act();
+ stage.draw();
+
+ containerWidget.centerOnScreen();
+
+ if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
+ containerWidget.rotateBy(Gdx.graphics.getDeltaTime() * 100);
+ System.out.println(containerWidget.getRotation());
+ }
+
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ stage.getViewport().update(width, height, true);
+ }
+
+ @Override
+ public void dispose() {
+
+ /* Disposing is good practice! */
+ skin.dispose();
+ stage.dispose();
+ batch.dispose();
+ tmpTex.dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/MgsxTests.java b/src/test/java/com/payne/games/piemenu/genericTests/MgsxTests.java
index e4fd2fb..892f4aa 100644
--- a/src/test/java/com/payne/games/piemenu/genericTests/MgsxTests.java
+++ b/src/test/java/com/payne/games/piemenu/genericTests/MgsxTests.java
@@ -34,7 +34,7 @@ public void create() {
// Group group = new Group();
-// PieMenu menu = new PieMenu(stage.getBatch(), skin.getRegion("white"), PieMenuUtils.getStyle(), SIZE, .2f);
+// PieMenu menu = new PieMenu(skin.getRegion("white"), PieMenuUtils.getStyle(), SIZE, .2f);
// fillMenu(menu, skin, "A", "D", "E");
// group.addActor(menu);
// menu.pack();
@@ -44,7 +44,7 @@ public void create() {
// Group group2 = new Group();
-// PieMenu menu2 = new PieMenu(stage.getBatch(), skin.getRegion("white"), PieMenuUtils.getStyle(), SIZE, .2f);
+// PieMenu menu2 = new PieMenu(skin.getRegion("white"), PieMenuUtils.getStyle(), SIZE, .2f);
// fillMenu(menu2, skin, "A", "D", "E");
// group2.addActor(menu2);
// menu2.setPieMenuListener(new InputListener());
@@ -52,7 +52,7 @@ public void create() {
// stage.addActor(group2);
-// PieMenu menu3 = new PieMenu(stage.getBatch(), skin.getRegion("white"), PieMenuUtils.getStyle(), SIZE, .2f);
+// PieMenu menu3 = new PieMenu(skin.getRegion("white"), PieMenuUtils.getStyle(), SIZE, .2f);
// fillMenu(menu3, skin, "A", "D", "E");
// menu3.pack();
// menu3.setPosition(200, 200);
@@ -147,7 +147,7 @@ public SettingsPOC(Stage stage, Skin skin) {
float offsetX = spaceX;
// floating case (OK)
- menu = new PieMenu(stage.getBatch(), skin.getRegion("white"), style, SIZE, .2f);
+ menu = new PieMenu(skin.getRegion("white"), style, SIZE, .2f);
fillMenu(menu, skin, "A", "B", "C");
menu.pack();
menu.setPosition(offsetX, stage.getHeight() - menu.getHeight());
@@ -159,7 +159,7 @@ public SettingsPOC(Stage stage, Skin skin) {
// floating table case. (KO)
table = new Table(skin);
table.add("Title very long").row();
- menu = new PieMenu(stage.getBatch(), skin.getRegion("white"), style, SIZE, .2f);
+ menu = new PieMenu(skin.getRegion("white"), style, SIZE, .2f);
fillMenu(menu, skin, "A", "D", "E");
table.add(menu);
table.pack();
@@ -170,7 +170,7 @@ public SettingsPOC(Stage stage, Skin skin) {
// floating table case 2. (KO)
table = new Table(skin);
- menu = new PieMenu(stage.getBatch(), skin.getRegion("white"), style, SIZE, .2f);
+ menu = new PieMenu(skin.getRegion("white"), style, SIZE, .2f);
fillMenu(menu, skin, "A", "F", "G");
table.add(menu).row();
table.add("Title").row();
@@ -183,7 +183,7 @@ public SettingsPOC(Stage stage, Skin skin) {
// floating table with multiple. (KO)
table = new Table(skin);
for (int i = 0; i < 3; i++) {
- menu = new PieMenu(stage.getBatch(), skin.getRegion("white"), style, SIZE, .2f);
+ menu = new PieMenu(skin.getRegion("white"), style, SIZE, .2f);
fillMenu(menu, skin, "A", "H", "I");
table.add(menu);
addListeners(menu);
@@ -195,7 +195,7 @@ public SettingsPOC(Stage stage, Skin skin) {
// floating table case with grow. (KO)
table = new Table(skin);
- menu = new PieMenu(stage.getBatch(), skin.getRegion("white"), style, 10, .2f);
+ menu = new PieMenu(skin.getRegion("white"), style, 10, .2f);
fillMenu(menu, skin, "A", "J", "K");
table.add(menu).grow().row();
table.setSize(400, 300);
@@ -205,7 +205,7 @@ public SettingsPOC(Stage stage, Skin skin) {
// table case with fill parent. (OK)
table = new Table(skin);
- menu = new PieMenu(stage.getBatch(), skin.getRegion("white"), style, SIZE, .2f);
+ menu = new PieMenu(skin.getRegion("white"), style, SIZE, .2f);
fillMenu(menu, skin, "A", "L", "M");
table.add(menu).expand().right().bottom().row();
table.setFillParent(true);
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/RotatingFillParentWidget.java b/src/test/java/com/payne/games/piemenu/genericTests/RotatingFillParentWidget.java
index 84188a2..e8cebfe 100644
--- a/src/test/java/com/payne/games/piemenu/genericTests/RotatingFillParentWidget.java
+++ b/src/test/java/com/payne/games/piemenu/genericTests/RotatingFillParentWidget.java
@@ -52,7 +52,7 @@ public void create () {
style.hoverColor = Color.RED;
style.selectedColor = Color.BLUE;
style.background = new TextureRegionDrawable(new Texture(Gdx.files.internal("rael_pie.png")));
- menu = new PieMenu(batch, whitePixel, style, 80, 24f/80, 30);
+ menu = new PieMenu(whitePixel, style, 80, 24f/80, 30);
menu.setGlobalAlphaMultiplier(.5f);
for(int i=0 ; i<6 ; i++)
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/SelfContainedPieMenu.java b/src/test/java/com/payne/games/piemenu/genericTests/SelfContainedPieMenu.java
new file mode 100644
index 0000000..659070b
--- /dev/null
+++ b/src/test/java/com/payne/games/piemenu/genericTests/SelfContainedPieMenu.java
@@ -0,0 +1,116 @@
+package com.payne.games.piemenu.genericTests;
+
+import com.badlogic.gdx.ApplicationAdapter;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+import com.payne.games.piemenu.PieMenu;
+import com.payne.games.piemenu.PieWidget;
+
+
+public class SelfContainedPieMenu extends ApplicationAdapter {
+ private Skin skin;
+ private Stage stage;
+ private Texture tmpTex;
+ private Batch batch;
+ private PieWidget containerWidget;
+
+ @Override
+ public void create() {
+
+ /* Setting up the Stage. */
+ skin = new Skin(Gdx.files.internal("skin.json"));
+ batch = new PolygonSpriteBatch();
+ stage = new Stage(new ScreenViewport(), batch);
+ Gdx.input.setInputProcessor(stage);
+ stage.setDebugAll(true);
+
+ /* Setting up the WhitePixel. */
+ Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
+ pixmap.setColor(1, 1, 1, 1);
+ pixmap.fill();
+ tmpTex = new Texture(pixmap);
+ pixmap.dispose();
+ TextureRegion whitePixel = new TextureRegion(tmpTex);
+
+
+
+
+
+ /* Adding the demo widgets. */
+ PieWidget.PieWidgetStyle style1 = new PieWidget.PieWidgetStyle();
+// style1.sliceColor = Color.ORANGE;
+// style1.alternateSliceColor = new Color(.8f, .5f, .2f, 1);
+ style1.circumferenceWidth = 2;
+ style1.circumferenceColor = Color.BLACK;
+ style1.separatorWidth = 2;
+ style1.separatorColor = Color.BLACK;
+ containerWidget = new PieWidget(whitePixel, style1, 500, 0.5f);
+ containerWidget.setName("MAIN");
+
+ PieMenu.PieMenuStyle style2 = new PieMenu.PieMenuStyle();
+ style2.hoverColor = Color.GREEN;
+ style2.selectedColor = Color.MAGENTA;
+ style2.backgroundColor = Color.BROWN;
+ for(int i=0 ; i<5 ; i++) {
+ PieMenu tmp = new PieMenu(whitePixel, style2, 110);
+ tmp.setName("menu " + i);
+ containerWidget.addActor(tmp);
+ for(int j=0 ; j<5 ; j++)
+ tmp.addActor(new Label(i + " " + j, skin));
+// tmp.setWidth(50);
+// tmp.setHeight(50);
+
+ }
+
+
+ stage.addActor(containerWidget);
+// containerWidget.setWidth(1600);
+ containerWidget.setFillParent(true);
+ }
+
+ @Override
+ public void render() {
+
+ /* Clearing the screen and filling up the background. */
+ Gdx.gl.glClearColor(.4f, .4f, .4f, 1);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+
+ /* Updating and drawing the Stage. */
+ stage.act();
+ stage.draw();
+
+ containerWidget.centerOnScreen();
+
+ if (Gdx.input.isKeyPressed(Input.Keys.SPACE)) {
+ containerWidget.rotateBy(Gdx.graphics.getDeltaTime() * 100);
+ System.out.println(containerWidget.getRotation());
+ }
+
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ stage.getViewport().update(width, height, true);
+ }
+
+ @Override
+ public void dispose() {
+
+ /* Disposing is good practice! */
+ skin.dispose();
+ stage.dispose();
+ batch.dispose();
+ tmpTex.dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/ShapeDrawerLimit.java b/src/test/java/com/payne/games/piemenu/genericTests/ShapeDrawerLimit.java
index 7255417..21c44d8 100644
--- a/src/test/java/com/payne/games/piemenu/genericTests/ShapeDrawerLimit.java
+++ b/src/test/java/com/payne/games/piemenu/genericTests/ShapeDrawerLimit.java
@@ -52,7 +52,7 @@ public void create() {
style1.hoverColor = Color.RED;
style1.selectedColor = Color.BLUE;
style1.backgroundColor = Color.ORANGE;
- menu = new PieMenu(batch, whitePixel, style1, 250); // at "5092" it crashes
+ menu = new PieMenu(whitePixel, style1, 250); // at "5092" it crashes
for(int i=0 ; i<5 ; i++)
menu.addActor(new Label("menu " + i, skin));
diff --git a/src/test/java/com/payne/games/piemenu/genericTests/TableWidgets.java b/src/test/java/com/payne/games/piemenu/genericTests/TableWidgets.java
index 435fdaa..084c9a7 100644
--- a/src/test/java/com/payne/games/piemenu/genericTests/TableWidgets.java
+++ b/src/test/java/com/payne/games/piemenu/genericTests/TableWidgets.java
@@ -10,12 +10,7 @@
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.scenes.scene2d.Stage;
-import com.badlogic.gdx.scenes.scene2d.ui.Button;
-import com.badlogic.gdx.scenes.scene2d.ui.ImageTextButton;
-import com.badlogic.gdx.scenes.scene2d.ui.Label;
-import com.badlogic.gdx.scenes.scene2d.ui.Skin;
-import com.badlogic.gdx.scenes.scene2d.ui.Table;
-import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.payne.games.piemenu.PieMenu;
@@ -64,7 +59,7 @@ public void create () {
style1.hoverColor = Color.RED;
style1.selectedColor = Color.BLUE;
style1.backgroundColor = Color.ORANGE;
- PieMenu menu1 = new PieMenu(batch, whitePixel, style1, 80);
+ PieMenu menu1 = new PieMenu(whitePixel, style1, 80);
menu1.setName("left widget");
for(int i=0 ; i<5 ; i++)
@@ -80,7 +75,7 @@ public void create () {
style2.hoverColor = Color.RED;
style2.selectedColor = Color.BLUE;
style2.backgroundColor = Color.ORANGE;
- PieMenu menu2 = new PieMenu(batch, whitePixel, style2, 120);
+ PieMenu menu2 = new PieMenu(whitePixel, style2, 120);
menu2.setName("right widget");
for(int i=0 ; i<5 ; i++)
@@ -99,7 +94,7 @@ public void create () {
style3.hoverColor = Color.RED;
style3.selectedColor = Color.BLUE;
style3.backgroundColor = Color.ORANGE;
- PieMenu menu3 = new PieMenu(batch, whitePixel, style3, 40);
+ PieMenu menu3 = new PieMenu(whitePixel, style3, 40);
for(int i=0 ; i<5 ; i++)
menu3.addActor(new Label("menu " + i, skin));
diff --git a/src/test/java/com/payne/games/piemenu/individuals/ButtonBound.java b/src/test/java/com/payne/games/piemenu/individuals/ButtonBound.java
index 80dbdf0..55cabf2 100644
--- a/src/test/java/com/payne/games/piemenu/individuals/ButtonBound.java
+++ b/src/test/java/com/payne/games/piemenu/individuals/ButtonBound.java
@@ -67,7 +67,7 @@ public void create () {
style.selectedColor = new Color(.7f,.3f,.5f,1);
style.sliceColor = new Color(0,.7f,0,1);
style.alternateSliceColor = new Color(.7f,0,0,1);
- menu = new AnimatedPieMenu(batch, whitePixel, style, 130, 50f/130, 180, 320);
+ menu = new AnimatedPieMenu(whitePixel, style, 130, 50f/130, 180, 320);
/* Customizing the behavior. */
menu.setInfiniteSelectionRange(true);
diff --git a/src/test/java/com/payne/games/piemenu/individuals/ButtonToggle.java b/src/test/java/com/payne/games/piemenu/individuals/ButtonToggle.java
index 498b8c1..91de7bf 100644
--- a/src/test/java/com/payne/games/piemenu/individuals/ButtonToggle.java
+++ b/src/test/java/com/payne/games/piemenu/individuals/ButtonToggle.java
@@ -18,8 +18,8 @@
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
-import com.payne.games.piemenu.AnimatedRadialGroup;
-import com.payne.games.piemenu.RadialGroup;
+import com.payne.games.piemenu.AnimatedPieWidget;
+import com.payne.games.piemenu.PieWidget;
public class ButtonToggle extends ApplicationAdapter {
@@ -27,7 +27,7 @@ public class ButtonToggle extends ApplicationAdapter {
private Stage stage;
private Texture tmpTex;
private Batch batch;
- private AnimatedRadialGroup radGroup;
+ private AnimatedPieWidget radGroup;
@Override
@@ -60,13 +60,13 @@ public void create () {
\==================================================================== */
/* Setting up and creating the widget. */
- RadialGroup.RadialGroupStyle style = new RadialGroup.RadialGroupStyle();
+ PieWidget.PieWidgetStyle style = new PieWidget.PieWidgetStyle();
style.sliceColor = new Color(1,1,1,.2f);
style.separatorWidth = 2;
style.circumferenceWidth = 2;
style.circumferenceColor = Color.BLACK;
style.separatorColor = style.circumferenceColor;
- radGroup = new AnimatedRadialGroup(batch, whitePixel, style, 110, 50f/110, 315, 270);
+ radGroup = new AnimatedPieWidget(whitePixel, style, 110, 50f/110, 315, 270);
/* Populating the widget. */
for (int i = 0; i < 8; i++) {
diff --git a/src/test/java/com/payne/games/piemenu/individuals/ClickDrag.java b/src/test/java/com/payne/games/piemenu/individuals/ClickDrag.java
index 81432c7..d9e5a99 100644
--- a/src/test/java/com/payne/games/piemenu/individuals/ClickDrag.java
+++ b/src/test/java/com/payne/games/piemenu/individuals/ClickDrag.java
@@ -64,7 +64,7 @@ public void create () {
style.separatorColor = new Color(.1f,.1f,.1f,1);
style.downColor = new Color(.5f,.5f,.5f,1);
style.sliceColor = new Color(.33f,.33f,.33f,1);
- menu = new PieMenu(batch, whitePixel, style, 80);
+ menu = new PieMenu(whitePixel, style, 80);
/* Customizing the behavior. */
menu.setInfiniteSelectionRange(true);
diff --git a/src/test/java/com/payne/games/piemenu/individuals/ClickToggle.java b/src/test/java/com/payne/games/piemenu/individuals/ClickToggle.java
index f624ff4..add1fd7 100644
--- a/src/test/java/com/payne/games/piemenu/individuals/ClickToggle.java
+++ b/src/test/java/com/payne/games/piemenu/individuals/ClickToggle.java
@@ -56,7 +56,7 @@ public void create () {
PieMenu.PieMenuStyle style = new PieMenu.PieMenuStyle();
style.background = new TextureRegionDrawable(new Texture(Gdx.files.internal("rael_pie.png"))); // image background!
style.selectedColor = new Color(1,.5f,.5f,.5f);
- menu = new PieMenu(batch, whitePixel, style, 80, 24f/80, 30) {
+ menu = new PieMenu(whitePixel, style, 80, 24f/80, 30) {
/* Since we are using Images, we want to resize them to fit within each sector. */
@Override
public void modifyActor(Actor actor, float degreesPerChild, float actorDistanceFromCenter) {
diff --git a/src/test/java/com/payne/games/piemenu/individuals/CustomAnimation.java b/src/test/java/com/payne/games/piemenu/individuals/CustomAnimation.java
index b7936d8..3af8a03 100644
--- a/src/test/java/com/payne/games/piemenu/individuals/CustomAnimation.java
+++ b/src/test/java/com/payne/games/piemenu/individuals/CustomAnimation.java
@@ -52,13 +52,13 @@ protected int estimateSidesRequired(float radiusX, float radiusY) {
style.downColor = new Color(1,.05f,.05f,.4f);
style.hoverColor = new Color(.8f,.8f,.8f,.05f);
style.hoverSelectedColor = new Color(1,.2f,.2f,.55f);
- pieMenu = new PieMenu(batch, skin.getRegion("white"), style, BASE_RADIUS) {
+ pieMenu = new PieMenu(skin.getRegion("white"), style, BASE_RADIUS) {
@Override
public float getActorDistanceFromCenter(Actor actor) {
/* We want the Labels to be placed closer to the edge than the default value. */
return getAmountOfChildren() > 1
- ? getMaxRadius() - getChild(0).getWidth()
+ ? getCurrentRadius() - getChild(0).getWidth()
: 0;
}
@@ -69,7 +69,7 @@ public void act(float delta) {
/* Our custom animation! */
time += delta*5;
pieMenu.setStartDegreesOffset((time * 10) % 360);
- pieMenu.setMinRadius(MathUtils.sin(time) * 20 + BASE_RADIUS);
+ pieMenu.setPreferredRadius(MathUtils.sin(time) * 20 + BASE_RADIUS);
// pieMenu.setInnerRadius(Math.abs(MathUtils.sin(time)/(float)Math.PI +.1f));
pieMenu.centerOnScreen();
}
diff --git a/src/test/java/com/payne/games/piemenu/individuals/KeyMap.java b/src/test/java/com/payne/games/piemenu/individuals/KeyMap.java
index 3f8f91b..d547f8a 100644
--- a/src/test/java/com/payne/games/piemenu/individuals/KeyMap.java
+++ b/src/test/java/com/payne/games/piemenu/individuals/KeyMap.java
@@ -13,17 +13,14 @@
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
-import com.badlogic.gdx.scenes.scene2d.ui.Container;
-import com.badlogic.gdx.scenes.scene2d.ui.Image;
-import com.badlogic.gdx.scenes.scene2d.ui.Label;
-import com.badlogic.gdx.scenes.scene2d.ui.Skin;
-import com.badlogic.gdx.scenes.scene2d.ui.Stack;
+import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import com.payne.games.piemenu.PieMenu;
+
import java.util.HashSet;
@@ -63,7 +60,7 @@ public void create () {
style.background = new TextureRegionDrawable(new Texture(Gdx.files.internal("rael_pie.png"))); // image background!
style.selectedColor = new Color(1,.5f,.5f,.5f);
style.downColor = new Color(1,.8f,.8f,.5f);
- menu = new PieMenu(batch, whitePixel, style, 80, 24f/80, 30) {
+ menu = new PieMenu(whitePixel, style, 80, 24f/80, 30) {
/* Since we are using Images, we want to resize them to fit within each sector. */
@Override
public void modifyActor(Actor actor, float degreesPerChild, float actorDistanceFromCenter) {
diff --git a/src/test/java/com/payne/games/piemenu/individuals/Permanent.java b/src/test/java/com/payne/games/piemenu/individuals/Permanent.java
index c953ad6..6a37bc6 100644
--- a/src/test/java/com/payne/games/piemenu/individuals/Permanent.java
+++ b/src/test/java/com/payne/games/piemenu/individuals/Permanent.java
@@ -61,7 +61,7 @@ public void create () {
style.sliceColor = new Color(.33f,.33f,.33f,1);
style.alternateSliceColor = new Color(.25f,.25f,.25f,1);
style.circumferenceColor = new Color(0,0,0,1);
- menu = new PieMenu(batch, whitePixel, style, 100, 30f/100, 0 ,180);
+ menu = new PieMenu(whitePixel, style, 100, 30f/100, 0 ,180);
/* Adding a selection-listener. */
menu.addListener(new ChangeListener() {
diff --git a/src/test/java/com/payne/games/piemenu/individuals/RadialButtons.java b/src/test/java/com/payne/games/piemenu/individuals/RadialButtons.java
new file mode 100644
index 0000000..b8a4b19
--- /dev/null
+++ b/src/test/java/com/payne/games/piemenu/individuals/RadialButtons.java
@@ -0,0 +1,142 @@
+package com.payne.games.piemenu.individuals;
+
+import com.badlogic.gdx.ApplicationAdapter;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.g2d.Batch;
+import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
+import com.badlogic.gdx.scenes.scene2d.Actor;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
+import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
+import com.badlogic.gdx.utils.Align;
+import com.badlogic.gdx.utils.viewport.ScreenViewport;
+import com.payne.games.piemenu.PieMenu;
+import com.payne.games.piemenu.RadialGroup;
+
+
+public class RadialButtons extends ApplicationAdapter {
+ private Skin skin;
+ private Stage stage;
+ private Batch batch;
+ private RadialGroup menu;
+
+ /* For the demonstration's purposes. Not actually necessary. */
+ private float red = .25f;
+ private float blue = .75f;
+ private float green = .25f;
+
+
+ @Override
+ public void create () {
+
+ /* Setting up the Stage. */
+ skin = new Skin(Gdx.files.internal("skin.json"));
+ batch = new PolygonSpriteBatch();
+ stage = new Stage(new ScreenViewport(), batch);
+ Gdx.input.setInputProcessor(stage);
+
+
+
+ /* ====================================================================\
+ | HERE BEGINS THE MORE SPECIFIC CODE |
+ \==================================================================== */
+
+ /* Setting up and creating the widget. */
+ PieMenu.PieMenuStyle style = new PieMenu.PieMenuStyle();
+ style.backgroundColor = new Color(1,1,1,.3f);
+ style.selectedColor = new Color(.7f,.3f,.5f,1);
+ style.sliceColor = new Color(0,.7f,0,1);
+ style.alternateSliceColor = new Color(.7f,0,0,1);
+ menu = new RadialGroup(200, .7f);
+
+ /* Populating the widget. */
+ for (int i = 0; i < 9; i++) {
+ final int tmp = i;
+ String name;
+ switch(i) {
+ case 0:
+ name = "-BLUE-";
+ break;
+ case 3:
+ name = "-RED-";
+ break;
+ case 6:
+ name = "-GREEN-";
+ break;
+ default:
+ name = "white";
+ break;
+ }
+ TextButton btn = new TextButton(name, skin);
+ btn.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ switch(tmp) {
+ case 0:
+ red = .25f;
+ blue = .75f;
+ green = .25f;
+ break;
+ case 3:
+ red = .75f;
+ blue = .25f;
+ green = .25f;
+ break;
+ case 6:
+ red = .25f;
+ blue = .25f;
+ green = .75f;
+ break;
+ default:
+ red = .75f;
+ blue = .75f;
+ green = .75f;
+ break;
+ }
+ }
+ });
+ menu.addActor(btn);
+ }
+
+ /* Setting up the demo-button. */
+ final TextButton textButton = new TextButton("Show buttons", skin);
+ textButton.addListener(new ChangeListener() {
+ @Override
+ public void changed(ChangeEvent event, Actor actor) {
+ menu.setVisible(!menu.isVisible());
+ }
+ });
+ textButton.setPosition(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2, Align.center);
+ stage.addActor(textButton);
+
+ /* Including the widget in the Stage. */
+ stage.addActor(menu);
+ menu.setVisible(false);
+ menu.centerOnActor(textButton);
+ }
+
+
+ @Override
+ public void render () {
+
+ /* Clearing the screen and filling up the background. */
+ Gdx.gl.glClearColor(red, green, blue, 1); // updated with the menu
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+
+ /* Drawing the Stage (no need to update with `Stage#act()`). */
+ stage.draw();
+ }
+
+
+ @Override
+ public void dispose () {
+
+ /* Disposing is good practice! */
+ stage.dispose();
+ batch.dispose();
+ skin.dispose();
+ }
+}