connecting to character create menu doesn't crash
This commit is contained in:
parent
ad556e3553
commit
5b4f3cede7
File diff suppressed because one or more lines are too long
@ -40,6 +40,7 @@ import electrosphere.game.simulation.MicroSimulation;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.main.Globals;
|
||||
import electrosphere.menu.MenuGenerators;
|
||||
import electrosphere.menu.MenuGeneratorsMultiplayer;
|
||||
import electrosphere.menu.WindowStrings;
|
||||
import electrosphere.menu.WindowUtils;
|
||||
import electrosphere.net.NetUtils;
|
||||
@ -64,6 +65,7 @@ import electrosphere.game.server.unit.UnitUtils;
|
||||
import electrosphere.renderer.ui.DrawableElement;
|
||||
import electrosphere.renderer.ui.WidgetUtils;
|
||||
import electrosphere.renderer.ui.Window;
|
||||
import electrosphere.util.Utilities;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -161,7 +163,7 @@ public class LoadingThread extends Thread {
|
||||
//set simulations to ready if they exist
|
||||
setSimulationsToReady();
|
||||
//log
|
||||
LoggerInterface.loggerEngine.INFO("[Server]Finished loading");
|
||||
LoggerInterface.loggerEngine.INFO("[Server]Finished loading main world");
|
||||
break;
|
||||
|
||||
|
||||
@ -196,7 +198,7 @@ public class LoadingThread extends Thread {
|
||||
creatingRandomEntities();
|
||||
//set simulations to ready if they exist
|
||||
setSimulationsToReady();
|
||||
LoggerInterface.loggerEngine.INFO("[Server]Finished loading");
|
||||
LoggerInterface.loggerEngine.INFO("[Server]Finished loading arena world");
|
||||
break;
|
||||
|
||||
case LOAD_CHARACTER_SERVER:
|
||||
@ -207,25 +209,26 @@ public class LoadingThread extends Thread {
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.NO_INPUT);
|
||||
//initialize the client thread (client)
|
||||
initClientThread();
|
||||
//while we don't know what races are playable, wait
|
||||
while(Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces().size() == 0){
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(5);
|
||||
} catch (InterruptedException ex) {}
|
||||
}
|
||||
//once we have them, bring up the character creation interface
|
||||
//init character creation window
|
||||
WindowUtils.replaceMainMenuContents(MenuGenerators.createEmptyMainMenu());
|
||||
//eventually should replace with at ui to select an already created character or create a new one
|
||||
WindowUtils.replaceMainMenuContents(MenuGeneratorsMultiplayer.createMultiplayerCharacterCreationWindow());
|
||||
//make loading dialog disappear
|
||||
loadingWindow.setVisible(false);
|
||||
//make character creation window visible
|
||||
WindowUtils.recursiveSetVisible(Globals.elementManager.getWindow(WindowStrings.WINDOW_MENU_MAIN), true);
|
||||
//recapture window
|
||||
Globals.controlHandler.setShouldRecapture(true);
|
||||
//set rendering flags
|
||||
Globals.RENDER_FLAG_RENDER_SHADOW_MAP = true;
|
||||
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER_CONTENT = true;
|
||||
Globals.RENDER_FLAG_RENDER_SCREEN_FRAMEBUFFER = true;
|
||||
Globals.RENDER_FLAG_RENDER_UI = true;
|
||||
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
|
||||
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
||||
//log
|
||||
LoggerInterface.loggerEngine.INFO("[Client]Finished loading");
|
||||
//set controls state
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.MAIN_GAME);
|
||||
LoggerInterface.loggerEngine.INFO("[Client]Finished loading character creation menu");
|
||||
//set menu controls again
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.TITLE_MENU);
|
||||
break;
|
||||
|
||||
case LOAD_CLIENT_WORLD:
|
||||
@ -265,7 +268,7 @@ public class LoadingThread extends Thread {
|
||||
Globals.RENDER_FLAG_RENDER_UI = true;
|
||||
Globals.RENDER_FLAG_RENDER_BLACK_BACKGROUND = false;
|
||||
Globals.RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
|
||||
LoggerInterface.loggerEngine.INFO("[Client]Finished loading");
|
||||
LoggerInterface.loggerEngine.INFO("[Client]Finished loading main game");
|
||||
//set controls state
|
||||
Globals.controlHandler.setHandlerState(ControlHandler.ControlsState.MAIN_GAME);
|
||||
break;
|
||||
|
||||
@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class CreatureTypeLoader {
|
||||
|
||||
@ -11,6 +12,8 @@ public class CreatureTypeLoader {
|
||||
|
||||
List<String> playableRaceNames = new LinkedList<String>();
|
||||
|
||||
Semaphore playableRaceLock = new Semaphore(1);
|
||||
|
||||
public void putCreature(String name, CreatureType type){
|
||||
creatureMap.put(name,type);
|
||||
}
|
||||
@ -24,7 +27,21 @@ public class CreatureTypeLoader {
|
||||
}
|
||||
|
||||
public List<String> getPlayableRaces(){
|
||||
return playableRaceNames;
|
||||
List<String> races = null;
|
||||
playableRaceLock.acquireUninterruptibly();
|
||||
races = playableRaceNames;
|
||||
playableRaceLock.release();
|
||||
return races;
|
||||
}
|
||||
|
||||
public void clearPlayableRaces(){
|
||||
playableRaceNames.clear();
|
||||
}
|
||||
|
||||
public void loadPlayableRaces(List<String> races){
|
||||
playableRaceLock.acquireUninterruptibly();
|
||||
playableRaceNames = races;
|
||||
playableRaceLock.release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ import electrosphere.renderer.ui.ClickableElement.ClickEventCallback;
|
||||
import electrosphere.renderer.ui.DraggableElement.DragEventCallback;
|
||||
import electrosphere.renderer.ui.FocusableElement.FocusEventCallback;
|
||||
import electrosphere.renderer.ui.NavigableElement.NavigationEventCallback;
|
||||
import electrosphere.renderer.ui.ValueElement.ValueChangeEventCallback;
|
||||
import electrosphere.renderer.ui.elements.Button;
|
||||
import electrosphere.renderer.ui.elements.Div;
|
||||
import electrosphere.renderer.ui.elements.ImagePanel;
|
||||
@ -44,6 +45,7 @@ import electrosphere.renderer.ui.events.ClickEvent;
|
||||
import electrosphere.renderer.ui.events.DragEvent;
|
||||
import electrosphere.renderer.ui.events.FocusEvent;
|
||||
import electrosphere.renderer.ui.events.NavigationEvent;
|
||||
import electrosphere.renderer.ui.events.ValueChangeEvent;
|
||||
import electrosphere.renderer.ui.form.FormElement;
|
||||
|
||||
import java.util.List;
|
||||
@ -100,7 +102,7 @@ public class MenuGenerators {
|
||||
arenaButton.addChild(arenaLabel);
|
||||
rVal.addChild(arenaButton);
|
||||
arenaButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
|
||||
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CLIENT_WORLD);
|
||||
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
|
||||
Globals.loadingThreadsList.add(clientThread);
|
||||
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_ARENA);
|
||||
Globals.loadingThreadsList.add(serverThread);
|
||||
@ -778,7 +780,8 @@ public class MenuGenerators {
|
||||
int posY = offset * 350 + 100;
|
||||
if(attribute.getType().equals("bone")){
|
||||
Slider attributeSlider = new Slider(50,posY,400,100,new Vector3f(0.1f,0.1f,0.1f),new Vector3f(1.0f,0,0));
|
||||
attributeSlider.setOnValueChange(new Slider.OnSliderChangeCallback() {public void onChange(float value) {
|
||||
attributeSlider.setOnValueChangeCallback(new ValueChangeEventCallback() {public void execute(ValueChangeEvent event) {
|
||||
float value = event.getAsFloat();
|
||||
float minVal = attribute.getMinValue();
|
||||
float range = attribute.getMaxValue() - minVal;
|
||||
float actualValue = minVal + range * value;
|
||||
|
||||
@ -1,51 +1,52 @@
|
||||
package electrosphere.menu;
|
||||
|
||||
import electrosphere.main.Globals;
|
||||
import electrosphere.renderer.ui.ClickableElement;
|
||||
import electrosphere.renderer.ui.Element;
|
||||
import electrosphere.renderer.ui.elements.Button;
|
||||
import electrosphere.renderer.ui.elements.Label;
|
||||
import electrosphere.renderer.ui.elements.StringCarousel;
|
||||
import electrosphere.renderer.ui.events.ClickEvent;
|
||||
import electrosphere.renderer.ui.form.FormElement;
|
||||
|
||||
public class MenuGeneratorsMultiplayer {
|
||||
|
||||
public static Element createMultiplayerCharacterSelectionWindow(){
|
||||
FormElement rVal = new FormElement();
|
||||
// int screenTop = Globals.WINDOW_HEIGHT - 150;
|
||||
int verticalPosition = 125;
|
||||
|
||||
//button (create)
|
||||
Button createButton = new Button();
|
||||
Label createLabel = new Label(100,125 + verticalPosition + 200,1.0f);
|
||||
createLabel.setText("Create Character");
|
||||
createButton.addChild(createLabel);
|
||||
rVal.addChild(createButton);
|
||||
createButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
|
||||
WindowUtils.replaceMainMenuContents(MenuGenerators.createWorldCreationMenu());
|
||||
return false;
|
||||
}});
|
||||
|
||||
return rVal;
|
||||
}
|
||||
|
||||
|
||||
public static Element createMultiplayerCharacterCreationWindow(){
|
||||
FormElement rVal = new FormElement();
|
||||
// int screenTop = Globals.WINDOW_HEIGHT - 150;
|
||||
List<String> saveNames = SaveUtils.getSaves();
|
||||
int verticalPosition = 125;
|
||||
for(String saveName : saveNames){
|
||||
if(!saveName.startsWith(".")){
|
||||
|
||||
//button (select save)
|
||||
Button selectButton = new Button();
|
||||
Label selectLabel = new Label(100,125 + verticalPosition,1.0f);
|
||||
selectLabel.setText(saveName.toUpperCase());
|
||||
selectButton.addChild(selectLabel);
|
||||
rVal.addChild(selectButton);
|
||||
selectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
|
||||
if(SaveUtils.worldHasSave(saveName.toLowerCase())){
|
||||
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
|
||||
Globals.loadingThreadsList.add(clientThread);
|
||||
LoadingThread serverThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
|
||||
Globals.loadingThreadsList.add(serverThread);
|
||||
Globals.RUN_CLIENT = true;
|
||||
Globals.RUN_SERVER = true;
|
||||
clientThread.start();
|
||||
serverThread.start();
|
||||
} else {
|
||||
Globals.currentSaveName = saveName.toLowerCase();
|
||||
SaveUtils.loadTerrainAndCreateWorldData();
|
||||
WindowUtils.replaceMainMenuContents(MenuGenerators.createSaveCreationMenu());
|
||||
}
|
||||
return false;
|
||||
}});
|
||||
|
||||
verticalPosition = verticalPosition + 75;
|
||||
}
|
||||
//select race
|
||||
StringCarousel raceCarousel = new StringCarousel(100, 125, 1.0f);
|
||||
for(String raceName : Globals.gameConfigCurrent.getCreatureTypeLoader().getPlayableRaces()){
|
||||
raceCarousel.addOption(raceName);
|
||||
}
|
||||
rVal.addChild(raceCarousel);
|
||||
|
||||
//button (create)
|
||||
Button createButton = new Button();
|
||||
Label createLabel = new Label(100,125 + verticalPosition + 200,1.0f);
|
||||
createLabel.setText("Create World");
|
||||
Label createLabel = new Label(100,275,1.0f);
|
||||
createLabel.setText("Create Character");
|
||||
createButton.addChild(createLabel);
|
||||
rVal.addChild(createButton);
|
||||
createButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
|
||||
|
||||
@ -22,6 +22,7 @@ import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
@ -45,13 +46,29 @@ public class ClientNetworking implements Runnable{
|
||||
|
||||
ClientProtocol clientProtocol = new ClientProtocol();
|
||||
|
||||
static final int MAX_CONNECTION_ATTEMPTS = 10;
|
||||
|
||||
public ClientNetworking(String address, int port){
|
||||
try {
|
||||
this.socket = new Socket(address,port);
|
||||
} catch (IOException ex) {
|
||||
System.err.println("Failed to connect!");
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
int connectionAttempts = 0;
|
||||
boolean connected = false;
|
||||
while(!connected){
|
||||
try {
|
||||
this.socket = new Socket(address,port);
|
||||
} catch (IOException ex) {
|
||||
LoggerInterface.loggerNetworking.WARNING("Client failed to connect!");
|
||||
} finally {
|
||||
connected = true;
|
||||
}
|
||||
if(!connected){
|
||||
try {
|
||||
TimeUnit.MILLISECONDS.sleep(50);
|
||||
} catch (InterruptedException e) {}
|
||||
connectionAttempts++;
|
||||
}
|
||||
if(connectionAttempts > MAX_CONNECTION_ATTEMPTS){
|
||||
LoggerInterface.loggerNetworking.ERROR("Max client connection attempts!", new Exception());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.main.Globals;
|
||||
import electrosphere.net.parser.net.message.AuthMessage;
|
||||
import electrosphere.net.parser.net.message.CharacterMessage;
|
||||
import electrosphere.net.parser.net.message.LoreMessage;
|
||||
import electrosphere.net.parser.net.message.TerrainMessage;
|
||||
|
||||
public class AuthProtocol {
|
||||
@ -17,8 +18,10 @@ public class AuthProtocol {
|
||||
break;
|
||||
case AUTHSUCCESS:
|
||||
//trigger request to spawn character
|
||||
Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
|
||||
Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage());
|
||||
// Globals.clientConnection.queueOutgoingMessage(TerrainMessage.constructRequestMetadataMessage());
|
||||
// Globals.clientConnection.queueOutgoingMessage(CharacterMessage.constructRequestSpawnCharacterMessage());
|
||||
//request playable races
|
||||
Globals.clientConnection.queueOutgoingMessage(LoreMessage.constructRequestRacesMessage());
|
||||
break;
|
||||
case AUTHFAILURE:
|
||||
//TODO: handle better
|
||||
|
||||
@ -11,6 +11,7 @@ import electrosphere.main.Globals;
|
||||
import electrosphere.main.Main;
|
||||
import electrosphere.net.parser.net.message.AuthMessage;
|
||||
import electrosphere.net.parser.net.message.EntityMessage;
|
||||
import electrosphere.net.parser.net.message.LoreMessage;
|
||||
import electrosphere.net.parser.net.message.NetworkMessage;
|
||||
import electrosphere.net.parser.net.message.PlayerMessage;
|
||||
import electrosphere.net.parser.net.message.ServerMessage;
|
||||
@ -41,6 +42,9 @@ public class ClientProtocol {
|
||||
case SERVER_MESSAGE:
|
||||
ServerProtocol.handleServerMessage((ServerMessage)message);
|
||||
break;
|
||||
case LORE_MESSAGE:
|
||||
LoreProtocol.handleLoreMessage((LoreMessage)message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
package electrosphere.net.client.protocol;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import electrosphere.main.Globals;
|
||||
import electrosphere.net.parser.net.message.LoreMessage;
|
||||
|
||||
public class LoreProtocol {
|
||||
|
||||
protected static void handleLoreMessage(LoreMessage message){
|
||||
switch(message.getMessageSubtype()){
|
||||
case RESPONSEDATA:
|
||||
break;
|
||||
case RESPONSERACES:
|
||||
//we get back the race list as a json array, deserialize, and push into type loader
|
||||
List<String> playableRaces = new Gson().fromJson(message.getdata(), List.class);
|
||||
Globals.gameConfigCurrent.getCreatureTypeLoader().loadPlayableRaces(playableRaces);
|
||||
break;
|
||||
case RESPONSERACEDATA:
|
||||
break;
|
||||
|
||||
case REQUESTDATA:
|
||||
case REQUESTRACEDATA:
|
||||
case REQUESTRACES:
|
||||
//silently ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
19
src/main/java/electrosphere/renderer/ui/ValueElement.java
Normal file
19
src/main/java/electrosphere/renderer/ui/ValueElement.java
Normal file
@ -0,0 +1,19 @@
|
||||
package electrosphere.renderer.ui;
|
||||
|
||||
import electrosphere.renderer.ui.events.ValueChangeEvent;
|
||||
|
||||
/**
|
||||
* Describes an element that contains a changeable value which will be used by the program somewhere
|
||||
* IE a carousel, text input, radio dial, etc
|
||||
*/
|
||||
public interface ValueElement extends Element {
|
||||
|
||||
public void setOnValueChangeCallback(ValueChangeEventCallback callback);
|
||||
|
||||
public interface ValueChangeEventCallback {
|
||||
|
||||
public void execute(ValueChangeEvent event);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,6 +11,7 @@ import electrosphere.renderer.ui.DrawableElement;
|
||||
import electrosphere.renderer.ui.FocusableElement;
|
||||
import electrosphere.renderer.ui.KeyEventElement;
|
||||
import electrosphere.renderer.ui.MenuEventElement;
|
||||
import electrosphere.renderer.ui.ValueElement;
|
||||
import electrosphere.renderer.ui.events.ClickEvent;
|
||||
import electrosphere.renderer.ui.events.DragEvent;
|
||||
import electrosphere.renderer.ui.events.Event;
|
||||
@ -18,9 +19,10 @@ import electrosphere.renderer.ui.events.FocusEvent;
|
||||
import electrosphere.renderer.ui.events.KeyboardEvent;
|
||||
import electrosphere.renderer.ui.events.MenuEvent;
|
||||
import electrosphere.renderer.ui.events.MouseEvent;
|
||||
import electrosphere.renderer.ui.events.ValueChangeEvent;
|
||||
import electrosphere.renderer.ui.events.DragEvent.DragEventType;
|
||||
|
||||
public class Slider implements ClickableElement, DraggableElement, FocusableElement, DrawableElement, MenuEventElement {
|
||||
public class Slider implements ClickableElement, DraggableElement, FocusableElement, DrawableElement, MenuEventElement, ValueElement {
|
||||
|
||||
public int width = 1;
|
||||
public int height = 1;
|
||||
@ -41,7 +43,7 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
|
||||
DragEventCallback onDragRelease;
|
||||
ClickEventCallback onClick;
|
||||
MenuEventCallback onMenuEvent;
|
||||
OnSliderChangeCallback onChangeValue;
|
||||
ValueChangeEventCallback onValueChange;
|
||||
|
||||
float min = 0.0f;
|
||||
float max = 1.0f;
|
||||
@ -238,8 +240,9 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
|
||||
onMenuEvent = callback;
|
||||
}
|
||||
|
||||
public void setOnValueChange(OnSliderChangeCallback callback){
|
||||
this.onChangeValue = callback;
|
||||
@Override
|
||||
public void setOnValueChangeCallback(ValueChangeEventCallback callback) {
|
||||
onValueChange = callback;
|
||||
}
|
||||
|
||||
|
||||
@ -272,15 +275,15 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
|
||||
switch(menuEvent.getType()){
|
||||
case INCREMENT:
|
||||
value = Math.min(value + ((max - min) * 0.01f),max);
|
||||
if(onChangeValue != null){
|
||||
onChangeValue.onChange(value);
|
||||
if(onValueChange != null){
|
||||
onValueChange.execute(new ValueChangeEvent(value));
|
||||
}
|
||||
propagate = false;
|
||||
break;
|
||||
case DECREMENT:
|
||||
value = Math.max(value - ((max - min) * 0.01f),min);
|
||||
if(onChangeValue != null){
|
||||
onChangeValue.onChange(value);
|
||||
if(onValueChange != null){
|
||||
onValueChange.execute(new ValueChangeEvent(value));
|
||||
}
|
||||
propagate = false;
|
||||
break;
|
||||
@ -320,8 +323,8 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
|
||||
int percentage = clickEvent.getCurrentX() - positionX;
|
||||
int max = width;
|
||||
value = Math.max(Math.min((float)percentage/max,1.0f),0.0f);
|
||||
if(onChangeValue != null){
|
||||
onChangeValue.onChange(value);
|
||||
if(onValueChange != null){
|
||||
onValueChange.execute(new ValueChangeEvent(value));
|
||||
}
|
||||
propagate = false;
|
||||
}
|
||||
@ -330,11 +333,4 @@ public class Slider implements ClickableElement, DraggableElement, FocusableElem
|
||||
return propagate;
|
||||
}
|
||||
|
||||
|
||||
public interface OnSliderChangeCallback {
|
||||
|
||||
public void onChange(float value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,326 @@
|
||||
package electrosphere.renderer.ui.elements;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import electrosphere.renderer.ui.DrawableElement;
|
||||
import electrosphere.renderer.ui.Element;
|
||||
import electrosphere.renderer.ui.FocusableElement;
|
||||
import electrosphere.renderer.ui.MenuEventElement;
|
||||
import electrosphere.renderer.ui.ValueElement;
|
||||
import electrosphere.renderer.ui.events.Event;
|
||||
import electrosphere.renderer.ui.events.FocusEvent;
|
||||
import electrosphere.renderer.ui.events.MenuEvent;
|
||||
import electrosphere.renderer.ui.events.ValueChangeEvent;
|
||||
import electrosphere.renderer.ui.events.MenuEvent.MenuEventType;
|
||||
import electrosphere.renderer.ui.font.FontUtils;
|
||||
import electrosphere.renderer.ui.font.bitmapchar.BitmapCharacter;
|
||||
|
||||
public class StringCarousel implements DrawableElement, MenuEventElement, FocusableElement, ValueElement {
|
||||
|
||||
public int width = 1;
|
||||
public int height = 1;
|
||||
|
||||
public int positionX = 0;
|
||||
public int positionY = 0;
|
||||
|
||||
public int parentWidth = 1;
|
||||
public int parentHeight = 1;
|
||||
|
||||
public boolean visible = false;
|
||||
|
||||
MenuEventCallback onMenuEventCallback;
|
||||
ValueChangeEventCallback onValueChange;
|
||||
|
||||
boolean focused = false;
|
||||
FocusEventCallback onFocusCallback;
|
||||
FocusEventCallback onLoseFocusCallback;
|
||||
|
||||
List<String> options = new LinkedList<String>();
|
||||
int currentOption = -1;
|
||||
String textCurrent = "";
|
||||
int textPixelWidth = 0;
|
||||
|
||||
float fontSize = 1.0f;
|
||||
|
||||
List<BitmapCharacter> childrenElements = new LinkedList<BitmapCharacter>();
|
||||
|
||||
public StringCarousel(int x, int y, float fontSize){
|
||||
this.positionX = x;
|
||||
this.positionY = y;
|
||||
this.width = 0;
|
||||
this.height = (int)(FontUtils.getFontHeight() * fontSize);
|
||||
this.fontSize = fontSize;
|
||||
}
|
||||
|
||||
public void addOption(String option){
|
||||
options.add(option);
|
||||
if(currentOption == -1){
|
||||
currentOption = 0;
|
||||
setText(option);
|
||||
if(onValueChange != null){
|
||||
onValueChange.execute(new ValueChangeEvent(option));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getOptions(){
|
||||
return options;
|
||||
}
|
||||
|
||||
public void removeOption(String option){
|
||||
options.remove(option);
|
||||
if(currentOption > options.size() - 1){
|
||||
currentOption = options.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void generateLetters(){
|
||||
childrenElements.clear();
|
||||
int rollingOffset = 0;
|
||||
for(int i = 0; i < textCurrent.length(); i++){
|
||||
char toDraw = textCurrent.charAt(i);
|
||||
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(toDraw);
|
||||
BitmapCharacter newLetter = new BitmapCharacter((int)(rollingOffset * fontSize) + positionX, positionY, (int)(bitMapDimension.x * fontSize), this.height, toDraw);
|
||||
rollingOffset += (int)bitMapDimension.x;
|
||||
childrenElements.add(newLetter);
|
||||
}
|
||||
}
|
||||
|
||||
public void setText(String text){
|
||||
this.textCurrent = text;
|
||||
textPixelWidth = 0;
|
||||
for(int i = 0; i < text.length(); i++){
|
||||
Vector3f bitMapDimension = FontUtils.getDimensionOfCharacterDiscrete(text.charAt(i));
|
||||
textPixelWidth = textPixelWidth + (int)bitMapDimension.x;
|
||||
}
|
||||
generateLetters();
|
||||
if(focused){
|
||||
setColor(new Vector3f(1,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
public void setColor(Vector3f color){
|
||||
for(BitmapCharacter character : childrenElements){
|
||||
character.setColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
public String getText(){
|
||||
return textCurrent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int parentFramebufferPointer, int parentWidth, int parentHeight) {
|
||||
for(DrawableElement child : childrenElements){
|
||||
child.draw(parentFramebufferPointer, parentWidth, parentHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
int minX = -1;
|
||||
int maxX = -1;
|
||||
for(BitmapCharacter child : childrenElements){
|
||||
if(minX == -1){
|
||||
minX = child.getPositionX();
|
||||
} else if(child.getPositionX() < minX){
|
||||
minX = child.getPositionX();
|
||||
}
|
||||
if(maxX == -1){
|
||||
maxX = child.getPositionX() + child.getWidth();
|
||||
} else if(child.getPositionX() + child.getWidth() > maxX){
|
||||
maxX = child.getPositionX() + child.getWidth();
|
||||
}
|
||||
}
|
||||
if(minX == -1){
|
||||
minX = 0;
|
||||
}
|
||||
if(maxX == -1){
|
||||
maxX = 0;
|
||||
}
|
||||
return maxX - minX;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
int minY = -1;
|
||||
int maxY = -1;
|
||||
for(BitmapCharacter child : childrenElements){
|
||||
if(minY == -1){
|
||||
minY = child.getPositionY();
|
||||
} else if(child.getPositionY() < minY){
|
||||
minY = child.getPositionY();
|
||||
}
|
||||
if(maxY == -1){
|
||||
maxY = child.getPositionY() + child.getHeight();
|
||||
} else if(child.getPositionY() + child.getHeight() > maxY){
|
||||
maxY = child.getPositionY() + child.getHeight();
|
||||
}
|
||||
}
|
||||
if(minY == -1){
|
||||
minY = 0;
|
||||
}
|
||||
if(maxY == -1){
|
||||
maxY = 0;
|
||||
}
|
||||
return maxY - minY;
|
||||
}
|
||||
|
||||
public int getPositionX() {
|
||||
int minX = -1;
|
||||
for(BitmapCharacter child : childrenElements){
|
||||
if(minX == -1){
|
||||
minX = child.getPositionX();
|
||||
} else if(child.getPositionX() < minX){
|
||||
minX = child.getPositionX();
|
||||
}
|
||||
}
|
||||
if(minX == -1){
|
||||
minX = 0;
|
||||
}
|
||||
return minX;
|
||||
}
|
||||
|
||||
public int getPositionY() {
|
||||
int minY = -1;
|
||||
for(BitmapCharacter child : childrenElements){
|
||||
if(minY == -1){
|
||||
minY = child.getPositionY();
|
||||
} else if(child.getPositionY() < minY){
|
||||
minY = child.getPositionY();
|
||||
}
|
||||
}
|
||||
if(minY == -1){
|
||||
minY = 0;
|
||||
}
|
||||
return minY;
|
||||
}
|
||||
|
||||
public boolean getVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public void setPositionX(int posX) {
|
||||
int deltaX = posX - this.positionX;
|
||||
this.positionX = posX;
|
||||
for(Element child : childrenElements){
|
||||
child.setPositionX(child.getPositionX() + deltaX);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPositionY(int posY) {
|
||||
int deltaY = posY - this.positionY;
|
||||
this.positionY = posY;
|
||||
for(Element child : childrenElements){
|
||||
child.setPositionY(child.getPositionY() + deltaY);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVisible(boolean draw) {
|
||||
this.visible = draw;
|
||||
}
|
||||
|
||||
public void setParentWidth(int width){
|
||||
parentWidth = width;
|
||||
}
|
||||
|
||||
public void setParentHeight(int height){
|
||||
this.parentHeight = height;
|
||||
}
|
||||
|
||||
public boolean handleEvent(Event event){
|
||||
boolean propagate = true;
|
||||
if(event instanceof MenuEvent){
|
||||
MenuEvent menuEvent = (MenuEvent)event;
|
||||
if(onMenuEventCallback != null){
|
||||
propagate = onMenuEventCallback.execute(menuEvent);
|
||||
} else {
|
||||
//default behavior
|
||||
if(menuEvent.getType() == MenuEventType.INCREMENT){
|
||||
propagate = false;
|
||||
if(options.size() > 0){
|
||||
currentOption++;
|
||||
if(currentOption > options.size() - 1){
|
||||
currentOption = 0;
|
||||
}
|
||||
String newOption = options.get(currentOption);
|
||||
setText(newOption);
|
||||
if(onValueChange != null){
|
||||
onValueChange.execute(new ValueChangeEvent(newOption));
|
||||
}
|
||||
}
|
||||
} else if(menuEvent.getType() == MenuEventType.DECREMENT){
|
||||
propagate = false;
|
||||
if(options.size() > 0){
|
||||
currentOption--;
|
||||
if(currentOption < 0){
|
||||
currentOption = options.size() - 1;
|
||||
}
|
||||
String newOption = options.get(currentOption);
|
||||
setText(newOption);
|
||||
if(onValueChange != null){
|
||||
onValueChange.execute(new ValueChangeEvent(newOption));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(event instanceof FocusEvent){
|
||||
FocusEvent focusEvent = (FocusEvent) event;
|
||||
if(focusEvent.isFocused()){
|
||||
this.focused = true;
|
||||
if(onFocusCallback != null){
|
||||
propagate = onFocusCallback.execute(focusEvent);
|
||||
} else {
|
||||
//default behavior
|
||||
propagate = false;
|
||||
setColor(new Vector3f(1,0,0));
|
||||
}
|
||||
} else {
|
||||
this.focused = false;
|
||||
if(onLoseFocusCallback != null){
|
||||
propagate = onLoseFocusCallback.execute(focusEvent);
|
||||
} else {
|
||||
//default behavior
|
||||
propagate = false;
|
||||
setColor(new Vector3f(1,1,1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return propagate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMenuEventCallback(MenuEventCallback callback) {
|
||||
onMenuEventCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnValueChangeCallback(ValueChangeEventCallback callback) {
|
||||
onValueChange = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFocused() {
|
||||
return focused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnFocus(FocusEventCallback callback) {
|
||||
onFocusCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnLoseFocus(FocusEventCallback callback) {
|
||||
onLoseFocusCallback = callback;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package electrosphere.renderer.ui.events;
|
||||
|
||||
public class ValueChangeEvent {
|
||||
|
||||
public static enum ValueType {
|
||||
STRING,
|
||||
FLOAT,
|
||||
}
|
||||
|
||||
String valueString;
|
||||
float valueFloat;
|
||||
ValueType valueType;
|
||||
|
||||
public ValueChangeEvent(String value){
|
||||
valueString = value;
|
||||
valueType = ValueType.STRING;
|
||||
}
|
||||
|
||||
public ValueChangeEvent(float value){
|
||||
valueFloat = value;
|
||||
valueType = ValueType.FLOAT;
|
||||
}
|
||||
|
||||
public ValueType getType(){
|
||||
return valueType;
|
||||
}
|
||||
|
||||
public float getAsFloat(){
|
||||
return valueFloat;
|
||||
}
|
||||
|
||||
public String getAsString(){
|
||||
return valueString;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user