1
\$\begingroup\$

I'm a self-taught programmer and I haven't really followed industry-standard coding classes. I'm currently coding my own game engine for android, though and I was wondering if my coding style could run me into big troubles. Here's my newly written custom button class:

package com.glu.engine.GUI;

import android.opengl.Matrix;
import android.util.Log;

import com.glu.engine.vectors.Matrix4f;
import com.glu.engine.vectors.Vector2f;
import com.glu.engine.vectors.Vector3f;

import java.util.ArrayList;

public class Button{
    //One thing to note is that I preffer setting my variables to public to get and set them. 
    //I ran some tests of my own and this practice is more performant than using methods.
    //just custom quads to actually render the button.
    public GUIBase stateDefault;
    public GUIBase statePressed;
    public GUIBase stateReleased;

    //I'm using arraylists to make it so that I can instance the button.
    public ArrayList<Boolean> isPressed = new ArrayList<>();
    public ArrayList<Boolean> hasBeenPressed = new ArrayList<>();
    public ArrayList<Boolean> isHovering = new ArrayList<>();
    public ArrayList<Boolean> hasClickedOff = new ArrayList<>();

    public ArrayList<Vector2f> position = new ArrayList<>();
    public ArrayList<Vector2f> size = new ArrayList<>();

    public ArrayList<String> name = new ArrayList<>();

    public int pressNumber;
    public int doOnClick;
    public int doOnClickRelease;
    public int doOnPass;
    public int doOnRelease;

    public static final int CANNOT_PRESS = 0;       // can't press the button
    public static final int PRESS_ONCE = 1;         // can only press the button once
    public static final int PRESS_MTONCE = 2;       // can press the button more than once
    public static final int STAY_ON_CLICK = 3;      // doesn't change on click
    public static final int CHANGE_ON_CLICK = 4;    // change on click
    public static final int STAY_ON_RELEASE = 3;    // stay on the pressed state at release
    public static final int RETURN_ON_RELEASE = 4;  // return to the default state at release
    public static final int CHANGE_ON_RELEASE = 5;  // change to the released state at release
    public static final int NTG_ON_PASS = 6;        // don't react when the finger goes over the button
    public static final int PREVIEW_ON_PASS = 7;    // change to pressed icon when the finger goes over the button
    public static final int CHANGE_ON_PASS = 8;     // change to released icon when the finger goes over the button
    public static final int CLICK_ON_PASS = 9;      // click the button when the finger goes over the button
    public static final int NTG_ON_RELEASE = 10;    // don't react if the finger releases when going over the button
    public static final int CLICK_ON_RELEASE = 11;  // click the button if the finger releases when going over it


    public ArrayList<Integer> state = new ArrayList<>();

    public static final int STATE_DEFAULT = 12;
    public static final int STATE_PRESSED = 13;
    public static final int STATE_RELEASED = 14;

