New Library And Game

Started by KittenKoder, November 01, 2012, 01:27:12 AM

Previous topic - Next topic

KittenKoder

Alright, I am working on a project that's cyberpunk "hacking," I spent the last year practicing modeling in 3D just so I could do this one. OpenGL perplexed me, and developing a system from scratch was too tedious so I found jPCT, which is perfect for my needs. However for the game I am developing a library that includes:

1. Multilayer world system, one layer for a GUI, another for the game, and one in between for "x-ray" objects. There is a world manager than can clean out things owned by only one of the worlds, included textures not needed elsewhere if the extended texture manager is used.

2. A texture manager that incorporates the jPCT texture manager with a few lists for tracking the texture image. Texture image class can be a texture, buffered image, or both, and has a built in dynamic update. Textures can be "owned" by objects and/or worlds so when those are removed from the game the textures can also be removed with them using only one method call.

3. Texture "sequences" for more complex texture animations. A complete system for adding these to the extended object class, extended to accommodate a lot of game dependent data.

4. Texture "layering" the efficient way. The library uses the AWT GL Canvas, which has a few limitations. The layered texture class overcomes some of them by combining multiple buffered images into one new texture, it actually combines multiple buffered images then creates a texture from that.

5. A managed HUD system, pretty straight forward, for posting things like text to the player or meters, 2D elements and the like.

6. The world GUI system, which includes animation responses, an event binding system that is versatile yet easy to use with keyboard, mouse, or even game controller input, you can combine several for each binding allowing multiple ways for the player to access something if desired.

7. An actor system for managing objects, specifically animated objects used for characters.

8. An audio system that utilizes the Tritonus plugins.

I will hopefully have the working demo, and a set of example programs, very soon. The demo will be the game demo as well. The jPCT extension library is dependent on my dev-libs, which includes a Canvas 2D GUI system as well, though it's basic it has some useful features and widgets focused on games.

My standard library, I often call my dev-lib.
http://www.java-gaming.org/user-generated-content/members/130380/kittstandard-v0-1.jar

The jPCT extension, requires jPCT of course, as well as Tritonus plugins for some audio formats, wav is supported directly by Java so if you don't use any other formats you don't need Tritonus.
http://www.java-gaming.org/user-generated-content/members/130380/jpctkitt-v0-1.jar

Edit: Thank you for moving it to the correct location.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

Large screen caps of the test app so far.

The 3D GUI.


The Canvas GUI.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

EgonOlsen

Nice. I like the 3d effect. Does it render the labels by itself or are they part of a texture?

KittenKoder

Quote from: EgonOlsen on November 05, 2012, 09:39:36 AM
Nice. I like the 3d effect. Does it render the labels by itself or are they part of a texture?

They are rendered onto the texture. There is a method in the Image/Texture class that allows you to make it dynamic using an texture effect interface, which is actually an alternate class to conserve memory. The image font class I wrote for the Canvas widgets is used for the printing onto the texture. If you use the dynamic interface then you can call a method in the image/texture object to update the texture easily. The text display at the bottom uses the same method, instead of blitting every letter.

Basically, it takes a BufferedImage, keeps the image in memory, and when you change the image you call the update method and that change is made to the texture using jPCT's texture effect interface. There is also a loader, which I need to work on a bit more as it's highly inefficient yet, that will combine two images to produce the texture, using BufferedImage of course. The green icons on that screen shot uses that specific technique as well. The icons and blank model texture are loaded as buffered images, then the you duplicate the blank one, paint the icon onto it, and it creates the texture. Though those I did not use dynamic texture images since they only needed to do that once. The model texture for the widgets I used a half texture for each of the color sets, so one texture has two color sets, and just flipped the U or V based on the orientation. Still working on how to simplify that process, it may not be something that can be simplified, but I extended the Object3D to include two methods, one for flipping the U the other for flipping the V, to make that part easier.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

Figured I should show what the test app looks like so you can get an idea of how it's done a bit.


package app;

import java.awt.Color;
import java.awt.Container;
import java.awt.HeadlessException;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

import kitt.com.jpct.WorldManager;
import kitt.com.jpct.XMLLoader;
import kitt.com.jpct.actor.Actor;
import kitt.com.jpct.actor.ActorCameraFocal;
import kitt.com.jpct.anim.Animator;
import kitt.com.jpct.anim.AnimatorCallback;
import kitt.com.jpct.anim.AnimatorCharacter;
import kitt.com.jpct.anim.AnimatorStayWith;
import kitt.com.jpct.ext.AmbientFull;
import kitt.com.jpct.ext.LightFlicker;
import kitt.com.jpct.ext.Object3DEx;
import kitt.com.jpct.ext.RadialCamera;
import kitt.com.jpct.game.ControllerData;
import kitt.com.jpct.game.GamePads;
import kitt.com.jpct.gui.world.CanvasEventHandler;
import kitt.com.jpct.gui.world.GUIWorldEx;
import kitt.com.jpct.gui.world.WorldEventHandler;
import kitt.com.jpct.gui.world.WorldSelector;
import kitt.com.jpct.gui.world.anim.GUIAnimator;
import kitt.com.jpct.gui.world.event.Controller2ButtonBinding;
import kitt.com.jpct.gui.world.event.ControllerAxisBinding;
import kitt.com.jpct.gui.world.event.ControllerBinding;
import kitt.com.jpct.gui.world.event.ControllerButtonBinding;
import kitt.com.jpct.gui.world.event.KeyBinding;
import kitt.com.jpct.gui.world.event.KeyDualBinding;
import kitt.com.jpct.gui.world.event.KeyQuadBinding;
import kitt.com.jpct.gui.world.event.MouseBinding;
import kitt.com.jpct.gui.world.event.bind.ActorBinding;
import kitt.com.jpct.gui.world.event.bind.CanvasBinding;
import kitt.com.jpct.gui.world.event.bind.EventBinding;
import kitt.com.jpct.gui.world.event.bind.EventBindingCallback;
import kitt.com.jpct.gui.world.event.bind.GUISelectionBinding;
import kitt.com.jpct.gui.world.event.bind.GUISelectorBinding;
import kitt.com.jpct.gui.world.event.bind.GUIToggleBinding;
import kitt.com.jpct.gui.world.event.bind.RadialCameraBinding;
import kitt.com.jpct.gui.world.event.bind.WorldSelectionBinding;
import kitt.com.jpct.gui.world.event.bind.data.ToggleData;
import kitt.com.jpct.gui.world.kits.ElementKits;
import kitt.com.jpct.gui.world.kits.SelectorKit;
import kitt.com.jpct.hud.AnimatedBackground;
import kitt.com.jpct.hud.HUDBarVerUp;
import kitt.com.jpct.hud.HUDManager;
import kitt.com.jpct.hud.HUDTextLayer;
import kitt.com.jpct.hud.HUDTextureElement;
import kitt.com.jpct.swing.GLPanel;
import kitt.com.jpct.tex.LinkedTextureImage;
import kitt.com.jpct.tex.TextureImage;
import kitt.com.jpct.tex.TextureManagerEx;
import kitt.com.jpct.tex.TexturePack;
import kitt.com.jpct.tex.TextureSequence;
import kitt.com.math.ColorFloat;
import kitt.com.math.Coordinate;
import kitt.com.math.Dimension;
import kitt.com.swing.Util;
import kitt.com.swing.canvas.CanvasButton;
import kitt.com.swing.canvas.CanvasGUI;
import kitt.com.swing.canvas.CanvasLabel;
import kitt.com.swing.canvas.CanvasPointer;
import kitt.com.swing.canvas.data.CanvasImageFont;
import kitt.com.swing.canvas.kits.MenuKit;
import kitt.com.swing.canvas.kits.ToggleMenuKit;
import kitt.com.swing.canvas.kits.WidgetKits;

import com.threed.jpct.Camera;
import com.threed.jpct.Config;
import com.threed.jpct.Object3D;
import com.threed.jpct.SimpleVector;

