aboutsummaryrefslogtreecommitdiffstats
path: root/ardor3d-ui/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'ardor3d-ui/src/main')
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/IPopOver.java29
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java46
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenu.java253
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenuItem.java34
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java4
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageArcBackdrop.java73
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageDiskBackdrop.java111
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidArcBackdrop.java144
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidDiskBackdrop.java118
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java10
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java38
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIArc.java266
-rw-r--r--ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIDisk.java143
-rw-r--r--ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.pngbin20798 -> 19730 bytes
14 files changed, 1245 insertions, 24 deletions
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/IPopOver.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/IPopOver.java
new file mode 100644
index 0000000..01dfdc7
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/IPopOver.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.renderer.Renderer;
+
+public interface IPopOver {
+
+ public abstract void showAt(int x, int y);
+
+ public abstract void setHud(UIHud hud);
+
+ public abstract UIComponent getUIComponent(int hudX, int hudY);
+
+ public abstract void onDraw(Renderer renderer);
+
+ public abstract void updateGeometricState(double time, boolean initiator);
+
+ public abstract void close();
+
+} \ No newline at end of file
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java
index 0ece8fa..391cc1b 100644
--- a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIHud.java
@@ -117,9 +117,9 @@ public class UIHud extends Node {
private MouseManager _mouseManager;
/**
- * The list of currently displayed popup menus, with each entry being a submenu of the one previous.
+ * The list of currently displayed pop-overs, with each entry being a "child" of the one previous.
*/
- private final List<UIPopupMenu> _popupMenus = Lists.newArrayList();
+ private final List<IPopOver> _popovers = Lists.newArrayList();
/**
* Construct a new UIHud
@@ -247,9 +247,11 @@ public class UIHud extends Node {
*/
public UIComponent getUIComponent(final int x, final int y) {
UIComponent found = null;
- for (int i = _popupMenus.size(); --i >= 0;) {
- final UIPopupMenu menu = _popupMenus.get(i);
- found = menu.getUIComponent(x, y);
+
+ // check for a popover first
+ for (int i = _popovers.size(); --i >= 0;) {
+ final IPopOver popover = _popovers.get(i);
+ found = popover.getUIComponent(x, y);
if (found != null) {
return found;
}
@@ -339,9 +341,9 @@ public class UIHud extends Node {
child.onDraw(r);
}
}
- if (!_popupMenus.isEmpty()) {
- for (i = 0, max = _popupMenus.size(); i < max; i++) {
- _popupMenus.get(i).onDraw(r);
+ if (!_popovers.isEmpty()) {
+ for (i = 0, max = _popovers.size(); i < max; i++) {
+ _popovers.get(i).onDraw(r);
}
}
if (_ttip != null && _ttip.isVisible()) {
@@ -360,9 +362,9 @@ public class UIHud extends Node {
@Override
public void updateGeometricState(final double time, final boolean initiator) {
super.updateGeometricState(time, initiator);
- if (!_popupMenus.isEmpty()) {
- for (int i = 0, max = _popupMenus.size(); i < max; i++) {
- _popupMenus.get(i).updateGeometricState(time, true);
+ if (!_popovers.isEmpty()) {
+ for (int i = 0, max = _popovers.size(); i < max; i++) {
+ _popovers.get(i).updateGeometricState(time, true);
}
}
if (_ttip != null && _ttip.isVisible()) {
@@ -680,7 +682,7 @@ public class UIHud extends Node {
// bring any clicked components to front
final UIComponent component = over.getTopLevelComponent();
- if (component != null && !(component instanceof UIPopupMenu)) {
+ if (component != null && !(component instanceof IPopOver)) {
bringToFront(component);
closePopupMenus();
}
@@ -858,10 +860,10 @@ public class UIHud extends Node {
}
public void closePopupMenus() {
- for (final UIPopupMenu menu : _popupMenus) {
+ for (final IPopOver menu : _popovers) {
menu.close();
}
- _popupMenus.clear();
+ _popovers.clear();
}
public void closePopupMenusAfter(final Object parent) {
@@ -871,8 +873,8 @@ public class UIHud extends Node {
}
boolean found = false;
- for (final Iterator<UIPopupMenu> it = _popupMenus.iterator(); it.hasNext();) {
- final UIPopupMenu pMenu = it.next();
+ for (final Iterator<IPopOver> it = _popovers.iterator(); it.hasNext();) {
+ final IPopOver pMenu = it.next();
if (found) {
pMenu.close();
it.remove();
@@ -882,14 +884,14 @@ public class UIHud extends Node {
}
}
- public void showPopupMenu(final UIPopupMenu menu) {
+ public void showPopOver(final IPopOver pop) {
closePopupMenus();
- _popupMenus.add(menu);
- menu.setHud(this);
+ _popovers.add(pop);
+ pop.setHud(this);
}
- public void showSubPopupMenu(final UIPopupMenu menu) {
- _popupMenus.add(menu);
- menu.setHud(this);
+ public void showSubPopupMenu(final IPopOver pop) {
+ _popovers.add(pop);
+ pop.setHud(this);
}
}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenu.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenu.java
new file mode 100644
index 0000000..206d2b1
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenu.java
@@ -0,0 +1,253 @@
+/**
+ * Copyright (c) 2008-2017 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import java.util.List;
+
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Rectangle2;
+import com.ardor3d.math.Vector2;
+import com.ardor3d.scenegraph.Spatial;
+import com.google.common.collect.Lists;
+
+/**
+ * A special frame meant to display menu items.
+ */
+public class UIPieMenu extends UIContainer implements IPopOver {
+
+ public static final int DEFAULT_INNER_RADIUS = 50;
+
+ private int _innerRadius, _outerRadius;
+ private double _radians = 1.0;
+
+ private boolean _menuDirty = true;
+
+ private UIPieMenuItem _center;
+
+ public UIPieMenu(final UIHud hud) {
+ this(hud, UIPieMenu.DEFAULT_INNER_RADIUS, Math.min(hud.getWidth() / 2, hud.getHeight() / 2));
+ }
+
+ public UIPieMenu(final UIHud hud, final int innerRadius, final int outerRadius) {
+ super();
+ _innerRadius = innerRadius;
+ _outerRadius = outerRadius;
+ setHud(hud);
+ applySkin();
+ }
+
+ @Override
+ public void showAt(final int x, final int y) {
+ setHudXY(x - _outerRadius, y - _outerRadius);
+ updateGeometricState(0, true);
+ }
+
+ @Override
+ public void setHud(final UIHud hud) {
+ _parent = hud;
+ attachedToHud();
+ }
+
+ public int getInnerRadius() {
+ return _innerRadius;
+ }
+
+ public int getOuterRadius() {
+ return _outerRadius;
+ }
+
+ public void setInnerRadius(final int radius) {
+ _menuDirty = true;
+ _innerRadius = radius;
+ }
+
+ public void setOuterRadius(final int radius) {
+ _menuDirty = true;
+ _outerRadius = radius;
+ }
+
+ public double getCurrentArcLength() {
+ return _radians;
+ }
+
+ public void addItem(final UIPieMenuItem item) {
+ _menuDirty = true;
+ add(item);
+ }
+
+ public void removeItem(final UIPieMenuItem item) {
+ _menuDirty = true;
+ remove(item);
+ }
+
+ public UIPieMenuItem getCenterItem() {
+ return _center;
+ }
+
+ public void setCenterItem(final UIPieMenuItem item) {
+ _menuDirty = true;
+ if (_center != null) {
+ remove(_center);
+ }
+ if (item != null) {
+ add(item);
+ }
+ _center = item;
+ }
+
+ public void clearCenterItem() {
+ setCenterItem(null);
+ }
+
+ public void clearItems() {
+ _menuDirty = true;
+ removeAllComponents();
+ }
+
+ @Override
+ public UIComponent getUIComponent(final int hudX, final int hudY) {
+ final Vector2 vec = new Vector2(hudX - getHudX() - _outerRadius, hudY - _outerRadius);
+
+ // check we are inside the pie
+ final double distSq = vec.lengthSquared();
+ if (distSq < _innerRadius * _innerRadius) {
+ return _center != null ? _center : this;
+ }
+ if (distSq > _outerRadius * _outerRadius) {
+ return this;
+ }
+
+ vec.normalizeLocal();
+
+ double r = Math.atan2(1, 0) - Math.atan2(vec.getY(), vec.getX());
+
+ r += _radians / 2;
+ if (r < 0) {
+ r += MathUtils.TWO_PI;
+ }
+
+ int index = (int) (r / _radians);
+ for (int i = 0; i < getNumberOfChildren(); i++) {
+ final Spatial s = getChild(i);
+ if (s == _center) {
+ continue;
+ }
+ if (s instanceof UIComponent) {
+ if (index == 0) {
+ return (UIComponent) s;
+ }
+ index--;
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public void layout() {
+ if (!_menuDirty) {
+ return;
+ }
+
+ final List<Spatial> content = getChildren();
+ if (content == null) {
+ return;
+ }
+
+ // gather our components
+ final List<UIComponent> comps = Lists.newArrayList();
+ final Rectangle2 storeA = Rectangle2.fetchTempInstance();
+ for (int i = 0; i < content.size(); i++) {
+ final Spatial spat = content.get(i);
+ if (spat instanceof UIComponent) {
+ final UIComponent comp = (UIComponent) spat;
+ final Rectangle2 minRect = comp.getRelativeMinComponentBounds(storeA);
+ comp.fitComponentIn(minRect.getWidth(), minRect.getHeight());
+ if (comp == _center) {
+ final Rectangle2 rect = comp.getRelativeComponentBounds(storeA);
+ comp.setLocalXY(_outerRadius - rect.getWidth() / 2, _outerRadius - rect.getHeight() / 2);
+ continue;
+ }
+ comps.add(comp);
+ }
+ }
+
+ // if we don't have components to layout, exit
+ if (comps.isEmpty()) {
+ Rectangle2.releaseTempInstance(storeA);
+ return;
+ }
+
+ // Figure out slice size
+ _radians = MathUtils.TWO_PI / Math.max(2, comps.size());
+ final int radius = (_innerRadius + _outerRadius) / 2;
+ double position = 0;
+ for (int i = 0, maxI = comps.size(); i < maxI; i++) {
+ final UIComponent comp = comps.get(i);
+
+ final Rectangle2 rect = comp.getRelativeComponentBounds(storeA);
+ final int x = (int) MathUtils.round(radius * MathUtils.sin(position));
+ final int y = (int) MathUtils.round(radius * MathUtils.cos(position));
+
+ comp.setLocalXY(_outerRadius + x - rect.getWidth() / 2, _outerRadius + y - rect.getHeight() / 2);
+
+ // step forward
+ position += _radians;
+ }
+
+ Rectangle2.releaseTempInstance(storeA);
+ _menuDirty = false;
+ }
+
+ @Override
+ public void updateMinimumSizeFromContents() {
+ setMinimumContentSize(_outerRadius * 2, _outerRadius * 2);
+ }
+
+ @Override
+ public void close() {
+ final UIHud hud = getHud();
+ if (hud == null) {
+ throw new IllegalStateException("UIPieMenu is not attached to a hud.");
+ }
+
+ // Close any open tooltip
+ hud.getTooltip().setVisible(false);
+
+ // clear any resources for standin
+ clearStandin();
+
+ hud.remove(this);
+ _parent = null;
+ }
+
+ public int getSliceIndex(final UIPieMenuItem item) {
+ final List<Spatial> content = getChildren();
+ if (content == null) {
+ return -1;
+ }
+
+ int x = 0;
+ for (int i = 0; i < content.size(); i++) {
+ final Spatial spat = content.get(i);
+ if (spat == _center) {
+ continue;
+ }
+ if (spat == item) {
+ return x;
+ }
+ if (spat instanceof UIPieMenuItem) {
+ x++;
+ }
+ }
+
+ return -1;
+ }
+} \ No newline at end of file
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenuItem.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenuItem.java
new file mode 100644
index 0000000..cd97024
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPieMenuItem.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2008-2017 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui;
+
+import com.ardor3d.extension.ui.event.ActionListener;
+import com.ardor3d.extension.ui.util.SubTex;
+
+/**
+ *
+ */
+public class UIPieMenuItem extends UIMenuItem {
+
+ public UIPieMenuItem(final String text) {
+ this(text, null);
+ }
+
+ public UIPieMenuItem(final String text, final SubTex icon) {
+ this(text, icon, true, null);
+ }
+
+ public UIPieMenuItem(final String text, final SubTex icon, final boolean closeMenuOnSelect,
+ final ActionListener listener) {
+ super(text, icon, closeMenuOnSelect, listener);
+ }
+
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java
index 11df42b..2050865 100644
--- a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/UIPopupMenu.java
@@ -17,7 +17,7 @@ import com.ardor3d.extension.ui.util.Insets;
/**
* A special frame meant to display menu items.
*/
-public class UIPopupMenu extends UIFrame {
+public class UIPopupMenu extends UIFrame implements IPopOver {
public UIPopupMenu() {
super(null, EnumSet.noneOf(UIFrame.FrameButtons.class));
@@ -25,6 +25,7 @@ public class UIPopupMenu extends UIFrame {
applySkin();
}
+ @Override
public void showAt(final int x, int y) {
final int width = getLocalComponentWidth();
final int height = getLocalComponentHeight();
@@ -49,6 +50,7 @@ public class UIPopupMenu extends UIFrame {
updateGeometricState(0, true);
}
+ @Override
public void setHud(final UIHud hud) {
_parent = hud;
attachedToHud();
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageArcBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageArcBackdrop.java
new file mode 100644
index 0000000..9df7596
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageArcBackdrop.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.util.SubTex;
+import com.ardor3d.extension.ui.util.UIArc;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.state.TextureState;
+
+public class ImageArcBackdrop extends SolidArcBackdrop {
+
+ /** The image to draw. */
+ protected SubTex _image = null;
+
+ protected TextureState _texState = new TextureState();
+
+ /** The arc used across all arc backdrops to render with. */
+ private static UIArc _standin = SolidArcBackdrop.createStandinArc();
+
+ /**
+ * Construct this back drop, using the given image.
+ *
+ * @param image
+ */
+ public ImageArcBackdrop(final SubTex image) {
+ this(image, ColorRGBA.WHITE);
+ }
+
+ /**
+ * Construct this back drop, using the given image and color.
+ *
+ * @param image
+ * the image to draw
+ * @param color
+ * the color of the backdrop
+ */
+ public ImageArcBackdrop(final SubTex image, final ReadOnlyColorRGBA color) {
+ super(color);
+ setImage(image);
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+
+ if (_texState.getNumberOfSetTextures() == 0 || _texState.getTexture().getTextureKey() == null
+ || !_texState.getTexture().getTextureKey().equals(_image.getTexture().getTextureKey())) {
+ _texState.setTexture(_image.getTexture());
+ ImageArcBackdrop._standin.setRenderState(_texState);
+ ImageArcBackdrop._standin.updateWorldRenderStates(false);
+ }
+
+ drawBackdrop(ImageArcBackdrop._standin, renderer, comp, _image);
+ }
+
+ public SubTex getImage() {
+ return _image;
+ }
+
+ public void setImage(final SubTex image) {
+ _image = image;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageDiskBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageDiskBackdrop.java
new file mode 100644
index 0000000..c373ad4
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/ImageDiskBackdrop.java
@@ -0,0 +1,111 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.UIPieMenu;
+import com.ardor3d.extension.ui.util.Insets;
+import com.ardor3d.extension.ui.util.SubTex;
+import com.ardor3d.extension.ui.util.UIDisk;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.state.TextureState;
+
+public class ImageDiskBackdrop extends SolidDiskBackdrop {
+
+ /** The image to draw. */
+ protected SubTex _image = null;
+
+ protected TextureState _texState = new TextureState();
+
+ /** The disk used across all disk backdrops to render with. */
+ private static UIDisk _standin = SolidDiskBackdrop.createStandinDisk();
+
+ /**
+ * Construct this back drop, using the given image.
+ *
+ * @param image
+ */
+ public ImageDiskBackdrop(final SubTex image) {
+ super(ColorRGBA.BLACK_NO_ALPHA);
+ setImage(image);
+ }
+
+ /**
+ * Construct this back drop, using the given image and color.
+ *
+ * @param image
+ * the image to draw
+ * @param color
+ * the color of the backdrop
+ */
+ public ImageDiskBackdrop(final SubTex image, final ReadOnlyColorRGBA color) {
+ super(color);
+ setImage(image);
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ final float oldA = _color.getAlpha();
+ if (oldA == 0) {
+ // no need to draw.
+ return;
+ }
+
+ _color.setAlpha(oldA * UIComponent.getCurrentOpacity());
+ ImageDiskBackdrop._standin.setDefaultColor(_color);
+
+ final Vector3 v = Vector3.fetchTempInstance();
+ final Insets margin = comp.getMargin() != null ? comp.getMargin() : Insets.EMPTY;
+ final Insets border = comp.getBorder() != null ? comp.getBorder() : Insets.EMPTY;
+ v.set(margin.getLeft() + border.getLeft(), margin.getBottom() + border.getBottom(), 0);
+ v.addLocal(comp.getContentWidth() / 2, comp.getContentHeight() / 2, 0);
+
+ final Transform t = Transform.fetchTempInstance();
+ t.set(comp.getWorldTransform());
+ t.applyForwardVector(v);
+ t.translate(v);
+ Vector3.releaseTempInstance(v);
+
+ ImageDiskBackdrop._standin.setWorldTransform(t);
+ Transform.releaseTempInstance(t);
+
+ double size = 0;
+ if (comp instanceof UIPieMenu) {
+ size = ((UIPieMenu) comp).getOuterRadius();
+ } else {
+ size = Math.max(UIBackdrop.getBackdropWidth(comp), UIBackdrop.getBackdropHeight(comp)) / 2;
+ }
+
+ if (_texState.getNumberOfSetTextures() == 0 || _texState.getTexture().getTextureKey() == null
+ || !_texState.getTexture().getTextureKey().equals(_image.getTexture().getTextureKey())) {
+ _texState.setTexture(_image.getTexture());
+ ImageDiskBackdrop._standin.setRenderState(_texState);
+ ImageDiskBackdrop._standin.updateWorldRenderStates(false);
+ }
+
+ ImageDiskBackdrop._standin.resetGeometry(size, 0, _image);
+ ImageDiskBackdrop._standin.render(renderer);
+
+ _color.setAlpha(oldA);
+ }
+
+ public SubTex getImage() {
+ return _image;
+ }
+
+ public void setImage(final SubTex image) {
+ _image = image;
+ }
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidArcBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidArcBackdrop.java
new file mode 100644
index 0000000..32b3908
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidArcBackdrop.java
@@ -0,0 +1,144 @@
+/**
+ * Copyright (c) 2008-2017 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.UIPieMenu;
+import com.ardor3d.extension.ui.UIPieMenuItem;
+import com.ardor3d.extension.ui.util.Insets;
+import com.ardor3d.extension.ui.util.SubTex;
+import com.ardor3d.extension.ui.util.UIArc;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.BlendState.DestinationFunction;
+import com.ardor3d.renderer.state.BlendState.SourceFunction;
+
+/**
+ * This backdrop paints a solid arc of color behind a UI component.
+ */
+public class SolidArcBackdrop extends UIBackdrop {
+
+ /** The color to draw */
+ protected final ColorRGBA _color = new ColorRGBA(ColorRGBA.GRAY);
+ /** The disk used across all disk backdrops to render with. */
+ private static UIArc _standin = SolidArcBackdrop.createStandinArc();
+
+ /**
+ * Construct this backdrop, using the given color.
+ *
+ * @param color
+ * the color of the backdrop
+ */
+ public SolidArcBackdrop(final ReadOnlyColorRGBA color) {
+ setColor(color);
+ }
+
+ /**
+ * @return the color of this back drop.
+ */
+ public ReadOnlyColorRGBA getColor() {
+ return _color;
+ }
+
+ /**
+ * Set the color of this back drop.
+ *
+ * @param color
+ * the color to use
+ */
+ public void setColor(final ReadOnlyColorRGBA color) {
+ if (color != null) {
+ _color.set(color);
+ }
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ drawBackdrop(SolidArcBackdrop._standin, renderer, comp, null);
+ }
+
+ protected void drawBackdrop(final UIArc arc, final Renderer renderer, final UIComponent comp, final SubTex sub) {
+ final float oldA = _color.getAlpha();
+ if (oldA == 0) {
+ // no need to draw.
+ return;
+ }
+
+ _color.setAlpha(oldA * UIComponent.getCurrentOpacity());
+ arc.setDefaultColor(_color);
+
+ final Vector3 v = Vector3.fetchTempInstance();
+ final Insets margin = comp.getMargin() != null ? comp.getMargin() : Insets.EMPTY;
+ final Insets border = comp.getBorder() != null ? comp.getBorder() : Insets.EMPTY;
+ v.set(margin.getLeft() + border.getLeft(), margin.getBottom() + border.getBottom(), 0);
+
+ final Transform t = Transform.fetchTempInstance();
+ if (comp instanceof UIPieMenuItem && comp.getParent() instanceof UIPieMenu) {
+ final UIPieMenu pie = (UIPieMenu) comp.getParent();
+ t.set(comp.getParent().getWorldTransform()).translate(pie.getOuterRadius(), pie.getOuterRadius(), 0);
+ } else {
+ t.set(comp.getWorldTransform());
+ v.addLocal(comp.getContentWidth() / 2, comp.getContentHeight() / 2, 0);
+ }
+ t.applyForwardVector(v);
+ t.translate(v);
+ Vector3.releaseTempInstance(v);
+
+ arc.setWorldTransform(t);
+ Transform.releaseTempInstance(t);
+
+ double size = 0, inner = 0, angle = 0, length = MathUtils.TWO_PI;
+ if (comp instanceof UIPieMenu) {
+ final UIPieMenu pie = (UIPieMenu) comp;
+ size = pie.getOuterRadius();
+ inner = 0;
+ } else if (comp instanceof UIPieMenuItem && comp.getParent() instanceof UIPieMenu) {
+ final UIPieMenuItem item = (UIPieMenuItem) comp;
+ final UIPieMenu pie = (UIPieMenu) comp.getParent();
+ if (pie.getCenterItem() == item) {
+ size = pie.getInnerRadius();
+ inner = 0;
+ angle = 0;
+ length = MathUtils.TWO_PI;
+ } else {
+ size = pie.getOuterRadius();
+ inner = pie.getInnerRadius();
+ length = pie.getCurrentArcLength();
+ angle = pie.getSliceIndex(item) * length - length / 2;
+ }
+ } else {
+ size = Math.max(UIBackdrop.getBackdropWidth(comp), UIBackdrop.getBackdropHeight(comp)) / 2;
+ }
+
+ arc.resetGeometry(angle, length, size, inner, sub);
+ arc.render(renderer);
+
+ _color.setAlpha(oldA);
+ }
+
+ public static UIArc createStandinArc() {
+ final UIArc arc = new UIArc("standin", MathUtils.TWO_PI / 60, 1, 0.5);
+
+ final BlendState blend = new BlendState();
+ blend.setBlendEnabled(true);
+ blend.setSourceFunction(SourceFunction.SourceAlpha);
+ blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha);
+ arc.setRenderState(blend);
+ arc.updateWorldRenderStates(false);
+
+ return arc;
+ }
+} \ No newline at end of file
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidDiskBackdrop.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidDiskBackdrop.java
new file mode 100644
index 0000000..6825b46
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/backdrop/SolidDiskBackdrop.java
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) 2008-2017 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.backdrop;
+
+import com.ardor3d.extension.ui.UIComponent;
+import com.ardor3d.extension.ui.UIPieMenu;
+import com.ardor3d.extension.ui.util.Insets;
+import com.ardor3d.extension.ui.util.UIDisk;
+import com.ardor3d.math.ColorRGBA;
+import com.ardor3d.math.Transform;
+import com.ardor3d.math.Vector3;
+import com.ardor3d.math.type.ReadOnlyColorRGBA;
+import com.ardor3d.renderer.Renderer;
+import com.ardor3d.renderer.state.BlendState;
+import com.ardor3d.renderer.state.BlendState.DestinationFunction;
+import com.ardor3d.renderer.state.BlendState.SourceFunction;
+import com.ardor3d.renderer.state.RenderState.StateType;
+
+/**
+ * This backdrop paints a solid disk of color behind a UI component.
+ */
+public class SolidDiskBackdrop extends UIBackdrop {
+
+ /** The color to draw */
+ protected final ColorRGBA _color = new ColorRGBA(ColorRGBA.GRAY);
+ /** The disk used across all disk backdrops to render with. */
+ private static UIDisk _standin = SolidDiskBackdrop.createStandinDisk();
+
+ /**
+ * Construct this backdrop, using the given color.
+ *
+ * @param color
+ * the color of the backdrop
+ */
+ public SolidDiskBackdrop(final ReadOnlyColorRGBA color) {
+ setColor(color);
+ }
+
+ /**
+ * @return the color of this back drop.
+ */
+ public ReadOnlyColorRGBA getColor() {
+ return _color;
+ }
+
+ /**
+ * Set the color of this back drop.
+ *
+ * @param color
+ * the color to use
+ */
+ public void setColor(final ReadOnlyColorRGBA color) {
+ if (color != null) {
+ _color.set(color);
+ }
+ }
+
+ @Override
+ public void draw(final Renderer renderer, final UIComponent comp) {
+ final float oldA = _color.getAlpha();
+ if (oldA == 0) {
+ // no need to draw.
+ return;
+ }
+
+ _color.setAlpha(oldA * UIComponent.getCurrentOpacity());
+ SolidDiskBackdrop._standin.setDefaultColor(_color);
+
+ final Vector3 v = Vector3.fetchTempInstance();
+ final Insets margin = comp.getMargin() != null ? comp.getMargin() : Insets.EMPTY;
+ final Insets border = comp.getBorder() != null ? comp.getBorder() : Insets.EMPTY;
+ v.set(margin.getLeft() + border.getLeft(), margin.getBottom() + border.getBottom(), 0);
+ v.addLocal(comp.getContentWidth() / 2, comp.getContentHeight() / 2, 0);
+
+ final Transform t = Transform.fetchTempInstance();
+ t.set(comp.getWorldTransform());
+ t.applyForwardVector(v);
+ t.translate(v);
+ Vector3.releaseTempInstance(v);
+
+ SolidDiskBackdrop._standin.setWorldTransform(t);
+ Transform.releaseTempInstance(t);
+
+ double size = 0;
+ if (comp instanceof UIPieMenu) {
+ size = ((UIPieMenu) comp).getOuterRadius();
+ } else {
+ size = Math.max(UIBackdrop.getBackdropWidth(comp), UIBackdrop.getBackdropHeight(comp)) / 2;
+ }
+
+ SolidDiskBackdrop._standin.clearRenderState(StateType.Texture);
+ SolidDiskBackdrop._standin.resetGeometry(size, 0, null);
+ SolidDiskBackdrop._standin.render(renderer);
+
+ _color.setAlpha(oldA);
+ }
+
+ public static UIDisk createStandinDisk() {
+ final UIDisk disk = new UIDisk("standin", 60, 1, 0);
+
+ final BlendState blend = new BlendState();
+ blend.setBlendEnabled(true);
+ blend.setSourceFunction(SourceFunction.SourceAlpha);
+ blend.setDestinationFunction(DestinationFunction.OneMinusSourceAlpha);
+ disk.setRenderState(blend);
+ disk.updateWorldRenderStates(false);
+
+ return disk;
+ }
+} \ No newline at end of file
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java
index f1358d7..69203d6 100644
--- a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/Skin.java
@@ -19,6 +19,8 @@ import com.ardor3d.extension.ui.UILabel;
import com.ardor3d.extension.ui.UIMenuItem;
import com.ardor3d.extension.ui.UIPanel;
import com.ardor3d.extension.ui.UIPasswordField;
+import com.ardor3d.extension.ui.UIPieMenu;
+import com.ardor3d.extension.ui.UIPieMenuItem;
import com.ardor3d.extension.ui.UIPopupMenu;
import com.ardor3d.extension.ui.UIProgressBar;
import com.ardor3d.extension.ui.UIRadioButton;
@@ -41,6 +43,8 @@ public abstract class Skin {
applyToCheckBox((UICheckBox) component);
} else if (component instanceof UIRadioButton) {
applyToRadioButton((UIRadioButton) component);
+ } else if (component instanceof UIPieMenuItem) {
+ applyToPieMenuItem((UIPieMenuItem) component);
} else if (component instanceof UIMenuItem) {
applyToMenuItem((UIMenuItem) component);
} else if (component instanceof UIButton) {
@@ -68,6 +72,8 @@ public abstract class Skin {
applyToComboBox((UIComboBox) component);
} else if (component instanceof UIScrollBar) {
applyToScrollBar((UIScrollBar) component);
+ } else if (component instanceof UIPieMenu) {
+ applyToPieMenu((UIPieMenu) component);
} else if (component instanceof UIPanel) {
applyToPanel((UIPanel) component);
}
@@ -95,6 +101,8 @@ public abstract class Skin {
protected abstract void applyToMenuItem(UIMenuItem component);
+ protected abstract void applyToPieMenuItem(UIPieMenuItem component);
+
protected abstract void applyToButton(UIButton component);
protected abstract void applyToLabel(UILabel component);
@@ -105,6 +113,8 @@ public abstract class Skin {
protected abstract void applyToTextArea(UITextArea component);
+ protected abstract void applyToPieMenu(UIPieMenu component);
+
protected abstract void applyToPanel(UIPanel component);
protected abstract void applyToTooltip(UITooltip component);
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java
index 2013294..1ac2974 100644
--- a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/skin/generic/GenericSkin.java
@@ -23,6 +23,8 @@ import com.ardor3d.extension.ui.UILabel;
import com.ardor3d.extension.ui.UIMenuItem;
import com.ardor3d.extension.ui.UIPanel;
import com.ardor3d.extension.ui.UIPasswordField;
+import com.ardor3d.extension.ui.UIPieMenu;
+import com.ardor3d.extension.ui.UIPieMenuItem;
import com.ardor3d.extension.ui.UIPopupMenu;
import com.ardor3d.extension.ui.UIProgressBar;
import com.ardor3d.extension.ui.UIRadioButton;
@@ -37,7 +39,9 @@ import com.ardor3d.extension.ui.UITextField;
import com.ardor3d.extension.ui.UITooltip;
import com.ardor3d.extension.ui.backdrop.EmptyBackdrop;
import com.ardor3d.extension.ui.backdrop.GradientBackdrop;
+import com.ardor3d.extension.ui.backdrop.ImageArcBackdrop;
import com.ardor3d.extension.ui.backdrop.ImageBackdrop;
+import com.ardor3d.extension.ui.backdrop.SolidArcBackdrop;
import com.ardor3d.extension.ui.backdrop.SolidBackdrop;
import com.ardor3d.extension.ui.backdrop.UIBackdrop;
import com.ardor3d.extension.ui.border.EmptyBorder;
@@ -47,6 +51,7 @@ import com.ardor3d.extension.ui.border.UIBorder;
import com.ardor3d.extension.ui.layout.RowLayout;
import com.ardor3d.extension.ui.skin.Skin;
import com.ardor3d.extension.ui.skin.SkinningTask;
+import com.ardor3d.extension.ui.text.StyleConstants;
import com.ardor3d.extension.ui.util.Alignment;
import com.ardor3d.extension.ui.util.Insets;
import com.ardor3d.extension.ui.util.SubTex;
@@ -312,7 +317,7 @@ public class GenericSkin extends Skin {
closeButton.updateMinimumSizeFromContents();
closeButton.compact();
closeButton
- .setMaximumContentSize(closeButton.getContentWidth(), closeButton.getContentHeight());
+ .setMaximumContentSize(closeButton.getContentWidth(), closeButton.getContentHeight());
}
}
@@ -484,6 +489,37 @@ public class GenericSkin extends Skin {
}
@Override
+ protected void applyToPieMenu(final UIPieMenu component) {
+ final UIBackdrop pieBack = new SolidArcBackdrop(new ColorRGBA(.9f, .9f, .9f, .8f));
+ component.setBackdrop(pieBack);
+ }
+
+ @Override
+ protected void applyToPieMenuItem(final UIPieMenuItem component) {
+ final EmptyBorder itemBorder = new EmptyBorder();
+ final SubTex bgImage = new SubTex(_sharedTex, 10, 102, 7, 45, 4, 4, 3, 0);
+ final UIBackdrop overBackdrop = new ImageArcBackdrop(bgImage, new ColorRGBA(.9f, .9f, .9f, 1f));
+ final UIBackdrop pieBack = new ImageArcBackdrop(bgImage, new ColorRGBA(.9f, .9f, .9f, .8f));
+ component.setBackdrop(pieBack);
+ component.setBorder(itemBorder);
+ component.addFontStyle(StyleConstants.KEY_BOLD, Boolean.TRUE);
+ component.setMargin(new Insets(0, 0, 0, 0));
+ component.setPadding(new Insets(0, 2, 0, 2));
+ component.setForegroundColor(ColorRGBA.BLACK);
+ component.setAlignment(Alignment.LEFT);
+ for (final UIState state : component.getStates()) {
+ state.setBorder(null);
+ state.setBackdrop(pieBack);
+ state.setForegroundColor(ColorRGBA.BLACK);
+ }
+
+ final LabelState over = component.getMouseOverState();
+ over.setForegroundColor(ColorRGBA.BLACK);
+ over.setBackdrop(overBackdrop);
+
+ }
+
+ @Override
protected void applyToPanel(final UIPanel component) {
; // nothing to do
}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIArc.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIArc.java
new file mode 100644
index 0000000..f92b928
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIArc.java
@@ -0,0 +1,266 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.util;
+
+import java.nio.FloatBuffer;
+
+import com.ardor3d.image.Image;
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Vector2;
+import com.ardor3d.renderer.IndexMode;
+import com.ardor3d.scenegraph.FloatBufferData;
+import com.ardor3d.scenegraph.IndexBufferData;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.util.geom.BufferUtils;
+
+public class UIArc extends Mesh {
+
+ protected double _sampleRate;
+
+ protected double _radius, _innerRadius, _arcLength;
+
+ public UIArc() {}
+
+ /**
+ * Creates a flat disk (circle) at the origin flat along the Z. Usually, a higher sample number creates a better
+ * looking cylinder, but at the cost of more vertex information.
+ *
+ * @param name
+ * The name of the arc.
+ * @param sampleRate
+ * The number of radial samples per radian.
+ * @param radius
+ * The radius of the arc.
+ * @param innerRadius
+ * The innerRadius of the arc.
+ */
+ public UIArc(final String name, final double sampleRate, final double radius, final double innerRadius) {
+ super(name);
+
+ _sampleRate = sampleRate;
+ resetGeometry(0, MathUtils.PI, radius, innerRadius, null);
+ getMeshData().setIndexMode(IndexMode.Triangles);
+ }
+
+ public void resetGeometry(final double startAngle, final double arcLength, final double radius,
+ final double innerRadius, final SubTex subTex) {
+ _radius = radius;
+ _innerRadius = innerRadius;
+ _arcLength = arcLength;
+
+ // allocate vertices
+ final int radialVerts = (int) MathUtils.round(_arcLength / _sampleRate);
+ final int verts = radialVerts * 4 + 4 * 4; // bg verts + edge decorations
+ if (_meshData.getVertexBuffer() == null || _meshData.getVertexBuffer().capacity() < verts * 2) {
+ _meshData.setVertexCoords(new FloatBufferData(verts * 2, 2));
+ } else {
+ _meshData.getVertexBuffer().clear();
+ }
+ if (_meshData.getTextureBuffer(0) == null || _meshData.getTextureBuffer(0).capacity() < verts * 2) {
+ _meshData.setTextureCoords(new FloatBufferData(verts * 2, 2), 0);
+ } else {
+ _meshData.getTextureBuffer(0).clear();
+ }
+
+ // allocate indices
+ final int tris = (radialVerts + 1) * 6; // bg tris + edge decorations
+ final int indices = tris * 3;
+ if (_meshData.getIndexBuffer() == null || _meshData.getIndexBuffer().capacity() < indices) {
+ _meshData.setIndices(BufferUtils.createIndexBufferData(indices, verts - 1));
+ } else {
+ _meshData.getIndexBuffer().clear();
+ }
+ _meshData.setIndexLengths(new int[] { indices - 36, 18 });
+
+ // generate geometry
+ float txOff = 0f, tyOff = 0f, txScale = 1f, tyScale = 1f;
+ int topBrd = 0, leftBrd = 0, bottomBrd = 0, rightBrd = 0;
+ float topOffTx = 0f, leftOffTx = 0f, bottomOffTx = 0f, rightOffTx = 0f;
+ if (subTex != null && subTex.getTexture() != null && subTex.getTexture() != null) {
+ txOff = subTex.getStartX();
+ tyOff = subTex.getStartY();
+ txScale = subTex.getEndX() - subTex.getStartX();
+ tyScale = subTex.getEndY() - subTex.getStartY();
+
+ topBrd = subTex.getBorderTop();
+ leftBrd = subTex.getBorderLeft();
+ bottomBrd = subTex.getBorderBottom();
+ rightBrd = subTex.getBorderRight();
+
+ final Image image = subTex.getTexture().getImage();
+ topOffTx = topBrd / (float) image.getHeight();
+ leftOffTx = leftBrd / (float) image.getWidth();
+ bottomOffTx = bottomBrd / (float) image.getHeight();
+ rightOffTx = rightBrd / (float) image.getWidth();
+ }
+
+ /***** VERT DATA *****/
+ {
+ final Vector2 radialOffset = new Vector2();
+ final Vector2 radialEdge = new Vector2();
+ final Vector2 texCoord = new Vector2();
+ final FloatBuffer vertBuffer = _meshData.getVertexBuffer();
+ final FloatBuffer texBuffer = _meshData.getTextureBuffer(0);
+
+ int i = 0;
+ final double actualSampleRate = _arcLength / (radialVerts - 1);
+ double angle = startAngle;
+ for (int x = 0; x < radialVerts; x++) {
+ final float radialU = txOff + leftOffTx + (txScale - leftOffTx - rightOffTx)
+ * ((float) x / (radialVerts - 1));
+ final Vector2 radial = new Vector2(MathUtils.sin(angle), MathUtils.cos(angle));
+ radialOffset.set(radial).multiplyLocal(_innerRadius);
+
+ // inner edge
+ radialEdge.zero().addLocal(radialOffset);
+ BufferUtils.setInBuffer(radialEdge, vertBuffer, i);
+ texCoord.set(radialU, tyOff + tyScale);
+ BufferUtils.setInBuffer(texCoord, texBuffer, i++);
+
+ // inner edge border
+ radialEdge.set(radial).multiplyLocal(bottomBrd).addLocal(radialOffset);
+ BufferUtils.setInBuffer(radialEdge, vertBuffer, i);
+ texCoord.set(radialU, tyOff + tyScale - topOffTx);
+ BufferUtils.setInBuffer(texCoord, texBuffer, i++);
+
+ // outer edge border
+ radialEdge.set(radial).multiplyLocal(_radius - _innerRadius - topBrd).addLocal(radialOffset);
+ BufferUtils.setInBuffer(radialEdge, vertBuffer, i);
+ texCoord.set(radialU, tyOff + bottomOffTx);
+ BufferUtils.setInBuffer(texCoord, texBuffer, i++);
+
+ // outer edge
+ radialEdge.set(radial).multiplyLocal(_radius - _innerRadius).addLocal(radialOffset);
+ BufferUtils.setInBuffer(radialEdge, vertBuffer, i);
+ texCoord.set(radialU, tyOff);
+ BufferUtils.setInBuffer(texCoord, texBuffer, i++);
+
+ angle += actualSampleRate;
+ }
+
+ // *** edge decoration - left
+ {
+ angle = startAngle + MathUtils.HALF_PI;
+ final float radialU1 = txOff;
+ final float radialU2 = txOff + leftOffTx;
+ final Vector2 radial = new Vector2(MathUtils.sin(angle), MathUtils.cos(angle));
+ radialOffset.set(radial).multiplyLocal(leftBrd);
+
+ for (int s = 0; s < 4; s++) {
+ BufferUtils.copyInternalVector2(vertBuffer, s, i + s);
+ BufferUtils.copyInternalVector2(vertBuffer, s, i + 4 + s);
+ BufferUtils.addInBuffer(radialOffset, vertBuffer, i + 4 + s);
+ }
+
+ // inner edge
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff + tyScale), texBuffer, i + 0);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff + tyScale), texBuffer, i + 4);
+
+ // inner edge border
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff + tyScale - topOffTx), texBuffer, i + 1);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff + tyScale - topOffTx), texBuffer, i + 5);
+
+ // outer edge border
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff + bottomOffTx), texBuffer, i + 2);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff + bottomOffTx), texBuffer, i + 6);
+
+ // outer edge
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff), texBuffer, i + 3);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff), texBuffer, i + 7);
+
+ i += 8;
+ }
+
+ // *** edge decoration - right
+ {
+ angle = startAngle + arcLength - MathUtils.HALF_PI;
+ final float radialU1 = txOff + txScale - rightOffTx;
+ final float radialU2 = txOff + txScale;
+ final Vector2 radial = new Vector2(MathUtils.sin(angle), MathUtils.cos(angle));
+ radialOffset.set(radial).multiplyLocal(rightBrd);
+
+ for (int s = 0; s < 4; s++) {
+ BufferUtils.copyInternalVector2(vertBuffer, s, i + s);
+ BufferUtils.copyInternalVector2(vertBuffer, s, i + 4 + s);
+ BufferUtils.addInBuffer(radialOffset, vertBuffer, i + 4 + s);
+ }
+
+ // inner edge
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff + tyScale), texBuffer, i + 0);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff + tyScale), texBuffer, i + 4);
+
+ // inner edge border
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff + tyScale - topOffTx), texBuffer, i + 1);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff + tyScale - topOffTx), texBuffer, i + 5);
+
+ // outer edge border
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff + bottomOffTx), texBuffer, i + 2);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff + bottomOffTx), texBuffer, i + 6);
+
+ // outer edge
+ BufferUtils.setInBuffer(texCoord.set(radialU1, tyOff), texBuffer, i + 3);
+ BufferUtils.setInBuffer(texCoord.set(radialU2, tyOff), texBuffer, i + 7);
+
+ i += 8;
+ }
+
+ /***** INDICE DATA *****/
+ {
+ final IndexBufferData<?> indBuff = _meshData.getIndices();
+ for (int r = 0; r < radialVerts - 1; r++) {
+ for (int iS = 0; iS < 3; iS++) {
+ final int i00 = iS + 4 * r;
+ final int i01 = iS + 4 * (r + 1);
+ final int i10 = i00 + 1;
+ final int i11 = i01 + 1;
+ indBuff.put(i00).put(i10).put(i11);
+ indBuff.put(i00).put(i11).put(i01);
+ }
+ }
+
+ // edge decoration - left
+ int e = verts - 16;
+ for (int iS = 0; iS < 3; iS++) {
+ final int i00 = e + iS;
+ final int i01 = e + iS + 4;
+ final int i10 = i00 + 1;
+ final int i11 = i01 + 1;
+ indBuff.put(i00).put(i10).put(i11);
+ indBuff.put(i00).put(i11).put(i01);
+ }
+
+ // edge decoration - right
+ e = verts - 8;
+ for (int iS = 0; iS < 3; iS++) {
+ final int i00 = e + iS;
+ final int i01 = e + iS + 4;
+ final int i10 = i00 + 1;
+ final int i11 = i01 + 1;
+ indBuff.put(i00).put(i10).put(i11);
+ indBuff.put(i00).put(i11).put(i01);
+ }
+ }
+ }
+ }
+
+ public double getSampleRate() {
+ return _sampleRate;
+ }
+
+ public double getRadius() {
+ return _radius;
+ }
+
+ public double getInnerRadius() {
+ return _innerRadius;
+ }
+
+}
diff --git a/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIDisk.java b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIDisk.java
new file mode 100644
index 0000000..de75cba
--- /dev/null
+++ b/ardor3d-ui/src/main/java/com/ardor3d/extension/ui/util/UIDisk.java
@@ -0,0 +1,143 @@
+/**
+ * Copyright (c) 2008-2010 Ardor Labs, Inc.
+ *
+ * This file is part of Ardor3D.
+ *
+ * Ardor3D is free software: you can redistribute it and/or modify it
+ * under the terms of its license which may be found in the accompanying
+ * LICENSE file or at <http://www.ardor3d.com/LICENSE>.
+ */
+
+package com.ardor3d.extension.ui.util;
+
+import com.ardor3d.math.MathUtils;
+import com.ardor3d.math.Vector2;
+import com.ardor3d.scenegraph.FloatBufferData;
+import com.ardor3d.scenegraph.Mesh;
+import com.ardor3d.util.geom.BufferUtils;
+
+public class UIDisk extends Mesh {
+
+ protected int _radialSamples;
+
+ protected double _radius;
+
+ protected double _innerRadius;
+
+ public UIDisk() {}
+
+ /**
+ * Creates a flat disk (circle) at the origin flat along the Z. Usually, a higher sample number creates a better
+ * looking disk, but at the cost of more vertex information.
+ *
+ * @param name
+ * The name of the disk.
+ * @param radialSamples
+ * The number of radial samples.
+ * @param radius
+ * The outer radius of the disk.
+ */
+ public UIDisk(final String name, final int radialSamples, final double radius) {
+ this(name, radialSamples, radius, 0);
+ }
+
+ /**
+ * Creates a flat disk (circle) at the origin flat along the Z. Usually, a higher sample number creates a better
+ * looking disk, but at the cost of more vertex information.
+ *
+ * @param name
+ * The name of the disk.
+ * @param radialSamples
+ * The number of radial samples.
+ * @param radius
+ * The outer radius of the disk.
+ * @param innerRadius
+ * The inner radius of the disk. If greater than 0, the center of the disk has a hole of this size.
+ */
+ public UIDisk(final String name, final int radialSamples, final double radius, final double innerRadius) {
+ super(name);
+
+ _radialSamples = radialSamples;
+
+ // allocate vertices
+ final int verts = radialSamples * 2;
+ _meshData.setVertexCoords(new FloatBufferData(verts * 2, 2));
+ _meshData.setTextureBuffer(BufferUtils.createVector2Buffer(verts), 0);
+
+ final int tris = radialSamples * 2;
+ _meshData.setIndices(BufferUtils.createIndexBufferData(3 * tris, verts - 1));
+
+ resetGeometry(radius, innerRadius, null);
+ setIndexData();
+
+ }
+
+ public void resetGeometry(final double radius, final double innerRadius, final SubTex subTex) {
+ _radius = radius;
+ _innerRadius = innerRadius;
+
+ // generate geometry
+ final double inverseRadial = 1.0 / _radialSamples;
+ final Vector2 radialFraction = new Vector2();
+ final Vector2 texCoord = new Vector2();
+
+ float txOff = 0f, tyOff = 0f, txScale = 1f, tyScale = 1f;
+ if (subTex != null && subTex.getTexture() != null && subTex.getTexture() != null) {
+ txOff = subTex.getStartX();
+ tyOff = subTex.getStartY();
+ txScale = subTex.getEndX() - subTex.getStartX();
+ tyScale = subTex.getEndY() - subTex.getStartY();
+ }
+
+ final Vector2 radialInner = new Vector2();
+ for (int radialCount = 0; radialCount < _radialSamples; radialCount++) {
+ final double angle = MathUtils.TWO_PI * inverseRadial * radialCount;
+ final double cos = MathUtils.cos(angle);
+ final double sin = MathUtils.sin(angle);
+ final Vector2 radial = new Vector2(cos, sin);
+ radialInner.set(radial).multiplyLocal(_innerRadius);
+
+ for (int shellCount = 0; shellCount < 2; shellCount++) {
+ radialFraction.set(radial).multiplyLocal(shellCount);
+
+ final int i = shellCount + 2 * radialCount;
+
+ radialFraction.multiplyLocal(_radius - _innerRadius).addLocal(radialInner);
+ BufferUtils.setInBuffer(radialFraction, _meshData.getVertexBuffer(), i);
+
+ texCoord.setX(txOff + txScale * 0.5 * (1.0 + radialFraction.getX() / _radius));
+ texCoord.setY(tyOff + tyScale * 0.5 * (1.0 + radialFraction.getY() / _radius));
+ BufferUtils.setInBuffer(texCoord, _meshData.getTextureCoords(0).getBuffer(), i);
+ }
+ }
+ }
+
+ private void setIndexData() {
+ // generate connectivity
+ for (int radialCount0 = _radialSamples - 1, radialCount1 = 0; radialCount1 < _radialSamples; radialCount0 = radialCount1++) {
+ final int i00 = 2 * radialCount0;
+ final int i01 = 2 * radialCount1;
+ final int i10 = i00 + 1;
+ final int i11 = i01 + 1;
+ _meshData.getIndices().put(i00);
+ _meshData.getIndices().put(i10);
+ _meshData.getIndices().put(i11);
+ _meshData.getIndices().put(i00);
+ _meshData.getIndices().put(i11);
+ _meshData.getIndices().put(i01);
+ }
+ }
+
+ public int getRadialSamples() {
+ return _radialSamples;
+ }
+
+ public double getRadius() {
+ return _radius;
+ }
+
+ public double getInnerRadius() {
+ return _innerRadius;
+ }
+
+}
diff --git a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png
index 8de8d1a..bea78cc 100644
--- a/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png
+++ b/ardor3d-ui/src/main/resources/com/ardor3d/extension/ui/skin/generic/genericSkin.png
Binary files differ