    public Button(GUIBase stateDefault, GUIBase statePressed){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (null);

        position.add(new Vector2f(0,0));
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        pressNumber = PRESS_MTONCE;
        doOnClick = CHANGE_ON_CLICK;
        doOnClickRelease = RETURN_ON_RELEASE;
        doOnPass = NTG_ON_PASS;
        doOnRelease = NTG_ON_RELEASE;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, GUIBase stateReleased){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (stateReleased);

        position.add(new Vector2f(0,0));
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);
        this.stateReleased.position.set(0,this.position.get(0));
        this.stateReleased.scale.get(0).multiply(this.size.get(0));
        this.stateReleased.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        pressNumber = PRESS_MTONCE;
        doOnClick = CHANGE_ON_CLICK;
        doOnClickRelease = RETURN_ON_RELEASE;
        doOnPass = NTG_ON_PASS;
        doOnRelease = NTG_ON_RELEASE;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, Vector2f position){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (null);

        this.position.add(position);
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        pressNumber = PRESS_MTONCE;
        doOnClick = CHANGE_ON_CLICK;
        doOnClickRelease = RETURN_ON_RELEASE;
        doOnPass = NTG_ON_PASS;
        doOnRelease = NTG_ON_RELEASE;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, Vector2f position, Vector2f size){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (null);

        this.position.add(position);
        this.size.add(size);

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        pressNumber = PRESS_MTONCE;
        doOnClick = CHANGE_ON_CLICK;
        doOnClickRelease = RETURN_ON_RELEASE;
        doOnPass = NTG_ON_PASS;
        doOnRelease = NTG_ON_RELEASE;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, GUIBase stateReleased, Vector2f position){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (stateReleased);

        this.position.add(position);
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);
        this.stateReleased.position.set(0,this.position.get(0));
        this.stateReleased.scale.get(0).multiply(this.size.get(0));
        this.stateReleased.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        pressNumber = PRESS_MTONCE;
        doOnClick = CHANGE_ON_CLICK;
        doOnClickRelease = RETURN_ON_RELEASE;
        doOnPass = NTG_ON_PASS;
        doOnRelease = NTG_ON_RELEASE;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, GUIBase stateReleased, Vector2f position, Vector2f size){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (stateReleased);

        this.position.add(position);
        this.size.add(size);

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);
        this.stateReleased.position.set(0,this.position.get(0));
        this.stateReleased.scale.get(0).multiply(this.size.get(0));
        this.stateReleased.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        pressNumber = PRESS_MTONCE;
        doOnClick = CHANGE_ON_CLICK;
        doOnClickRelease = RETURN_ON_RELEASE;
        doOnPass = NTG_ON_PASS;
        doOnRelease = NTG_ON_RELEASE;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, int pressNumber,int doOnClick, int doOnClickRelease, int doOnPass, int doOnRelease){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (null);

        this.position.add(new Vector2f(0,0));
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        this.pressNumber = pressNumber;
        this.doOnClick = doOnClick;
        this.doOnClickRelease = doOnClickRelease;
        this.doOnPass = doOnPass;
        this.doOnRelease = doOnRelease;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, GUIBase stateReleased,  int pressNumber,int doOnClick, int doOnClickRelease, int doOnPass, int doOnRelease){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (stateReleased);

        position.add(new Vector2f(0,0));
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);
        this.stateReleased.position.set(0,this.position.get(0));
        this.stateReleased.scale.get(0).multiply(this.size.get(0));
        this.stateReleased.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        this.pressNumber = pressNumber;
        this.doOnClick = doOnClick;
        this.doOnClickRelease = doOnClickRelease;
        this.doOnPass = doOnPass;
        this.doOnRelease = doOnRelease;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, Vector2f position,  int pressNumber,int doOnClick, int doOnClickRelease, int doOnPass, int doOnRelease){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (null);

        this.position.add(position);
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        this.pressNumber = pressNumber;
        this.doOnClick = doOnClick;
        this.doOnClickRelease = doOnClickRelease;
        this.doOnPass = doOnPass;
        this.doOnRelease = doOnRelease;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, Vector2f position, Vector2f size,  int pressNumber,int doOnClick, int doOnClickRelease, int doOnPass, int doOnRelease){
        this.stateDefault = stateDefault;
        this.statePressed = statePressed;
        this.stateReleased = null;

        this.position.add(position);
        this.size.add(size);

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        this.pressNumber = pressNumber;
        this.doOnClick = doOnClick;
        this.doOnClickRelease = doOnClickRelease;
        this.doOnPass = doOnPass;
        this.doOnRelease = doOnRelease;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, GUIBase stateReleased, Vector2f position,  int pressNumber,int doOnClick, int doOnClickRelease, int doOnPass, int doOnRelease){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (stateReleased);

        this.position.add(position);
        this.size.add(new Vector2f(1,1));

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);
        this.stateReleased.position.set(0,this.position.get(0));
        this.stateReleased.scale.get(0).multiply(this.size.get(0));
        this.stateReleased.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        this.pressNumber = pressNumber;
        this.doOnClick = doOnClick;
        this.doOnClickRelease = doOnClickRelease;
        this.doOnPass = doOnPass;
        this.doOnRelease = doOnRelease;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public Button(GUIBase stateDefault, GUIBase statePressed, GUIBase stateReleased, Vector2f position, Vector2f size,  int pressNumber,int doOnClick, int doOnClickRelease, int doOnPass, int doOnRelease){
        this.stateDefault = (stateDefault);
        this.statePressed = (statePressed);
        this.stateReleased = (stateReleased);

        this.position.add(position);
        this.size.add(size);

        this.stateDefault.position.set(0,this.position.get(0));
        this.stateDefault.scale.get(0).multiply(this.size.get(0));
        this.stateDefault.show.set(0,true);
        this.statePressed.position.set(0,this.position.get(0));
        this.statePressed.scale.get(0).multiply(this.size.get(0));
        this.statePressed.show.set(0,false);
        this.stateReleased.position.set(0,this.position.get(0));
        this.stateReleased.scale.get(0).multiply(this.size.get(0));
        this.stateReleased.show.set(0,false);

        isPressed.add(false);
        hasBeenPressed.add(false);
        isHovering.add(false);
        hasClickedOff.add(false);

        this.pressNumber = pressNumber;
        this.doOnClick = doOnClick;
        this.doOnClickRelease = doOnClickRelease;
        this.doOnPass = doOnPass;
        this.doOnRelease = doOnRelease;
        state.add(STATE_DEFAULT);

        name.add("button"+(name.size()));
    }

    public void setBehavior( int pressNumber,int doOnClick, int doOnClickRelease, int doOnPass, int doOnRelease){
        this.pressNumber = pressNumber;
        this.doOnClick = doOnClick;
        this.doOnClickRelease = doOnClickRelease;
        this.doOnPass = doOnPass;
        this.doOnRelease = doOnRelease;
    }

    public void setName(int index,String name){this.name.set(index,name);}

    public void checkClickAt(Vector2f click,int index){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        if(((pos.x>position.get(index).x-size.get(index).x)&&(pos.x<position.get(index).x+size.get(index).x))&&
                ((pos.y>position.get(index).y-size.get(index).y)&&(pos.y<position.get(index).y+size.get(index).y))){
            if(!hasClickedOff.get(index)) {
                click(index);
            }
        }else {

        }
    }

    public void checkClickAt(Vector2f click){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        for (int i = 0; i < name.size(); i++) {
            if (((pos.x > position.get(i).x - size.get(i).x) && (pos.x < position.get(i).x + size.get(i).x)) &&
                    ((pos.y > position.get(i).y - size.get(i).y) && (pos.y < position.get(i).y + size.get(i).y))) {
                if(!hasClickedOff.get(i)){
                    click(i);
                }
            }else {
                boolean tmp = false;
                if(isPressed.get(i)) {
                    tmp = true;
                    release(i);
                }
                if(tmp){hasClickedOff.set(i,true);}
            }
        }
    }

    public void checkPassAt(Vector2f click,int index){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        if(((pos.x>position.get(index).x-size.get(index).x)&&(pos.x<position.get(index).x+size.get(index).x))&&
                ((pos.y>position.get(index).y-size.get(index).y)&&(pos.y<position.get(index).y+size.get(index).y))){
            if(!hasClickedOff.get(index)) {
                passOn(index);
            }
        }else{if(isHovering.get(index)){
            passOff(index);
        }}
    }

    public void checkPassAt(Vector2f click){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        for (int i = 0; i < name.size(); i++) {
            if (((pos.x > position.get(i).x - size.get(i).x) && (pos.x < position.get(i).x + size.get(i).x)) &&
                    ((pos.y > position.get(i).y - size.get(i).y) && (pos.y < position.get(i).y + size.get(i).y))) {
                if(!hasClickedOff.get(i)) {
                    passOn(i);
                }
            }else{if(isHovering.get(i)){passOff(i);}}
        }
    }

    public void checkReleaseIn(Vector2f click,int index){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        if(((pos.x>position.get(index).x-size.get(index).x)&&(pos.x<position.get(index).x+size.get(index).x))&&
                ((pos.y>position.get(index).y-size.get(index).y)&&(pos.y<position.get(index).y+size.get(index).y))) {
            release(index);
        }
    }

    public void checkReleaseIn(Vector2f click){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        for (int i = 0; i < name.size(); i++) {
            if (((pos.x > position.get(i).x - size.get(i).x) && (pos.x < position.get(i).x + size.get(i).x)) &&
                    ((pos.y > position.get(i).y - size.get(i).y) && (pos.y < position.get(i).y + size.get(i).y))) {
                release(i);
            }
        }
    }

    public void checkReleaseOut(Vector2f click,int index){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        if(((pos.x<position.get(index).x-size.get(index).x)||(pos.x>position.get(index).x+size.get(index).x))||
                ((pos.y<position.get(index).y-size.get(index).y)||(pos.y>position.get(index).y+size.get(index).y))) {
            boolean tmp = false;
            if(isPressed.get(index)){
                tmp = true;
                release(index);
            }
            if(tmp){hasClickedOff.set(index,true);}
        }
    }

    public void checkReleaseOut(Vector2f click){
        Vector2f pos = Vector2f.scale(Vector2f.sub(click,Vector2f.scale(stateDefault.screenDimensions,0.5f)),2f);
        for (int i = 0; i < name.size(); i++) {
            if (((pos.x < position.get(i).x - size.get(i).x) || (pos.x > position.get(i).x + size.get(i).x)) ||
                    ((pos.y > position.get(i).y - size.get(i).y) || (pos.y < position.get(i).y + size.get(i).y))) {
                boolean tmp = false;
                if(isPressed.get(i)){
                    tmp = true;
                    release(i);
                }
                if(tmp){hasClickedOff.set(i,true);}
            }
        }
    }

    public void click(int index){
        switch (pressNumber){
            case CANNOT_PRESS:
                Log.w("clickButton","You can't press this button!");
                break;
            case PRESS_ONCE:
                switch (doOnClick){
                    case STAY_ON_CLICK:
                        if(!hasBeenPressed.get(index)){
                            isPressed.set(index,true);
                            hasBeenPressed.set(index,true);
                        }
                        break;
                    case CHANGE_ON_CLICK:
                        if(!hasBeenPressed.get(index)){
                            isPressed.set(index,true);
                            hasBeenPressed.set(index,true);
                            state.set(index,STATE_PRESSED);
                        }
                        break;
                    default:
                        Log.e("clickButton","doOnClick can't be : " + doOnClick + ", it must either be STAY_ON_CLICK or CHANGE_ON_CLICK.");
                        break;
                }
                break;
            case PRESS_MTONCE:
                switch (doOnClick){
                    case STAY_ON_CLICK:
                        isPressed.set(index,true);
                        hasBeenPressed.set(index,true);
                        break;
                    case CHANGE_ON_CLICK:
                        isPressed.set(index,true);
                        hasBeenPressed.set(index,true);
                        state.set(index,STATE_PRESSED);
                        break;
                    default:
                        Log.e("clickButton","invalid value for doOnClick : "+doOnClick);
                        break;
                }
                break;
            default:
                Log.e("clickButton","invalid value for pressNumber : "+pressNumber);
                break;
        }
        updateIcon(index);
    }

    public void release(int index){
        if(isPressed.get(index)){
            switch (doOnClickRelease){
                case STAY_ON_RELEASE:
                    isPressed.set(index,false);
                    hasBeenPressed.set(index,true);
                    state.set(index,STATE_PRESSED);
                    break;
                case CHANGE_ON_RELEASE:
                    isPressed.set(index,false);
                    hasBeenPressed.set(index,true);
                    state.set(index,STATE_RELEASED);
                    break;
                case RETURN_ON_RELEASE:
                    isPressed.set(index,false);
                    hasBeenPressed.set(index,true);
                    state.set(index,STATE_DEFAULT);
                    break;
                default:
                    Log.e("releaseButton","invalid value for doOnClickRelease : "+doOnClickRelease);
                    break;
            }
            updateIcon(index);
        }else {
            switch (doOnRelease){
                case NTG_ON_RELEASE:
                    state.set(index,STATE_DEFAULT);
                    break;
                case CLICK_ON_RELEASE:
                    click(index);
                    release(index);
                    break;
                default:
                    Log.e("releaseButton","invalid value for doOnRelease : "+doOnRelease);
                    break;
            }
        }
        isHovering.set(index,true);
        hasClickedOff.set(index,false);
    }

    public void passOn(int index){
        switch (doOnPass){
            case NTG_ON_PASS:
                isHovering.set(index,true);
                break;
            case PREVIEW_ON_PASS:
                state.set(index,STATE_PRESSED);
                isHovering.set(index,true);
                break;
            case CHANGE_ON_PASS:
                state.set(index,STATE_RELEASED);
                isHovering.set(index,true);
                break;
            case CLICK_ON_PASS:
                click(index);
                isHovering.set(index,true);
                break;
            default:
                Log.e("passOnButton","invalid value for doOnPass : "+doOnPass);
                break;
        }
        updateIcon(index);
    }

    public void passOff(int index){
        Log.w("passOff","passOff");
        if(doOnPass != CLICK_ON_PASS){
            Log.w("checkPassAt","!ClickOnPass");
            state.set(index,STATE_DEFAULT);
            isHovering.set(index,false);
        }
        updateIcon(index);
    }

    public void updateIcon(int index){
        //Log.w("updateButtonIcon","state : "+state.get(index));
        switch (state.get(index)){
            case STATE_DEFAULT:
                stateDefault.show.set(index,true);
                statePressed.show.set(index,false);
                if(stateReleased != null){stateReleased.show.set(index,false);}
                break;
            case STATE_PRESSED:
                stateDefault.show.set(index,false);
                statePressed.show.set(index,true);
                if(stateReleased != null){stateReleased.show.set(index,false);}
                break;
            case STATE_RELEASED:
                stateDefault.show.set(index,false);
                statePressed.show.set(index,false);
                if (stateReleased!= null){stateReleased.show.set(index,true);}else
                    {Log.e("updateButtonIcon",name.get(index)+" has no stateReleased icon!");}
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + state.get(index));
        }

        stateDefault.position.set(index,position.get(index));
        statePressed.position.set(index,position.get(index));
        if(stateReleased != null) {
            stateReleased.position.set(index, position.get(index));
        }
    }

    public Button copy(){
        Button button = new Button(stateDefault,statePressed,stateReleased,pressNumber,doOnClick,doOnClickRelease,doOnPass,doOnRelease);
        button.position = new ArrayList<>(position);
        button.size = new ArrayList<>(size);
        button.state = new ArrayList<>(state);
        button.isPressed = new ArrayList<>(isPressed);
        button.hasBeenPressed = new ArrayList<>(isPressed);
        button.name = new ArrayList<>(name);
        button.isHovering = new ArrayList<>(isHovering);
        return button;
    }

    public void addInstance(){
        isPressed.add(false);
        hasBeenPressed.add(false);
        position.add(new Vector2f(0,0));
        size.add(new Vector2f(1,1));
        state.add(STATE_DEFAULT);
        stateDefault.instance(0);
        stateDefault.position.set(stateDefault.position.size()-1,new Vector2f(0,0));
        statePressed.instance(0);
        statePressed.position.set(statePressed.position.size()-1,new Vector2f(0,0));
        stateReleased.instance(0);
        stateReleased.position.set(stateReleased.position.size()-1,new Vector2f(0,0));
        Log.w("addInstance","added instance");
    }

    public void addInstance(Vector2f position,Vector2f size){
        isPressed.add(false);
        hasBeenPressed.add(false);
        this.position.add(position);
        size.add(size);
        state.add(STATE_DEFAULT);
        stateDefault.addInstance(position,0,size);
        statePressed.addInstance(position,0,size);
        stateReleased.addInstance(position,0,size);
        Log.w("addInstance","added instance");
    }

    public void instance(int index){
        isPressed.add(isPressed.get(index));
        hasBeenPressed.add(hasBeenPressed.get(index));
        this.position.add(position.get(index));
        size.add(size.get(index));
        state.add(state.get(index));
        stateDefault.instance(index);
        statePressed.instance(index);
        stateReleased.instance(index);
        Log.w("Instance","instanced"+index);
    }

    public void removeInstance(int index){
        isPressed.remove(index);
        hasBeenPressed.remove(index);
        this.position.remove(index);
        size.remove(index);
        state.remove(index);
        stateDefault.removeInstance(index);
        statePressed.removeInstance(index);
        stateReleased.removeInstance(index);
        Log.w("removedInstance","instance removed "+index);
    }

    public void reset(int index){
        isPressed.set(index,false);
        hasBeenPressed.set(index,false);
        state.set(index,STATE_DEFAULT);
    }

    public void setPosition(int index, Vector2f pos){
        position.set(index,pos);
        stateDefault.position.set(index,pos);
        statePressed.position.set(index,pos);
        stateReleased.position.set(index,pos);
    }

    public void setSize(int index, Vector2f s){
        size.set(index,s);
        stateDefault.scale.set(index,s);
        statePressed.scale.set(index,s);
        stateReleased.scale.set(index,s);
    }

}