public class HUDTest extends JFrame implements EventBindingCallback, AnimatorCallback {
private static final long serialVersionUID = 1L;

private static final String modelsdir = "res/models/";
private static final String texdir = "res/tex/";

private GLPanel mainpanel = null;
private HUDManager hud = null;
private TextureImage guitexture = null;
private TextureImage barstexture = null;
private RadialCamera camera = null;
private ControllerData controller = null;
private GUIWorldEx gui3d = null;
private ActorBinding mover = null;
// private File ping = null;

private Object3DEx box = null;
private WorldEventHandler eventhandler = null;
private CanvasEventHandler canvashandler = null;
private GUIToggleBinding hextoggle = null;
private HUDTextLayer textlayer = null;
private ActorCameraFocal mainactor = null;
private AnimatorCharacter mainanimator = null;

private CanvasGUI basecanvas = null;

public HUDTest() throws HeadlessException {
this.setup();
}

private void setup() {
this.setTitle("HUD Test");
this.setBounds(0, 0, 256, 256);
this.setLocationRelativeTo(null);

this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
this.setResizable(false);
Container cpane = this.getContentPane();
cpane.setLayout(null);

this.setVisible(true);
Dimension dim = Util.getRealSize(this, 1024, 768);
Coordinate loc = Util.centerScreen(dim.width, dim.height);
this.setBounds(loc.x, loc.y, dim.width, dim.height);

Config.isIndoor = true;
Config.glFullscreen = false;
Config.glAvoidTextureCopies = true;
Config.glColorDepth = 24;
// Config.farPlane = 4000;
Config.glShadowZBias = 0.8f;
Config.lightMul = 1;
Config.collideOffset = 500;
Config.glTrilinear = true;

this.mainpanel = new GLPanel(1024, 768);
this.mainpanel.setRenderGL(false);

// AudioManager.playLoop("res/audio/music/danosongs.com-bitbybits.ogg", -5.0f);
// this.ping = new File("res/audio/effects/ping.wav");

this.basecanvas = new CanvasGUI();
this.mainpanel.setBaseCanvas(this.basecanvas);
this.basecanvas.setBackground(new Color(0,128,128,128));
this.basecanvas.setForeground(new Color(64,255,255));
this.basecanvas.setName("Main Menu");
this.basecanvas.setFont(CanvasGUI.FONTLARGE);
this.basecanvas.setTextColor(Color.WHITE);

CanvasGUI.DEFAULT_DISABLED = new Color(255,0,0,128);
CanvasGUI.DEFAULT_HOVER = new Color(0,255,0,128);
CanvasGUI.DEFAULT_PRESSED = new Color(0,0,255,128);
CanvasGUI.DEFAULT_FOREGROUND = new Color(0,255,0);
CanvasGUI.DEFAULT_BACKGROUND = CanvasGUI.HALFBLACK;;

this.canvashandler = new CanvasEventHandler(this.basecanvas);
this.canvashandler.addTo(this.basecanvas);
this.mainpanel.setCurrentEventHandler(this.canvashandler);

this.basecanvas.setFlags(CanvasGUI.ROUNDED | CanvasGUI.BORDER);

this.guitexture = TextureManagerEx.loadImageTexture("res/tex/gui/base.png", "gui", true, true);
this.barstexture = TextureManagerEx.loadImageTexture("res/tex/gui/bars-ver.png", "bars", true, true);
TextureImage timage = TextureManagerEx.loadImageTexture("res/tex/font-base.png", "font", true, true);
CanvasGUI.IMAGEFONT = new CanvasImageFont(timage.getImage(), 32, 32);
CanvasGUI.IMAGEFONT.setBaseline(8);
CanvasGUI.IMAGEFONT.setAsciiOffset(32);
CanvasGUI.IMAGEFONT.setScale(0.5f);
TexturePack icons = XMLLoader.loadPackFromXML("res/xml/texpack-icons.xml", HUDTest.texdir, this.gui3d);

TextureImage image = TextureManagerEx.loadImageTexture("res/tex/icons/icon-logo-full.png", "icon-logo", true, true);
CanvasLabel label = new CanvasLabel(null, "Hacker's\nHaven", 100, 50, 100, 100);
label.setFlags(CanvasGUI.ROUNDED | CanvasGUI.BORDER | CanvasGUI.SHOWTEXT |
CanvasGUI.TEXT_LEFT | CanvasGUI.TEXT_TOP | CanvasGUI.IMAGE_STRETCH);
label.setImage(image.getImage());
this.basecanvas.addWidget(label);

CanvasButton button = new CanvasButton(null, "Pause", 0, 0, 100, 100);
button.setID("Pause");
this.basecanvas.addWidget(button);

String[][] options = {
{"GameStart", "Start"},
{"GameLoad", "Load"},
{"GameConfigure", "Settings"},
{"GameDelete", "Delete"},
{"GameExit", "Exit"}
};
MenuKit menu = WidgetKits.makeMenu(this.basecanvas, "Main Menu",
null, 150, 40,
options, 3, -1);
menu.parent.setLocation(200, 250);
menu.parent.setEnabled(false);

CanvasGUI.DEFAULT_FOREGROUND = new Color(0,255,255);

String[][] toptions = {
{"GameFun", "Fun"},
{"GameWicked", "Wicked"},
{"GameCool", "Cool"},
{"GameRun", "Run"}
};
ToggleMenuKit togglemenu = WidgetKits.makeToggleMenu(this.basecanvas, "Sub Menu",
null, 150, 40,
toptions, 2, CanvasGUI.HEXAGONAL | CanvasGUI.BORDER | CanvasGUI.SHOWTEXT |
CanvasGUI.TEXT_RIGHT | CanvasGUI.TEXT_BOTTOM | CanvasGUI.FILL  | CanvasGUI.IMAGE_STRETCH);
togglemenu.parent.setLocation(400, 50);
togglemenu.parent.setSingleToggle(true);
for (int i = 0; i < togglemenu.options.length; i++) {
togglemenu.options[i].setImage(icons.getTextureImage(i).getImage());
}

CanvasPointer pointer = new CanvasPointer(this.guitexture.getImage());
pointer.setImageOffset(new Coordinate(0, 200));
pointer.setImagePart(new Dimension(64,64));
pointer.setSize(64, 64);
pointer.setLocation(-8, -20);
this.basecanvas.setPointer(pointer);

this.basecanvas.setBackImage(new BufferedImage(this.mainpanel.getWidth(), this.mainpanel.getHeight(),
BufferedImage.TYPE_INT_RGB));

this.guitexture.makeTexture();
this.barstexture.makeTexture();

this.mainpanel.setLocation(0, 0);
cpane.add(this.mainpanel);
this.mainpanel.alignBaseCanvas();

this.gui3d = WorldManager.createGUIWorld("GUI");

this.hud = new HUDManager();
this.eventhandler = new WorldEventHandler(this.mainpanel.getBuffer());
this.eventhandler.installFixer();

this.mainpanel.addEventHandler(this.eventhandler);
this.mainpanel.setCurrentEventHandlerGL(this.eventhandler);
this.mainpanel.setGUIWorld(this.gui3d);
this.mainpanel.setHUD(this.hud);

this.camera = new RadialCamera();
this.mainpanel.getWorld().setCameraTo(this.camera);
this.camera.setDistance(0.05f);
Camera linked = new Camera();
linked.setFOV(1.5f);
this.camera.setLinked(linked);
this.mainpanel.enableTopWorld(linked);

this.eventhandler.addWorld(this.gui3d);
this.eventhandler.addWorld(this.mainpanel.getWorld());

HUDTextureElement element = new HUDTextureElement("text", 0, 512, 1024, 256);
element.setTexture(this.guitexture, 0, 0, 1024, 200);
this.hud.add(element);

element = new HUDTextureElement("text2", 10, 548, 100, 200);
element.setTexture(this.guitexture, 0, 0, 1024, 200);
element.setZOrder(0);
element.setVisible(false);
this.hud.add(element);

HUDBarVerUp elementbar = new HUDBarVerUp("bars", 10, 680, 5, 100);
elementbar.setTexture(this.barstexture, 0, 0, 100, 512);
elementbar.setZOrder(5);
elementbar.setValue(1.0f);
this.hud.add(elementbar);

CanvasImageFont font = new CanvasImageFont(CanvasGUI.IMAGEFONT, 0.8f);

this.textlayer = new HUDTextLayer("text-layer", 0, 512, 1024, 256);
this.textlayer.setZOrder(1);
this.textlayer.setFont(font);
this.textlayer.setBorder(32);
this.hud.add(this.textlayer);

this.hud.zSort();

TextureSequence tseq = XMLLoader.loadSequenceFromXML("res/xml/texseq-dissolve.xml", HUDTest.texdir, null);
tseq.makeTexture();
tseq = XMLLoader.loadSequenceFromXML("res/xml/texseq-appear.xml", HUDTest.texdir, null);
tseq.makeTexture();
tseq = XMLLoader.loadSequenceFromXML("res/xml/texseq-grid-shine.xml", HUDTest.texdir, null);
tseq.makeTexture();

if(tseq != null) {
AnimatedBackground background = new AnimatedBackground("background", this.mainpanel.getCanvas());
background.setTexture(tseq);
background.setFullImage();
this.mainpanel.setBackgroundElement(background);
}

this.controller = GamePads.getController(0);
if (this.controller != null) {
this.controller.setEnabled(true);
System.out.println("Controller Enabled");
this.eventhandler.addController(this.controller);
this.canvashandler.addController(this.controller);
}

TextureImage concrete = TextureManagerEx.loadImageTexture("res/tex/concrete.jpg", "concrete", false, false);
concrete.makeTexture();
Object3DEx tobject = XMLLoader.loadObject("res/models/scene.obj", 1.75f);
if(tobject != null) {
tobject.setName("scene");
System.out.println("Got Scene");
tobject.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
tobject.setCollisionOptimization(Object3D.COLLISION_DETECTION_OPTIMIZED);
tobject.rotateX((float)Math.toRadians(180.0));
tobject.setTexture("concrete");
tobject.build();
tobject.setSelectable(false);
this.mainpanel.getWorld().addObjectEx(tobject);
}


XMLLoader.loadXMLObjectCollection("res/xml/obj-hexes.xml", HUDTest.modelsdir, HUDTest.texdir, true, this.gui3d);
Object3DEx object = WorldManager.findObject(null, "hex-hor");
if(object != null) {
SelectorKit selectorkit = ElementKits.makeSelector(ElementKits.HEXAGONAL |
ElementKits.HORIZONTAL | ElementKits.OFFSETUP | ElementKits.EVENODD,
"Hex Menu", null, object, "Hex", 0.5f, 0.5f, 0.0f,
3, 3, this.gui3d, this.eventhandler);
if(selectorkit != null) {
GUIAnimator animator = new GUIAnimator();
animator.setRotationVectorY();
animator.setSpeed(0.025f);
animator.setRotationAngle((float)Math.toRadians(180.0f));

this.hextoggle = new GUIToggleBinding(null);
this.hextoggle.setAnimator(animator);
this.hextoggle.setElementArray(selectorkit.elements);
this.eventhandler.addEvent(this.hextoggle);

selectorkit.parent.translate(1.4f, -0.5f, 1.0f);
selectorkit.parent.rotateY((float)Math.toRadians(75.0));
selectorkit.parent.scale(0.125f);

TextureImage hex = TextureManagerEx.getImage(null, "hex-blank-hor");

TextureImage icon = icons.getTextureImage("icon-buffer");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-buffer-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[0].setTexture(tex.getName());
selectorkit.elements[0].flipUVVert();
tex.setOwner(selectorkit.elements[0]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-clone");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-clone-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[1].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[1]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-crash-bomb");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-crash-bomb-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[2].setTexture(tex.getName());
selectorkit.elements[2].flipUVVert();
tex.setOwner(selectorkit.elements[2]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-decode");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-decode-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[3].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[3]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-deflector");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-deflector-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[4].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[4]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-firewall");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-firewall-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[5].setTexture(tex.getName());
selectorkit.elements[5].flipUVVert();
tex.setOwner(selectorkit.elements[5]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-mask");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-mask-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[6].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[6]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-slicer");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-slicer-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[7].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[7]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-spy-bot");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-spy-bot-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[8].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[8]);
TextureManagerEx.addImage(tex);
}
icon = icons.getTextureImage("icon-torrent");
if(icon != null && hex != null) {
TextureImage tex = new TextureImage(hex, "hex-torrent-hor", false, true);
tex.paintOnto(icon, 132, 139, 120, 110, false, false);
tex.paintOnto(icon, 132, 7, 120, 110, false, true);
tex.makeTexture();
selectorkit.elements[9].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[9]);
TextureManagerEx.addImage(tex);
}
}
}

