aboutsummaryrefslogtreecommitdiffstats
path: root/ardor3d-ui/src/main
diff options
context:
space:
mode:
authorJoshua Slack <[email protected]>2017-09-11 07:46:31 -0500
committerJoshua Slack <[email protected]>2017-09-11 07:46:31 -0500
commit90fa0f6c4997d65e5c5980cd1602956d62cc83c8 (patch)
tree811405dd6613fee8f84e1d8846f043aa891faa5c /ardor3d-ui/src/main
parentd2e0a7c79d1be87f867691a9e0317a549014ebcb (diff)
Added new UI Components - UIPieMenu and UIPieMenuItem.
Added new backdrops - Disk and Arc Added generic skin support for the above Added use of piemenu to one of the examples. Made popover an interface shared between piemenu and popupmenu
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