If anything is unclear, please tell me in the comments, I will update as soon as possible.

I would like to know what improvements I should do and if my code has some overly complex stuff. I'm especially looking at the amount of initialisers and if there's a better way to do this and som tips as to what I should include in the initialisation.

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Making variables public is not terrible in a toy project. In anything more significant than that, it makes maintenance very hard. For instance, right now anybody that can see a Button can change its state or add or remove from any of the various lists, and the button has no way of knowing that its internal state has been modified in unsupported and unintended ways.

Code should not make micro-optimizations for performance reasons until there is a clearly tested bottleneck in the code. There is a long history of micro-optimizations that have no noticeable impact on users and make code harder to maintain. First use repeatable performance testing to find actual performance bottlenecks, then fix them.

Variables that are not intended to be reassigned should be marked as final.

Classes that are not carefully and explicitly designed for extension should be marked final.

Prefer the most generally applicable type when making assignments. None of the code cares about what List implementation is used, so values should be assigned to List, not ArrayList.

//I'm using arraylists to make it so that I can instance the button. I'm not an Android developer, so maybe that's the problem, but I have no idea what this means.

Both sets of constants should probably be enums. The inline comments should be javadoc. Using multiple enums for the different types of settings lets the compile ensure clients are not setting invalid values, such as accidentally passing in CHANGE_ON_CLICK for a button press. Type safety is a Good Thing. The variables then no longer need to document their type in the name.