GUIAnimator inanim = new GUIAnimator();
inanim.setTranslation(0.0f, 0.0f, -0.5f);
inanim.setSpeed(0.08f);

object = WorldManager.findObject(null, "panel-hex");
if(object != null) {
object.setRelativeRotationPivot(-1.0f, 0.0f, 0.0f);
SelectorKit selectorkit = ElementKits.makeMenuSelector("Panel Menu",
inanim, object, "Panel", 0.5f, 0.5f, 0.0f,
7, this.gui3d, this.eventhandler);
if(selectorkit != null) {
ToggleData toggledata = new ToggleData("Panel-0", this.hextoggle.getElementArray());
toggledata.states[0] = true;
toggledata.states[7] = true;
toggledata.states[8] = true;
this.hextoggle.setToggleSet(toggledata);

toggledata = new ToggleData("Panel-1", this.hextoggle.getElementArray());
toggledata.states[1] = true;
toggledata.states[4] = true;
toggledata.states[9] = true;
this.hextoggle.setToggleSet(toggledata);

GUISelectorBinding sevent = new GUISelectorBinding(null, selectorkit.selector);
sevent.setControllerEvent(new ControllerAxisBinding(false, ControllerBinding.DIRECTIONAL, ControllerBinding.YDIRECTION));
sevent.setController(this.controller);
sevent.setWorld(this.gui3d);
this.eventhandler.addEvent(sevent);

GUIAnimator animator = new GUIAnimator();
animator.setTranslation(0.075f, 0.0f, 0.0f);
animator.setSpeed(0.08f);
animator.setBounce(true);

GUISelectionBinding event = new GUISelectionBinding(null, selectorkit.selector);
event.setAnimator(animator);
event.setMouseEvent(new MouseBinding(EventBinding.MOUSE_CLICK, 1, 0, 1, 0));
event.setControllerEvent(new ControllerButtonBinding(false, 1));
event.setController(this.controller);
event.setKeyEvent(new KeyBinding('c', 0, EventBinding.KEY_TYPED));
event.setWorld(this.gui3d);
event.setHitCheck(true);
this.eventhandler.addEvent(event);

selectorkit.parent.translate(-1.8f, -0.3f, 1.0f);
selectorkit.parent.rotateY(-(float)Math.toRadians(75.0));
selectorkit.parent.scale(0.25f);

TextureImage hex = TextureManagerEx.getImage(null, "panel-hex-blank");
if(hex != null) {
LinkedTextureImage tex = new LinkedTextureImage(hex, "panel-hex-attack", true, true);
tex.printOnto(font, "Attack", 26, 210, false, false);
tex.printOnto(font, "Attack", 26, 12, false, true);
tex.makeTexture();

selectorkit.elements[0].setTexture(tex.getName());
selectorkit.elements[0].flipUVVert();
tex.setOwner(selectorkit.elements[0]);
TextureManagerEx.addImage(tex);

tex = new LinkedTextureImage(hex, "panel-hex-defend", true, true);
tex.printOnto(font, "Defend", 26, 210, false, false);
tex.printOnto(font, "Defend", 26, 12, false, true);
tex.makeTexture();

selectorkit.elements[1].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[1]);
TextureManagerEx.addImage(tex);

tex = new LinkedTextureImage(hex, "panel-hex-killer", true, true);
tex.printOnto(font, "Killer", 26, 210, false, false);
tex.printOnto(font, "Killer", 26, 12, false, true);
tex.makeTexture();

selectorkit.elements[2].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[2]);
TextureManagerEx.addImage(tex);

tex = new LinkedTextureImage(hex, "panel-hex-slash", true, true);
tex.printOnto(font, "Slash", 26, 210, false, false);
tex.printOnto(font, "Slash", 26, 12, false, true);
tex.makeTexture();

selectorkit.elements[3].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[3]);
TextureManagerEx.addImage(tex);

tex = new LinkedTextureImage(hex, "panel-hex-drain", true, true);
tex.printOnto(font, "Drain", 26, 210, false, false);
tex.printOnto(font, "Drain", 26, 12, false, true);
tex.makeTexture();

selectorkit.elements[4].setTexture(tex.getName());
tex.setOwner(selectorkit.elements[4]);
TextureManagerEx.addImage(tex);
}
}
}

this.box = XMLLoader.loadObjectXML("res/xml/avat-shiva.xml", HUDTest.modelsdir, HUDTest.texdir);
this.box.averageCollisionXZ();
this.box.setCollisionMode(Object3D.COLLISION_CHECK_SELF);
this.box.setCollisionOptimization(Object3D.COLLISION_DETECTION_OPTIMIZED);
this.mainpanel.getWorld().addObjectEx(this.box);

this.camera.setObject(this.box);
this.camera.setPullIn(false);
this.camera.setDistance(0.5f);
this.camera.cameraChangeAngle(0, 0, this.mainpanel.getWorld());

tobject = XMLLoader.loadObjectXML("res/xml/obj-pointer.xml", "res/models/", "res/tex/");
if(tobject != null) {
tobject.setSelectable(false);
this.mainpanel.getTopWorld().addObjectEx(tobject);

AnimatorStayWith animator = new AnimatorStayWith(tobject);
animator.offsetAboveTarget();
animator.setSpeed(1.0f);
animator.setCamera(this.camera);
animator.setMaxDistance(20.0f);
animator.setVisibility(false);
this.mainpanel.getWorld().addActor(new Actor("Pointer", tobject, animator, this.mainpanel.getWorld(), false));

WorldSelector selector = new WorldSelector(this.mainpanel.getWorld(), this.box, animator, 10.0f);
selector.setClickOnly(true);
selector.setMaxRange(20.0f);
this.eventhandler.addWorldSelector(selector);

WorldSelectionBinding event = new WorldSelectionBinding("Object-Click", selector);
event.setMouseWheel(true);
event.setKeyEvent(new KeyDualBinding('q', 'e', 0, EventBinding.KEY_TYPED));
event.setWorld(this.mainpanel.getWorld());
event.setControllerEvent(new ControllerAxisBinding(false, ControllerBinding.DIRECTIONAL, ControllerBinding.XDIRECTION));
event.setController(this.controller);
event.setHitCheck(true);
this.eventhandler.addEvent(event);
}


this.mainanimator = new AnimatorCharacter(this.box);
this.mainanimator.setCurrentMeshAnimation("stand", false);
this.mainanimator.setCallback(this);

this.mainactor = new ActorCameraFocal("Actor", this.camera, this.mainanimator, this.mainpanel.getWorld(), true);
this.mainactor.setTeam(0);
this.mainactor.setCollision(true);
this.mainactor.setBounds(new SimpleVector(30.0f, 150.0f, 20.0f));
this.mainactor.setChangeAnimation(true);
this.mainactor.setScale(0.5f);
this.mainactor.setPickable(true);
this.mainactor.setPausable(true);
this.camera.setLinkedActor(this.mainactor);
this.mainpanel.getWorld().addActor(this.mainactor);

this.mover = new ActorBinding(null, this.mainactor);
this.mover.setController(this.controller);
this.mover.setControllerEvent(new ControllerAxisBinding(false, ControllerBinding.LEFT));
this.mover.getControllerEvent().scale = 1.0f;
this.mover.setKeyEvent(new KeyQuadBinding(KeyEvent.VK_A, KeyEvent.VK_S, KeyEvent.VK_W, KeyEvent.VK_Z,
0, EventBinding.KEY_HOLD));
this.mover.getKeyEvent().scale = 0.5f;
this.mover.getKeyEvent().continual = false;
this.eventhandler.addEvent(this.mover);

ActorBinding abind = new ActorBinding(null, this.mainactor);
abind.setEffectLift(true);
abind.setController(this.controller);
abind.setControllerEvent(new Controller2ButtonBinding(true, 4, 5));
abind.getControllerEvent().scale = 0.2f;
abind.setMouseEvent(new MouseBinding(EventBinding.MOUSE_FULL_DRAG, 2, 0, 1, EventBinding.AXIS_Y));
abind.getMouseEvent().scale = -0.5f;
this.eventhandler.addEvent(abind);

RadialCameraBinding cevent = new RadialCameraBinding(null, this.camera);
cevent.setWorld(this.mainpanel.getWorld());
cevent.setController(this.controller);
cevent.setControllerEvent(new ControllerAxisBinding(true, ControllerBinding.RIGHT));
cevent.getControllerEvent().scale = 0.025f;
cevent.setMouseEvent(new MouseBinding(EventBinding.MOUSE_FULL_DRAG, 3, 0, 1, EventBinding.AXIS_BOTH));
cevent.getMouseEvent().scale = 0.05f;
this.eventhandler.addEvent(cevent);

EventBinding gevent = new EventBinding("Pause");
gevent.setController(this.controller);
gevent.setControllerEvent(new ControllerButtonBinding(false, 9));
gevent.setKeyEvent(new KeyBinding(KeyEvent.VK_P, 0, EventBinding.KEY_PRESSED));
gevent.setCallback(this);
this.eventhandler.addEvent(gevent);
this.canvashandler.addEvent(gevent);

gevent = new EventBinding("Canvas");
gevent.setController(this.controller);
gevent.setControllerEvent(new ControllerButtonBinding(false, 3));
gevent.setKeyEvent(new KeyBinding(KeyEvent.VK_ESCAPE, 0,
EventBinding.KEY_PRESSED));
gevent.setCallback(this);
this.eventhandler.addEvent(gevent);

CanvasBinding canevent = new CanvasBinding(null, this.basecanvas);
canevent.setController(this.controller);
canevent.setControllerEvent(new ControllerAxisBinding(false, ControllerBinding.DIRECTIONAL, ControllerBinding.BOTH));
canevent.setEffectPointer(true);
this.canvashandler.addEvent(canevent);

canevent = new CanvasBinding(null, this.basecanvas);
canevent.setController(this.controller);
canevent.setControllerEvent(new Controller2ButtonBinding(false, 4, 5));
canevent.setNavigateWidgets(true);
this.canvashandler.addEvent(canevent);

canevent = new CanvasBinding(null, this.basecanvas);
canevent.setController(this.controller);
canevent.setControllerEvent(new ControllerButtonBinding(false, 1));
canevent.setSimulateClick(true);
this.canvashandler.addEvent(canevent);

AmbientFull fogger = new AmbientFull(this.mainpanel.getWorld());
this.mainpanel.getWorld().setAmbient(fogger);
fogger.setLight(new ColorFloat(128,128,128), new ColorFloat(200,64,64), 0.001f);
fogger.setFogging(true);
fogger.setFogger(new ColorFloat(-255.0f,128.0f,-255.0f), new ColorFloat(-255.0f,-255.0f,-255.0f));
fogger.setFogRange1(20.0f, 40.0f);
fogger.setFogRange2(50.0f, 70.0f);

LightFlicker light = new LightFlicker(this.mainpanel.getWorld(), "red");
light.set(-3, -3, -3, 255, 0, 0, 30.0f, 5.0f);
light.setFlicker(new ColorFloat(255,0,0), new ColorFloat(255,255,0), 0.01f);

light = new LightFlicker(this.mainpanel.getWorld(), "blue");
light.set(-3, -3, 3, 255, 0, 0, 30.0f, 5.0f);
light.setFlicker(new ColorFloat(0,0,255), null, 0.025f);

this.mainpanel.getWorld().addLight("main", 0, -3, 0, 255, 255, 255, 30.0f, 5.0f);
// this.mainpanel.getWorld().createTriangleStrips();
// this.gui3d.createTriangleStrips();
// this.mainpanel.getTopWorld().createTriangleStrips();
}

public static void main(String[] args) {
HUDTest app = new HUDTest();
try {
app.loop();
} catch (Exception e) {
e.printStackTrace();
}
}