Try to avoid abbreviations. For instance, PRESS_MTONCE is not meaningful to most readers. I needed to look at the comment to see it meant PRESS_MORE_THAN_ONCE. NTG_ON_PASS is maybe "nothing"? Very hard to tell.

There are 12 constructors. That's about 9 too many. It's unmaintainable. Either use a Builder or make some of the variables properties that can/must be set after construction.

The copy method should be either a copy constructor (public Button(Button buttonToCopy)) or can be facilitated as part of the builder.

It is neither necessary nor desirable to have parenthesis around simple assignments such as this.stateDefault = (stateDefault).

In idiomatic java, there is whitespace between ) and {

In idiomatic java, there is whitespace after a comma.

In idiomatic java, there is whitespace between a control flow keyword (if, for, etc) and an open paren.

In idiomatic java, there is whitespace around operators (==, &&, =`, etc).

In idiomatic java, there is whitespace between } and else.

Code is much harder to read when it's squished on one line. This:

public void setName(int index,String name){this.name.set(index,name);}

is much harder to read than this:

public void setName(int index,String name) {
    this.name.set(index,name);
}

An empty else block is confusing and should be avoided.

Avoid nesting if checks when they can be combined.

Code such as in checkClickAt would benefit from extracting variables. For instance, position.get(index); -> indexPosition.

Common code can be extracted for the two checkClickAt methods - the if block which checks if the click was inside a space. That code will be useful in later methods as well. It might look like:

private boolean isClickInside(Vector2f click, int index) {
    Vector2f clickPosition = 
        Vector2f.scale(Vector2f.sub(click, Vector2f.scale(stateDefault.screenDimensions, 0.5f)), 2f);

    Vector2f indexPosition = position.get(index);
    Vector2f indexSize = size.get(index);

    return (((clickPosition.x > indexPosition.x - indexSize.x) && (clickPosition.x < indexPosition.x + indexSize.x))
            && ((clickPosition.y > indexPosition.y - indexPosition.y) && (clickPosition.y < indexPosition.y + indexSize.y)));
}

wasPressed would be a better name than tmp.

release checks isPressed, so there's no need to do it in checkClickAt also. Alternately, the two if checks can be combined.

else if is preferable to else { if .

The second checkPassAt can be modified to call the first, since it loops over and does the same thing.

checkReleaseOut can be simplified by having the second instance call the first, since it loops over and does the same thing.

There's more work to be done, but I'm out of juice. If you were to make all these changes, your class might look more like:

public final class Button {

    private final GUIBase stateDefault;
    private final GUIBase statePressed;
    private final GUIBase stateReleased;

    private final List<Boolean> isPressed = new ArrayList<>();
    private final List<Boolean> hasBeenPressed = new ArrayList<>();
    private final List<Boolean> isHovering = new ArrayList<>();
    private final List<Boolean> hasClickedOff = new ArrayList<>();

    private final List<Vector2f> position = new ArrayList<>();
    private final List<Vector2f> size = new ArrayList<>();

    private final List<String> name = new ArrayList<>();

    private PressBehavior pressBehavior;
    private ClickBehavior doOnClick;
    private ClickReleaseBehavior doOnClickRelease;
    private PassBehavior doOnPass;
    private ReleaseBehavior doOnRelease;

    private final List<Integer> state = new ArrayList<>();

    public static final int STATE_DEFAULT = 12;
    public static final int STATE_PRESSED = 13;
    public static final int STATE_RELEASED = 14;

    public static Button.Builder builder(GUIBase stateDefault, GUIBase statePressed) {
    return new Button.Builder(stateDefault, statePressed);
    }
    
    
    public Button(Button buttonToCopy) {
    this.stateDefault = buttonToCopy.stateDefault;
    this.statePressed = buttonToCopy.statePressed;
    this.stateReleased = buttonToCopy.stateReleased;
    
    this.position.clear();
    this.size.clear();
    this.state.clear();
    this.isPressed.clear();
    this.hasBeenPressed.clear();
    this.name.clear();
    this.isHovering.clear();
    
    this.position.addAll(buttonToCopy.position);
    this.size.addAll(buttonToCopy.size);
    this.state.addAll(buttonToCopy.state);
    this.isPressed.addAll(buttonToCopy.isPressed);
    this.hasBeenPressed.addAll(buttonToCopy.hasBeenPressed);
    this.name.addAll(buttonToCopy.name);
    this.isHovering.addAll(buttonToCopy.isHovering);
    
    this.pressBehavior = buttonToCopy.pressBehavior;
    this.doOnClick = buttonToCopy.doOnClick;
    this.doOnClickRelease = buttonToCopy.doOnClickRelease;
    this.doOnPass = buttonToCopy.doOnPass;
    this.doOnRelease = buttonToCopy.doOnRelease;
    }
    
    private Button(
        GUIBase stateDefault, 
        GUIBase statePressed, 
        GUIBase stateReleased, 
        Vector2f position, 
        Vector2f size) {
    this.stateDefault = stateDefault;
    this.statePressed = statePressed;
    this.stateReleased = stateReleased;

    position.add(position);
    this.size.add(size);

    this.stateDefault.position.set(0, this.position.get(0));
    this.stateDefault.scale.get(0).multiply(this.size.get(0));
    this.stateDefault.show.set(0, true);
    
    this.statePressed.position.set(0, this.position.get(0));
    this.statePressed.scale.get(0).multiply(this.size.get(0));
    this.statePressed.show.set(0, false);

    if (this.stateReleased != null) {
        this.stateReleased.position.set(0, this.position.get(0));
        this.stateReleased.scale.get(0).multiply(this.size.get(0));
        this.stateReleased.show.set(0, false);
    }

    isPressed.add(false);
    hasBeenPressed.add(false);
    isHovering.add(false);
    hasClickedOff.add(false);
    state.add(STATE_DEFAULT);

    name.add("button" + (name.size()));
    }

    public void setBehavior(
        PressBehavior pressBehavior, 
        ClickBehavior clickBehavior,
        ClickReleaseBehavior clickReleaseBehavior, 
        PassBehavior passBehavior, 
        ReleaseBehavior releaseBehavior) {
    this.pressBehavior = pressBehavior;
    this.doOnClick = clickBehavior;
    this.doOnClickRelease = clickReleaseBehavior;
    this.doOnPass = passBehavior;
    this.doOnRelease = releaseBehavior;
    }

    public void setName(int index, String name) {
    this.name.set(index, name);
    }

    public void checkClickAt(Vector2f click, int index) {
    if (isClickInside(click, index) && !hasClickedOff.get(index)) {
        click(index);
    }
    }

    public void checkClickAt(Vector2f click) {
    for (int i = 0; i < name.size(); i++) {
        if (isClickInside(click, i) && !hasClickedOff.get(i)) {
        click(i);
        } else if (isPressed.get(i)) {
        release(i);
        hasClickedOff.set(i, true);
        }
    }
    }

    public void checkPassAt(Vector2f click, int index) {
    if (isClickInside(click, index) && !hasClickedOff.get(index)) {
        passOn(index);
    } else if (isHovering.get(index)) {
        passOff(index);
    }
    }

    public void checkPassAt(Vector2f click) {
    for (int i = 0; i < name.size(); i++) {
        checkPassAt(click, i);
    }
    }

    public void checkReleaseIn(Vector2f click, int index) {
    if (isClickInside(click, index)) {
        release(index);
    }
    }

    public void checkReleaseIn(Vector2f click) {
    for (int i = 0; i < name.size(); i++) {
        checkReleaseIn(click, i);
    }
    }

    public void checkReleaseOut(Vector2f click, int index) {
    if (isClickInside(click, index) && isPressed.get(index)) {
        release(index);
        hasClickedOff.set(index, true);
    }
    }

    public void checkReleaseOut(Vector2f click) {
    for (int i = 0; i < name.size(); i++) {
        checkReleaseOut(click, i);
    }
    }

    public void click(int index) {
    switch (pressBehavior) {
    case CANNOT_PRESS:
        Log.w("clickButton", "You can't press this button!");
        break;
    case PRESS_ONCE:
        switch (doOnClick) {
        case STAY:
        if (!hasBeenPressed.get(index)) {
            isPressed.set(index, true);
            hasBeenPressed.set(index, true);
        }
        break;
        case CHANGE:
        if (!hasBeenPressed.get(index)) {
            isPressed.set(index, true);
            hasBeenPressed.set(index, true);
            state.set(index, STATE_PRESSED);
        }
        break;
        default:
        Log.e("clickButton",
            "doOnClick can't be : " + doOnClick + ", it must either be STAY_ON_CLICK or CHANGE_ON_CLICK.");
        break;
        }
        break;
    case PRESS_MORE_THAN_ONCE:
        switch (doOnClick) {
        case STAY:
        isPressed.set(index, true);
        hasBeenPressed.set(index, true);
        break;
        case CHANGE:
        isPressed.set(index, true);
        hasBeenPressed.set(index, true);
        state.set(index, STATE_PRESSED);
        break;
        default:
        Log.e("clickButton", "invalid value for doOnClick : " + doOnClick);
        break;
        }
        break;
    default:
        Log.e("clickButton", "invalid value for pressBehavior : " + pressBehavior);
        break;
    }
    updateIcon(index);
    }

    public void release(int index) {
    if (isPressed.get(index)) {
        switch (doOnClickRelease) {
        case STAY:
        isPressed.set(index, false);
        hasBeenPressed.set(index, true);
        state.set(index, STATE_PRESSED);
        break;
        case CHANGE:
        isPressed.set(index, false);
        hasBeenPressed.set(index, true);
        state.set(index, STATE_RELEASED);
        break;
        case RETURN:
        isPressed.set(index, false);
        hasBeenPressed.set(index, true);
        state.set(index, STATE_DEFAULT);
        break;
        default:
        Log.e("releaseButton", "invalid value for doOnClickRelease : " + doOnClickRelease);
        break;
        }
        updateIcon(index);
    } else {
        switch (doOnRelease) {
        case NOTHING:
        state.set(index, STATE_DEFAULT);
        break;
        case CLICK:
        click(index);
        release(index);
        break;
        default:
        Log.e("releaseButton", "invalid value for doOnRelease : " + doOnRelease);
        break;
        }
    }
    isHovering.set(index, true);
    hasClickedOff.set(index, false);
    }

    public void passOn(int index) {
    switch (doOnPass) {
    case NOTHING:
        isHovering.set(index, true);
        break;
    case PREVIEW:
        state.set(index, STATE_PRESSED);
        isHovering.set(index, true);
        break;
    case CHANGE:
        state.set(index, STATE_RELEASED);
        isHovering.set(index, true);
        break;
    case CLICK:
        click(index);
        isHovering.set(index, true);
        break;
    default:
        Log.e("passOnButton", "invalid value for doOnPass : " + doOnPass);
        break;
    }
    updateIcon(index);
    }

    public void passOff(int index) {
    Log.w("passOff", "passOff");
    if (doOnPass != PassBehavior.CLICK) {
        Log.w("checkPassAt", "!ClickOnPass");
        state.set(index, STATE_DEFAULT);
        isHovering.set(index, false);
    }
    updateIcon(index);
    }

    public void updateIcon(int index) {
    // Log.w("updateButtonIcon","state : "+state.get(index));
    switch (state.get(index)) {
    case STATE_DEFAULT:
        stateDefault.show.set(index, true);
        statePressed.show.set(index, false);
        if (stateReleased != null) {
        stateReleased.show.set(index, false);
        }
        break;
    case STATE_PRESSED:
        stateDefault.show.set(index, false);
        statePressed.show.set(index, true);
        if (stateReleased != null) {
        stateReleased.show.set(index, false);
        }
        break;
    case STATE_RELEASED:
        stateDefault.show.set(index, false);
        statePressed.show.set(index, false);
        if (stateReleased != null) {
        stateReleased.show.set(index, true);
        } else {
        Log.e("updateButtonIcon", name.get(index) + " has no stateReleased icon!");
        }
        break;
    default:
        throw new IllegalStateException("Unexpected value: " + state.get(index));
    }

    stateDefault.position.set(index, position.get(index));
    statePressed.position.set(index, position.get(index));
    if (stateReleased != null) {
        stateReleased.position.set(index, position.get(index));
    }
    }

    public void addInstance() {
    isPressed.add(false);
    hasBeenPressed.add(false);
    position.add(new Vector2f(0, 0));
    size.add(new Vector2f(1, 1));
    state.add(STATE_DEFAULT);
    stateDefault.instance(0);
    stateDefault.position.set(stateDefault.position.size() - 1, new Vector2f(0, 0));
    statePressed.instance(0);
    statePressed.position.set(statePressed.position.size() - 1, new Vector2f(0, 0));
    stateReleased.instance(0);
    stateReleased.position.set(stateReleased.position.size() - 1, new Vector2f(0, 0));
    Log.w("addInstance", "added instance");
    }

    public void addInstance(Vector2f position, Vector2f size) {
    isPressed.add(false);
    hasBeenPressed.add(false);
    this.position.add(position);
    size.add(size);
    state.add(STATE_DEFAULT);
    stateDefault.addInstance(position, 0, size);
    statePressed.addInstance(position, 0, size);
    stateReleased.addInstance(position, 0, size);
    Log.w("addInstance", "added instance");
    }

    public void instance(int index) {
    isPressed.add(isPressed.get(index));
    hasBeenPressed.add(hasBeenPressed.get(index));
    this.position.add(position.get(index));
    size.add(size.get(index));
    state.add(state.get(index));
    stateDefault.instance(index);
    statePressed.instance(index);
    stateReleased.instance(index);
    Log.w("Instance", "instanced" + index);
    }

    public void removeInstance(int index) {
    isPressed.remove(index);
    hasBeenPressed.remove(index);
    this.position.remove(index);
    size.remove(index);
    state.remove(index);
    stateDefault.removeInstance(index);
    statePressed.removeInstance(index);
    stateReleased.removeInstance(index);
    Log.w("removedInstance", "instance removed " + index);
    }

    public void reset(int index) {
    isPressed.set(index, false);
    hasBeenPressed.set(index, false);
    state.set(index, STATE_DEFAULT);
    }

    public void setPosition(int index, Vector2f pos) {
    position.set(index, pos);
    stateDefault.position.set(index, pos);
    statePressed.position.set(index, pos);
    stateReleased.position.set(index, pos);
    }

    public void setSize(int index, Vector2f s) {
    size.set(index, s);
    stateDefault.scale.set(index, s);
    statePressed.scale.set(index, s);
    stateReleased.scale.set(index, s);
    }

    private boolean isClickInside(Vector2f click, int index) {
    Vector2f clickPosition = 
        Vector2f.scale(Vector2f.sub(click, Vector2f.scale(stateDefault.screenDimensions, 0.5f)), 2f);

    Vector2f indexPosition = position.get(index);
    Vector2f indexSize = size.get(index);

    return (((clickPosition.x > indexPosition.x - indexSize.x) && (clickPosition.x < indexPosition.x + indexSize.x))
        && ((clickPosition.y > indexPosition.y - indexPosition.y) && (clickPosition.y < indexPosition.y + indexSize.y)));
    }

    public static final class Builder {

    private final GUIBase stateDefault;
    private final GUIBase statePressed;
    private GUIBase stateReleased;
    private Vector2f position = new Vector2f(0, 0);
    private Vector2f size = new Vector2f(1, 1);
    private PressBehavior pressBehavior = PressBehavior.PRESS_MORE_THAN_ONCE;
    private ClickBehavior clickBehavior = ClickBehavior.CHANGE;
    private ClickReleaseBehavior clickReleaseBehavior = ClickReleaseBehavior.RETURN;
    private PassBehavior passBehavior = PassBehavior.NOTHING;
    private ReleaseBehavior releaseBehavior = ReleaseBehavior.NOTHING;

    private Builder(GUIBase stateDefault, GUIBase statePressed) {
        this.stateDefault = stateDefault;
        this.statePressed = statePressed;
    }

    public Builder stateReleased(GUIBase stateReleased) {
        this.stateReleased = stateReleased;
        return this;
    }

    public Builder position(Vector2f position) {
        this.position = position;
        return this;
    }

    public Builder size(Vector2f size) {
        this.size = size;
        return this;
    }

    public Builder onPress(PressBehavior pressBehavior) {
        this.pressBehavior = pressBehavior;
        return this;
    }

    public Builder onClick(ClickBehavior clickBehavior) {
        this.clickBehavior = clickBehavior;
        return this;
    }

    public Builder onClickRelease(ClickReleaseBehavior clickReleaseBehavior) {
        this.clickReleaseBehavior = clickReleaseBehavior;
        return this;
    }

    public Builder onPass(PassBehavior passBehavior) {
        this.passBehavior = passBehavior;
        return this;
    }

    public Builder onRelease(ReleaseBehavior releaseBehavior) {
        this.releaseBehavior = releaseBehavior;
        return this;
    }

    public Button build() {
        final Button newButton = new Button(stateDefault, statePressed, stateReleased, position, size);
        newButton.setBehavior(pressBehavior, clickBehavior, clickReleaseBehavior, passBehavior, releaseBehavior);
        return newButton;
    }
    }

}
\$\endgroup\$
3
  • \$\begingroup\$ Hm. The indentation went wonky copying from Eclipse. Not sure why that happened. Any IDE autoformatter will fix it. \$\endgroup\$
    – Eric Stein
    Commented Mar 4, 2022 at 0:09
  • \$\begingroup\$ Thank you very much! I didn't expect so many things to change. \$\endgroup\$
    – Gyoo
    Commented Mar 4, 2022 at 15:18
  • \$\begingroup\$ for the instancing thing, it's just a way of putting the same thing in different places to re-use the data. So, for example, you have a very detailed 3d model that you want to appear in multiple places, you can render it multiple times, in different places, re-using the data instead of copying it and thus saving some memory. \$\endgroup\$
    – Gyoo
    Commented Mar 4, 2022 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.