private void loop() throws Exception {
System.out.println("Looping");
if(!GamePads.isInitialized()) GamePads.initialize();
this.mainpanel.setRenderGL(true);
this.textlayer.addLine("Environment simulation loaded.");
this.textlayer.addLine("Avatar Shiva loaded.");
this.textlayer.addLine("Interface initiated.");
this.textlayer.addLine("Login in progress ...");
this.mainpanel.clearTimer();

while (this.isShowing()) {
while(this.eventhandler.hasCommands() || this.canvashandler.hasCommands()) {
String tcomm = "";
if(this.eventhandler.hasCommands()) tcomm = this.eventhandler.popCommand();
else if(this.canvashandler.hasCommands()) tcomm = this.canvashandler.popCommand();
System.out.println(tcomm);
this.textlayer.addLine(tcomm);

this.hextoggle.toggleCommand(tcomm);
if(tcomm.compareTo("Panel-2") == 0) {
this.mainanimator.setCurrentMeshAnimation("access", true);
}
if(tcomm.compareTo("Panel-3") == 0) {
this.mainanimator.setCurrentMeshAnimation("delete", true);
// AudioManager.pauseLoop(true);
}
if(tcomm.compareTo("Panel-4") == 0) {
TextureSequence seq = TextureManagerEx.getSequence("dissolve");
this.mainanimator.setTextureSequence(seq);
this.mainanimator.setCurrentMeshAnimation("dissolve", false);
// AudioManager.pauseLoop(false);
}
if(tcomm.compareTo("Panel-5") == 0) {
TextureSequence seq = TextureManagerEx.getSequence("appear");
this.mainanimator.setTextureSequence(seq);
this.mainanimator.setAnimateMesh(false);
this.mainanimator.setCurrentMeshAnimation("appear", true);
// AudioManager.playEffect(this.ping);
}
if(tcomm.compareTo("Panel-6") == 0) {
this.mainanimator.setCurrentMeshAnimation("failb", true);
}
if(tcomm.compareTo("Pause") == 0) {
if(this.mainpanel.isRenderGL()) {
this.mainpanel.setPaused(!this.mainpanel.isPaused());
this.mover.setEnabled(!this.mainpanel.isPaused());
} else {
this.mainpanel.setPaused(true);
this.mover.setEnabled(false);
this.mainpanel.setRenderGL(true);
}
}
if(tcomm.compareTo("Canvas") == 0) {
if(this.mainpanel.isRenderGL()) {
this.mainpanel.snapshot(this.basecanvas.getBackImage());
this.mainpanel.setRenderGL(false);
}
}
}
this.mainpanel.renderScene();
Thread.sleep(30);
}

System.out.println("Exiting!");
this.mainpanel.dispose();
this.eventhandler.removeFixer();
System.exit(0);
}

@Override
public boolean eventCall(int event, EventBinding binding) {
System.out.println("Callback!");
return true;
}

@Override
public void animateCallback(Animator animator, int event) {
if(animator == this.mainanimator) {
if(event == AnimatorCallback.TEXTURE_DONE) {
this.mainanimator.setAnimateMesh(true);
}
if(event == AnimatorCallback.MESH_DONE) {

}
}
}

}


I really suck with comments, so I don't actually put many inside my code itself, so sorry about that. Anyhow, this is the mucky way of making an app with the library, but it demonstrates (tests) a lot of the core methods and objects so that's why it's mucky instead of well done. A real app would be written much cleaner, but this is the one used for the screenshots.

An example XML file used, the avat-shiva.xml

<?xml version="1.0"?>
<base>
    <type>md2</type>
    <filename>avatars/shiva.md2</filename>
    <scale>1.0</scale>
    <object>
        <model name="Shiva-0_Shiva">
            <name>avatar-shiva</name>
            <setting name="EnvMap">false</setting>
            <setting name="Culling">true</setting>
            <setting name="Compile">true</setting>
            <setting name="Specular">true</setting>
            <setting name="Transparency">128</setting>
            <setting name="CollisionEllipse">1.0</setting>
            <setting name="Color">128,128,128</setting>
        </model>
        <animations>
            <sequence name="faila" cyclic="false">0.01</sequence>
            <sequence name="run" cyclic="true">0.01</sequence>
            <sequence name="appear" cyclic="false">0.01</sequence>
            <sequence name="scan" cyclic="true">0.005</sequence>
            <sequence name="walk" cyclic="true">0.005</sequence>
            <sequence name="access" cyclic="false">0.0075</sequence>
            <sequence name="failb" cyclic="false">0.01</sequence>
            <sequence name="stand" cyclic="true">0.005</sequence>
            <sequence name="dissolve" cyclic="false">0.02</sequence>
            <sequence name="delete" cyclic="false">0.02</sequence>
        </animations>
        <textures speed="0.05" usealpha="true">
            <sequence>shiva-ice</sequence>
            <texture index="0" maintain="false">
                <name>shiva-1</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00000.png</filename>
            </texture>
            <texture index="1" maintain="false">
                <name>shiva-2</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00001.png</filename>
            </texture>
            <texture index="2" maintain="false">
                <name>shiva-3</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00002.png</filename>
            </texture>
            <texture index="3" maintain="false">
                <name>shiva-4</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00003.png</filename>
            </texture>
            <texture index="4" maintain="false">
                <name>shiva-5</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00004.png</filename>
            </texture>
            <texture index="5" maintain="false">
                <name>shiva-6</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00005.png</filename>
            </texture>
            <texture index="6" maintain="false">
                <name>shiva-7</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00006.png</filename>
            </texture>
            <texture index="7" maintain="false">
                <name>shiva-8</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00007.png</filename>
            </texture>
            <texture index="8" maintain="false">
                <name>shiva-9</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00008.png</filename>
            </texture>
            <texture index="9" maintain="false">
                <name>shiva-10</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
                <filename layer="1">avatars/ice-ripple/00009.png</filename>
            </texture>
            <texture index="10" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="11" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="12" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="13" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="14" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="15" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="16" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="17" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="18" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="19" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="20" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="21" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
            <texture index="22" maintain="false">
                <name>shiva-0</name>
                <filename layer="0">avatars/shiva-outer.png</filename>
            </texture>
        </textures>
    </object>
</base>
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

Just a quick update on the progress. I am almost happy with the arrangement and will hopefully be out of the experimental phase of development and have a real version to launch. Some of the actor, animation, and manipulation classes are still a bit of a mess though. Trying to make the semantics for the classes to be universal yet comprehensive, without weighing it down.

The current method is:

Actor: Controls the object in the world space, based on game needs. This merges objects with everything else, and is only needed for objects that interact in the world, static map like objects with no animations will not need this class.
Animator: Animated object animations based on time passed. Only needed for objects with animations or animated texture sequences.
Manipulator: Moves the objects or alters some of the object settings based on time passed.

Currently only one manipulator is installed per actor, I am debating multiple manipulators per actor, though manipulators can effect multiple objects or even be used in other classes effecting objects. The base manipulator is an interface, not a class, making it easier to extend hopefully. Considering a "wandering" actor, but I'm having a difficult time figuring out exactly how to work that without limiting it too much or making it too elaborate.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

SNAFU, pretty big one. My method for texture management was too heavy on memory I think, either that or I'm swapping objects to the new class wrong, could be either. I need to sleep on it to figure it out but any ideas may be helpful if anyone has any. Currently to port an object3D into the new class I'm using super(object3D, true) to reuse mesh data, unsure if it holds the original when I do that or not, if it does then I may just need to fix that.

I do need to rework the textures+images system though, it's messy now that I look at it, and far from neat. I neglected a lot of problem areas through the experimental portion of development, and now seeing issues that will arise eventually. Heap stack keeps screaming at me and I think streamlining the textures will help prevent future problems there.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

EgonOlsen

Quote from: KittenKoder on November 09, 2012, 04:12:04 PM
Currently to port an object3D into the new class I'm using super(object3D, true) to reuse mesh data, unsure if it holds the original when I do that or not, if it does then I may just need to fix that.
...the "orginal" what is it supposed to hold? This constructor makes an Object3D share the mesh with another. If you use compile() on your objects, you might consider to use shareCompiledData() as well.

KittenKoder

Quote from: EgonOlsen on November 09, 2012, 09:04:26 PM
Quote from: KittenKoder on November 09, 2012, 04:12:04 PM
Currently to port an object3D into the new class I'm using super(object3D, true) to reuse mesh data, unsure if it holds the original when I do that or not, if it does then I may just need to fix that.
...the "orginal" what is it supposed to hold? This constructor makes an Object3D share the mesh with another. If you use compile() on your objects, you might consider to use shareCompiledData() as well.

Well, i don't call compile until after the new one is made, I let the old Object3D die after I am finished with it. The point was if there was a reference to the original Object3D somewhere  that i am unaware of. On my end the object is only used to create the new object then it's gone. But the library needs the data that's in the extended Object3D to work efficiently.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

I may have figured out the error, which will need an overhaul of my original texture system. It seems that my image manager is likely causing the error. Possibly making too many textures, and I know I'm loading too many "dead" images that are only used for a moment in the test app.

The trick of it is that I need to maintain images of some textures, and not others, and some images don't get made into textures, so I'm still ironing out the specific techniques I want to use for this. I was thinking of using the iTextureEffect with the byte arrays for animated textures, though it would limit the variation with objects using the same animation it would improve memory consumption a lot.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

Alright, before I commit to a specific method, which would be harder on the CPU for texture animations:

1. Loading all the frames to the GPU then setting a different frame each "pass."

2. Using an ITextureEffect and updating the buffer directly each "pass."

A "pass" is when the frame actually changes.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

Slight change in plans, though not massive. I developed a pretty decent 3D GUI system, but the drain on the CPU due to collision checks and such with the mouse have made me choose to change gears a bit. Getting rid of the "picking" with the mouse completely, for the 3D GUI, most games use hotkeys for such things anyway so I'm probably just going too big. I am also going to put more focus on the HUD system, making it into a full GUI which will respond to the mouse. As it is I have to do something that will wind up abusing memory and queuing all the events in order to prevent some serious glitches when working cross threads, Swing's event system demands such and that's sort of the purpose of this library, to merge Swing with the GL rendering.

So to recap:

1. More focus on 2D HUD elements and interactions.
2. Elimination of 3D GUI object "picking."
3. A more refined event queue system.
4. A HUD system that's comprehensive and useful, as well as more GUI capable, that means event bindings and animations for the HUD elements themselves.

For those interested, I managed to iron out the texture system in a way that will actually benefit even small projects. Added a new object, the Scene object, which only tracks things that are unique to that scene allowing you to remove them easier and faster when changing scenes. Considering being rid of the 3D GUI completely, as cool as it looks, I want my library to be capable of operating on lower level machines than modern top of the line, the 2D HUD system can look not only as smooth, but also more like what people are used to for widgets anyway.

If there are any suggestions of ideas, please let me know, also any specific requests. I will hold onto the 3D GUI and maybe develop it further later on, but for now I prefer the 2D one.
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

Alright, I got the Blender to Kitt jPCT engine scripts done, here's a scene exported from Blender to the engine.





The beams and the green ground have animated textures, the ground shimmers, the small beams look like blips flying through, and the big one looks freaking cool animated. lol
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

KittenKoder

Quick update, the code for the above test app is now:


package app;

import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

import kitt.com.jpct.GameControls;
import kitt.com.jpct.XMLLoader;
import kitt.com.jpct.anim.Animator;
import kitt.com.jpct.anim.AnimatorCallback;
import kitt.com.jpct.event.CanvasEventHandler;
import kitt.com.jpct.event.Controller2ButtonBinding;
import kitt.com.jpct.event.ControllerAxisBinding;
import kitt.com.jpct.event.ControllerBinding;
import kitt.com.jpct.event.ControllerButtonBinding;
import kitt.com.jpct.event.EventHandler;
import kitt.com.jpct.event.KeyBinding;
import kitt.com.jpct.event.bind.CanvasBinding;
import kitt.com.jpct.event.bind.EventBinding;
import kitt.com.jpct.event.bind.EventBindingCallback;
import kitt.com.jpct.ext.GameWorld;
import kitt.com.jpct.ext.Object3DEx;
import kitt.com.jpct.ext.RadialCamera;
import kitt.com.jpct.game.ControllerData;
import kitt.com.jpct.game.GamePads;
import kitt.com.jpct.hud.HUDCellElement;
import kitt.com.jpct.hud.HUDElement;
import kitt.com.jpct.hud.HUDManager;
import kitt.com.jpct.hud.HUDTextLayer;
import kitt.com.jpct.hud.HUDTextureElement;
import kitt.com.jpct.hud.anim.HUDAnimator;
import kitt.com.jpct.hud.kits.HUDSelectorKit;
import kitt.com.jpct.scene.Scene;
import kitt.com.jpct.swing.GLPanel;
import kitt.com.jpct.swing.RenderCallback;
import kitt.com.jpct.tex.TextureEx;
import kitt.com.jpct.tex.TextureLabel;
import kitt.com.jpct.tex.TextureSequence;
import kitt.com.jpct.tex.TextureStored;
import kitt.com.jpct.tex.TextureSystem;
import kitt.com.math.Coordinate;
import kitt.com.math.Dimension;
import kitt.com.swing.Util;
import kitt.com.swing.canvas.CanvasButton;
import kitt.com.swing.canvas.CanvasGUI;
import kitt.com.swing.canvas.CanvasLabel;
import kitt.com.swing.canvas.CanvasPointer;
import kitt.com.swing.canvas.data.CanvasImageFont;
import kitt.com.swing.canvas.kits.MenuKit;
import kitt.com.swing.canvas.kits.ToggleMenuKit;
import kitt.com.swing.canvas.kits.WidgetKits;

import com.threed.jpct.Config;
import com.threed.jpct.Object3D;
import com.threed.jpct.Texture;

public class HUDTest extends JFrame implements EventBindingCallback, RenderCallback, AnimatorCallback {
private static final long serialVersionUID = 1L;

private static final String modelsdir = "res/models/";
private static final String texdir = "res/tex/";
    private static final String xmldir = "res/xml/";

private GLPanel mainpanel = null;
private HUDManager hud = null;
private TextureStored guitexture = null;
private TextureStored barstexture = null;
private RadialCamera camera = null;
private ControllerData controller = null;
private GameWorld gameworld = null;
// private File ping = null;

private Object3DEx box = null;
private CanvasEventHandler canvashandler = null;
private HUDTextLayer textlayer = null;
private CanvasImageFont font = null;

private CanvasGUI basecanvas = null;

private GameControls gamecontroller = null;

public HUDTest() throws HeadlessException {
this.setup();
}

private void setup() {
this.setTitle("HUD Test");
this.setBounds(0, 0, 256, 256);
this.setLocationRelativeTo(null);

this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
this.setResizable(false);
Container cpane = this.getContentPane();
cpane.setLayout(null);

this.setVisible(true);
Dimension dim = Util.getRealSize(this, 1024, 768);
Coordinate loc = Util.centerScreen(dim.width, dim.height);
this.setBounds(loc.x, loc.y, dim.width, dim.height);

// Config.isIndoor = true;
Config.tuneForOutdoor();
Config.doSorting = false;
Config.glFullscreen = false;
Config.glAvoidTextureCopies = true;
Config.glColorDepth = 24;
// Config.maxAnimationSubSequences = 10;
Config.farPlane = 100;
Config.glShadowZBias = 0.5f;
Config.saveMemory=true;
Config.maxTextureLayers = 2;
Config.maxPolysVisible = 20000;
Config.collideOffset = 1;
Config.glUseIgnorantBlits = true;
Config.autoBuild = true;
Config.lightMul = 5;
// Config.glTrilinear = true;

this.mainpanel = new GLPanel(1024, 768);
this.mainpanel.setRenderGL(false);
this.gameworld = this.mainpanel.getWorld();

// AudioManager.playLoop("res/audio/music/danosongs.com-bitbybits.ogg", -5.0f);
// this.ping = new File("res/audio/effects/ping.wav");

this.basecanvas = new CanvasGUI();
this.mainpanel.setBaseCanvas(this.basecanvas);
this.basecanvas.setBackground(new Color(0,128,128,128));
this.basecanvas.setForeground(new Color(64,255,255));
this.basecanvas.setName("Main Menu");
this.basecanvas.setFont(CanvasGUI.FONTLARGE);
this.basecanvas.setTextColor(Color.WHITE);

CanvasGUI.DEFAULT_DISABLED = new Color(255,0,0,128);
CanvasGUI.DEFAULT_HOVER = new Color(0,255,0,128);
CanvasGUI.DEFAULT_PRESSED = new Color(0,0,255,128);
CanvasGUI.DEFAULT_FOREGROUND = new Color(0,255,0);
CanvasGUI.DEFAULT_BACKGROUND = CanvasGUI.HALFBLACK;;

this.canvashandler = new CanvasEventHandler(this.basecanvas);
this.canvashandler.addTo(this.basecanvas);
this.mainpanel.setCurrentEventHandler(this.canvashandler);

this.basecanvas.setFlags(CanvasGUI.ROUNDED | CanvasGUI.BORDER);

this.guitexture = TextureSystem.loadStoredImage("res/tex/gui/base.png", "gui");
this.guitexture.makeTexture();
this.guitexture.addTexture();
this.barstexture = TextureSystem.loadStoredImage("res/tex/gui/bars-ver.png", "bars");
this.barstexture.makeTexture();
this.barstexture.addTexture();
TextureStored image = TextureSystem.loadStoredImage("res/tex/font-base.png", "font");
CanvasGUI.IMAGEFONT = new CanvasImageFont(image.getImage(), 32, 32);
CanvasGUI.IMAGEFONT.setBaseline(8);
CanvasGUI.IMAGEFONT.setAsciiOffset(32);
CanvasGUI.IMAGEFONT.setScale(0.5f);
TextureStored[] icons = XMLLoader.loadStoredPackFromXML("res/xml/texpack-icons.xml", HUDTest.texdir, null);
XMLLoader.loadStoredPackFromXML("res/xml/texpack-basic.xml", HUDTest.texdir, null);

image = TextureSystem.loadStoredImage("res/tex/icons/icon-logo-full.png", "icon-logo");
CanvasLabel label = new CanvasLabel(null, "Hacker's\nHaven", 100, 50, 100, 100);
label.setFlags(CanvasGUI.ROUNDED | CanvasGUI.BORDER | CanvasGUI.SHOWTEXT |
CanvasGUI.TEXT_LEFT | CanvasGUI.TEXT_TOP | CanvasGUI.IMAGE_STRETCH);
label.setImage(image.getImage());
this.basecanvas.addWidget(label);

CanvasButton button = new CanvasButton(null, "Pause", 0, 0, 100, 100);
button.setID("Pause");
this.basecanvas.addWidget(button);

String[][] options = {
{"GameStart", "Start"},
{"GameLoad", "Load"},
{"GameConfigure", "Settings"},
{"GameDelete", "Delete"},
{"GameExit", "Exit"}
};
MenuKit menu = WidgetKits.makeMenu(this.basecanvas, "Main Menu",
null, 150, 40,
options, 3, -1);
menu.parent.setLocation(200, 250);
menu.parent.setEnabled(false);

CanvasGUI.DEFAULT_FOREGROUND = new Color(0,255,255);

String[][] toptions = {
{"GameFun", "Fun"},
{"GameWicked", "Wicked"},
{"GameCool", "Cool"},
{"GameRun", "Run"}
};
ToggleMenuKit togglemenu = WidgetKits.makeToggleMenu(this.basecanvas, "Sub Menu",
null, 150, 40,
toptions, 2, CanvasGUI.HEXAGONAL | CanvasGUI.BORDER | CanvasGUI.SHOWTEXT |
CanvasGUI.TEXT_RIGHT | CanvasGUI.TEXT_BOTTOM | CanvasGUI.FILL  | CanvasGUI.IMAGE_STRETCH);
togglemenu.parent.setLocation(400, 50);
togglemenu.parent.setSingleToggle(true);
for (int i = 0; i < togglemenu.options.length; i++) {
togglemenu.options[i].setImage(icons[i].getImage());
}

CanvasPointer pointer = new CanvasPointer(this.guitexture.getImage());
pointer.setImageOffset(new Coordinate(0, 200));
pointer.setImagePart(new Dimension(64,64));
pointer.setSize(64, 64);
pointer.setLocation(-8, -20);
this.basecanvas.setPointer(pointer);

this.basecanvas.setBackImage(new BufferedImage(this.mainpanel.getWidth(), this.mainpanel.getHeight(),
BufferedImage.TYPE_INT_RGB));

this.guitexture.makeTexture();
this.barstexture.makeTexture();

this.mainpanel.setLocation(0, 0);
cpane.add(this.mainpanel);
this.mainpanel.alignBaseCanvas();

this.gamecontroller = new GameControls(this.gameworld, this.mainpanel.getBuffer());
this.hud = this.gamecontroller.getHUD();
// EventHandler.installFixer();

this.mainpanel.addEventHandler(this.gamecontroller.getHandler());
this.mainpanel.setCurrentEventHandlerGL(this.gamecontroller.getHandler());
this.mainpanel.setHUD(this.hud);

this.controller = GamePads.getController(0);
if (this.controller != null) {
this.controller.setEnabled(true);
System.out.println("Controller Enabled");
this.gamecontroller.setControllerDevice(this.controller);
this.canvashandler.addController(this.controller);
}

this.camera = new RadialCamera();
this.gameworld.setCameraTo(this.camera);
this.camera.setDistance(0.05f);

HUDTextureElement element = new HUDTextureElement(null, "text", 0, 512, 1024, 256);
element.setTexture(this.guitexture.getTexture(), 0, 0, 1024, 200);
element.setZOrder(0);
this.hud.add(element);

this.font = new CanvasImageFont(CanvasGUI.IMAGEFONT, 0.8f);

this.textlayer = new HUDTextLayer(element, "text-layer", 0, 0, 1024, 256);
this.textlayer.setZOrder(1);
this.textlayer.setFont(font);
this.textlayer.setBorder(32);
this.textlayer.setZOrder(1);
this.hud.add(this.textlayer);

TextureStored tex = TextureSystem.findStoredImage(null, "hud-panel-option");
if(tex != null) tex.addTexture();

HUDSelectorKit selectorkit = HUDSelectorKit.makeMenuSelector(
HUDSelectorKit.CELLELEMENTS, "Menu", null, "Panel",
-200.0f, 50.0f, 256.0f, 32.0f, 10, this.hud, null, tex, 0, 0, 512, 64);
if(selectorkit != null) {
        HUDAnimator animator = new HUDAnimator();
        animator.setTranslation(200.0f, -8.0f);
        animator.setSpeed(0.025f);
        animator.setScale(1.0f, 1.5f);
       
            HUDAnimator select = new HUDAnimator();
            select.setSpeed(0.1f);
            select.setTranslation(0.0f, 10.0f);
            select.setBounce(true);

    this.gamecontroller.setHUDList(selectorkit.elements, animator, select);
   
for(HUDElement elem : selectorkit.elements) {
    TextureLabel ntex = new TextureLabel(tex, elem.getName());
    ntex.initializeCenters(2);
    ntex.getCenters()[0] = new Coordinate(256, 32);
                ntex.getCenters()[1] = new Coordinate(768, 32);
                ntex.setFont(this.font);
                ntex.setText(elem.getName());
                ntex.updateText();
                ntex.makeTexture();
                ntex.addTexture();
                TextureSystem.addStoredImage(ntex);
                ((HUDTextureElement)elem).setTexture(ntex.getTexture());
}
}

tex = TextureSystem.findStoredImage(null, "hud-icon-hex");
if(tex != null) tex.addTexture();
selectorkit = HUDSelectorKit.makeSelector(HUDSelectorKit.EVENODD | HUDSelectorKit.HEXAGONAL |
HUDSelectorKit.HORIZONTAL | HUDSelectorKit.OFFSETUP | HUDSelectorKit.CELLELEMENTS,
"Menu", null, "Hex",
800.0f, 50.0f, 80.0f, 80.0f, 3, 3, this.hud, null, tex, 0, 0, 128, 128);
if(selectorkit != null) {
String[] iconnames = {
"icon-buffer",
"icon-clone",
"icon-crash-bomb",
"icon-decode",
"icon-deflector",
"icon-firewall",
"icon-mask",
"icon-slicer",
"icon-spy-bot",
"icon-torrent"
};
for(int i = 0; i < iconnames.length; i++) {
TextureStored icontex = TextureSystem.findStoredImage(null, iconnames[i]);
if(icontex != null && tex != null) {
BufferedImage img = Util.cloneImage(tex.getImage());
Graphics2D g = (Graphics2D)img.getGraphics();
Util.quickPaint(g, icontex.getImage(), 0, 0, false, false);
Util.quickPaint(g, icontex.getImage(), 128, 0, false, false);
g.dispose();
TextureEx eltex = new TextureEx(null, "hex-" + iconnames[i], new Texture(img, true));
TextureSystem.addTexture(eltex);
eltex.addTexture();
System.out.println(eltex.getName());
((HUDCellElement)selectorkit.elements[i]).setTexture(eltex.getTexture());
if(i == (i/3)*3)
((HUDCellElement)selectorkit.elements[i]).setCell(1);
}
}
}

this.hud.zSort();

// TextureSequence tseq = XMLLoader.loadSequenceFromXML("res/xml/texseq-dissolve.xml", HUDTest.texdir, null);
// tseq.addTextures();
// tseq = XMLLoader.loadSequenceFromXML("res/xml/texseq-appear.xml", HUDTest.texdir, null);
// tseq.addTextures();
TextureSequence tanim = XMLLoader.loadSequenceFromXML("res/xml/texseq-barslide.xml", HUDTest.texdir, null);
tanim.addTextures();
// tseq = XMLLoader.loadSequenceFromXML("res/xml/texseq-grid-shine.xml", HUDTest.texdir, null);
// tseq.makeTexture();

// if(tseq != null) {
// AnimatedBackground background = new AnimatedBackground("background", this.mainpanel.getCanvas());
// background.setTexture(tseq);
// background.setFullImage();
// this.mainpanel.setBackgroundElement(background);
// }

Scene scene = XMLLoader.loadSceneFromXML("res/xml/scene-internet.xml", HUDTest.xmldir, HUDTest.modelsdir, HUDTest.texdir);
scene.setWorld(this.gameworld);
scene.setScene();

this.box = XMLLoader.loadObjectXML("res/xml/avat-shiva.xml", HUDTest.modelsdir, HUDTest.texdir);
this.box.averageCollisionXZ();
this.box.setCollisionMode(Object3D.COLLISION_CHECK_SELF);
this.box.setCollisionOptimization(Object3D.COLLISION_DETECTION_OPTIMIZED);
        this.box.translate(scene.getSpawn("Logon"));
this.gameworld.addObjectEx(this.box);
this.gamecontroller.setPlayerObject(this.box);
        this.gamecontroller.getPlayerAnimator().setCurrentMeshAnimation("stand", false);

element = new HUDTextureElement(null, "Pointer", 0, 0, 32, 32);
element.setTexture(this.guitexture.getTexture(), 64, 200, 64, 64);
element.setVisible(true);
this.hud.add(element);
this.gamecontroller.setPointer(element);

EventBinding gevent = new EventBinding("Pause");
gevent.setController(this.controller);
gevent.setControllerEvent(new ControllerButtonBinding(false, 9));
gevent.setKeyEvent(new KeyBinding(KeyEvent.VK_P, 0, EventBinding.KEY_PRESSED));
gevent.setCallback(this);
this.gamecontroller.getHandler().addEvent(gevent);
this.canvashandler.addEvent(gevent);

gevent = new EventBinding("Canvas");
gevent.setController(this.controller);
gevent.setControllerEvent(new ControllerButtonBinding(false, 3));
gevent.setKeyEvent(new KeyBinding(KeyEvent.VK_ESCAPE, 0,
EventBinding.KEY_PRESSED));
gevent.setCallback(this);
this.gamecontroller.getHandler().addEvent(gevent);

CanvasBinding canevent = new CanvasBinding(null, this.basecanvas);
canevent.setController(this.controller);
canevent.setControllerEvent(new ControllerAxisBinding(false, ControllerBinding.DIRECTIONAL, ControllerBinding.BOTH));
canevent.setEffectPointer(true);
this.canvashandler.addEvent(canevent);

canevent = new CanvasBinding(null, this.basecanvas);
canevent.setController(this.controller);
canevent.setControllerEvent(new Controller2ButtonBinding(false, 4, 5));
canevent.setNavigateWidgets(true);
this.canvashandler.addEvent(canevent);

canevent = new CanvasBinding(null, this.basecanvas);
canevent.setController(this.controller);
canevent.setControllerEvent(new ControllerButtonBinding(false, 1));
canevent.setSimulateClick(true);
this.canvashandler.addEvent(canevent);

this.gamecontroller.enableControls();
}

public static void main(String[] args) {
HUDTest app = new HUDTest();
try {
app.loop();
} catch (Exception e) {
e.printStackTrace();
}
}

private void loop() throws Exception {
System.out.println("Looping");
if(!GamePads.isInitialized()) GamePads.initialize();
this.mainpanel.setRenderGL(true);
this.textlayer.addLine("Environment simulation loaded.");
this.textlayer.addLine("Avatar Shiva loaded.");
this.textlayer.addLine("Interface initiated.");
this.textlayer.addLine("Login in progress ...");
this.mainpanel.clearTimer();

while (this.isShowing()) {
while(this.gamecontroller.getHandler().hasCommands() || this.canvashandler.hasCommands()) {
String tcomm = "";
if(this.gamecontroller.getHandler().hasCommands()) tcomm = this.gamecontroller.getHandler().popCommand();
else if(this.canvashandler.hasCommands()) tcomm = this.canvashandler.popCommand();
System.out.println(tcomm);
this.textlayer.addLine(tcomm);

if(tcomm.compareTo("Panel-2") == 0) {
this.gamecontroller.getPlayerAnimator().setCurrentMeshAnimation("access", true);
}
if(tcomm.compareTo("Panel-3") == 0) {
this.gamecontroller.getPlayerAnimator().setCurrentMeshAnimation("delete", true);
// AudioManager.pauseLoop(true);
}
if(tcomm.compareTo("Panel-4") == 0) {
// AudioManager.pauseLoop(false);
}
if(tcomm.compareTo("Panel-5") == 0) {
this.gamecontroller.getPlayerAnimator().setCurrentMeshAnimation("appear", true);
// AudioManager.playEffect(this.ping);
}
if(tcomm.compareTo("Panel-6") == 0) {
this.gamecontroller.getPlayerAnimator().setCurrentMeshAnimation("failb", true);
}
if(tcomm.compareTo("Pause") == 0) {
if(this.mainpanel.isRenderGL()) {
this.mainpanel.setPaused(!this.mainpanel.isPaused());
this.gamecontroller.setPause(this.mainpanel.isPaused());
} else {
this.mainpanel.setRenderGL(true);
}
}
if(tcomm.compareTo("Canvas") == 0) {
if(this.mainpanel.isRenderGL()) {
this.mainpanel.snapshot(this.basecanvas.getBackImage());
                        this.mainpanel.setPaused(true);
                        this.gamecontroller.setPause(true);
this.mainpanel.setRenderGL(false);
}
}
}
this.mainpanel.renderScene();
Thread.sleep(30);
}

System.out.println("Exiting!");
this.mainpanel.dispose();
EventHandler.removeFixer();
System.exit(0);
}

@Override
public boolean eventCall(int event, EventBinding binding) {
System.out.println("Callback!");
return true;
}

@Override
public void animateCallback(Animator animator, int event) {
// if(animator == this.mainanimator) {
// if(event == AnimatorCallback.TEXTURE_DONE) {
// this.mainanimator.setAnimateMesh(true);
// }
// if(event == AnimatorCallback.MESH_DONE) {
//
// }
// }
}

@Override
public void renderCallback() {
// Called after each render.
}

}
When life throws you lemons, make lemon juice, then drop life into a pile of razors and pour the lemon juice over it.

EgonOlsen

Looks very...tronish. I like it.