Results 1 to 9 of 9
  1. #1
    godshawk's Avatar
    Join Date
    Mar 2013
    Gender
    female
    Location
    root@google ~#
    Posts
    90
    Reputation
    14
    Thanks
    134
    My Mood
    Crappy

    [OOP] How to make a clickable, draggable, OOP GUI

    Since there's like 0 information about this out there, I figured I'd be nice to all the skidz out there.

    Let's begin.




    First, we need a class called ModManager or something similar. This really just holds ArrayList<Mod>s that we used to make everyone's lives easier.
    It'll look something like this...:
    Code:
    package com.godshawk.colony.mods;
    
    import java.util.ArrayList;
    
    import com.godshawk.colony.core.Colony;
    
    public class ModManager {
    	
    	public ArrayList<Mod> mods;
    	public ArrayList<Mod> worldMods;
    	public ArrayList<Mod> playerMods;
    	
    	public ModManager( Colony c ) {
    		/*
    		 * Eventually, I'll get around to having an EnumGUI
    		 */
    		mods = new ArrayList<Mod>( );
    		worldMods = new ArrayList<Mod>( );
    		playerMods = new ArrayList<Mod>( );
    		
    		/** 
                           -snip-
                                     **/
    		
    		// Main mod list
    		for ( Mod m : worldMods ) {
    			mods.add( m );
    		}
    		for ( Mod m : playerMods ) {
    			mods.add( m );
    		}
    	}
    	
    	public void addMod( Mod m ) {
    		mods.add( m );
    	}
    	
    	public void addWMod( Mod m ) {
    		worldMods.add( m );
    	}
    	
    	public void addPMod( Mod m ) {
    		playerMods.add( m );
    	}
    	
    	/**
    	 * Gets hack by name. Ignores case. Returns matching mod; returns null
    	 * otherwise. TODO Throw exception if mod==null?
    	 * 
    	 * @param name
    	 * @return
    	 */
    	public Mod getHackByName( String name ) {
    		for ( int i = 0; i < mods.size( ); i++ ) {
    			if ( name.equalsIgnoreCase( mods.get( i ).name ) ) {
    				return mods.get( i );
    			}
    		}
    		throw new NullPointerException( "Yo, hack " + name + " don't exist, bro. Da hale you thinkin'?" );
    	}
    }
    Mkay, so this should be self explanatory. We have ArrayList<Mod>s that hold our hacks in them. We use these for organizing our hacks in the right tabs. Yeah, it'd be neater to have it as "EnumGuiTab.[...]", but I haven't done that yet.

    The getHackByName(...) method simply goes through our list of hacks to see if any of the hacks has the same name as the string passed in. If not, it throws an exception. Don't forget to "try {...} catch(...) {...}" it wherever you call it.

    Now that we have that, we can move on to our GUI.




    Okay, so all our GUI elements (buttons, windows, sliders, text, etc) will extend a base class that provides a lot of functionality. Let's call it Item.java.

    Code:
    package com.godshawk.colony.gui.api.components;
    
    import com.godshawk.colony.core.Colony;
    
    public abstract class Item {
    	/**
    	 * Reference to the main class
    	 */
    	public Colony c;
    	
    	/**
    	 * Parent frame
    	 */
    	public Frame parent;
    	
    	/**
    	 * How to color it
    	 */
    	public int color;
    	
    	/**
    	 * Used for determining whether to do a gradient quad
    	 */
    	public int color2 = -1;
    	
    	/**
    	 * X position
    	 */
    	int x = 0;
    	
    	/**
    	 * Y position
    	 */
    	int y = 0;
    	
    	/**
    	 * Width
    	 */
    	int width = 0;
    	
    	/**
    	 * Height
    	 */
    	int height = 0;
    	
    	/**
    	 * Can it be dragged?
    	 */
    	public boolean draggable;
    	
    	/**
    	 * Is it currently being dragged?
    	 */
    	public boolean dragging;
    	
    	/**
    	 * Is it active? Ie do we activate the bound hack?
    	 */
    	public boolean active;
    	
    	/**
    	 * String to render on it
    	 */
    	public String text;
    	
    	/**
    	 * Drawing the thing is important too, you know?
    	 */
    	public abstract void draw( );
    	
    	/**
    	 * Updates. (Would) Handle[s] updating text,...
    	 */
    	public void update( ) {
    		draw( );
    	}
    	
    	/**
    	 * Drags the item
    	 */
    	public abstract void drag( int x, int y );
    	
    	/**
    	 * Sets the item's state to the given boolean. Args: State
    	 * 
    	 * @param tof
    	 */
    	public void setActive( boolean tof ) {
    		this.active = tof;
    	}
    	
    	/**
    	 * Updates the text to the given string. Args: New text
    	 * 
    	 * @param text
    	 */
    	public void updateText( String text ) {
    		this.text = text;
    	}
    	
    	/**
    	 * Returns true if the component is being dragged
    	 * 
    	 * @return
    	 */
    	public boolean isDragging( ) {
    		if ( draggable ) {
    			if ( dragging ) {
    				return true;
    			}
    		}
    		return false;
    	}
    	
    	/**
    	 * Sets the dragging state. Args: New state
    	 */
    	public void setDragging( boolean state ) {
    		this.dragging = state;
    	}
    	
    	/**
    	 * Sets whether this Item is draggable
    	 * 
    	 * @param tof
    	 */
    	public void setDraggable( boolean tof ) {
    		this.draggable = tof;
    	}
    	
    	public boolean isDraggable( ) {
    		if ( draggable ) {
    			return true;
    		}
    		return false;
    	}
    	
    	/**
    	 * Handles mouse clicks
    	 * 
    	 * @param x
    	 * @param y
    	 */
    	public abstract void onClick( int x, int y );
    	
    	/**
    	 * Converts a hex value into a float[] we can use with glColor4f(...)
    	 * 
    	 * @param hex
    	 * @return
    	 */
    	public static float[ ] hexToRGBA( int hex )
    	{
    		float r = ( ( hex >> 16 ) & 255 ) / 255F;
    		float g = ( ( hex >> 8 ) & 255 ) / 255F;
    		float b = ( hex & 255 ) / 255F;
    		float a = ( ( hex >> 24 ) & 255 ) / 255F;
    		return new float[ ] { r, g, b, a };
    	}
    	
    	/**
    	 * Returns true if the mouse has clicked inside the component
    	 * 
    	 * @param x
    	 * @param y
    	 * @return
    	 */
    	public boolean clickedInside( int x, int y ) {
    		if ( x > this.x ) {
    			if ( y > this.y ) {
    				if ( x < ( this.x + this.width ) ) {
    					if ( y < ( this.y + this.height ) ) {
    						return true;
    					}
    				}
    			}
    		}
    		return false;
    	}
    	
    	public void setParent( Frame e, int x, int y ) {
    		this.parent = e;
    		this.x = x;
    		this.y = y;
    	}
    	
    	/**
    	 * Would, theoretically, be used for recoloring buttons when they're moused
    	 * over.
    	 * 
    	 * @param x
    	 * @param y
    	 * @return
    	 */
    	public abstract boolean mouseOver( int x, int y );
    }
    Most everything here is commented, so I'm just going to gloss over it. The only thing that might need explaining is the setParent(...){...} method. This method just tells the item which frame it's 'attached' to, and where to position itself. 'Course, now we need that frame class. Here it is:

    Code:
    package com.godshawk.colony.gui.api.components;
    
    import java.util.ArrayList;
    
    import com.godshawk.colony.core.Colony;
    import com.godshawk.colony.gui.api.render.ModGuiUtils;
    
    public class Frame extends Item {
    	public ArrayList<Item> toBeAdded = new ArrayList<Item>( );
    	public ArrayList<Item> toBeRemoved = new ArrayList<Item>( );
    	public ArrayList<Item> children = new ArrayList<Item>( );
    	boolean minimized = false;
    	public boolean pinnable = false;
    	public boolean pinned = false;
    	
    	/**
    	 * Should we clear labels? Only used for the console
    	 */
    	public boolean shouldClear = false;
    	int oldHeight = 0;
    	
    	public Frame( Colony c, int x, int y, int w, int h, String s ) {
    		this( c, x, y, w, h, 0xff666666, s );
    	}
    	
    	public Frame( Colony c, int x, int y, int w, int h, int color, String s ) {
    		this( c, x, y, w, h, color, -1, s );
    	}
    	
    	public Frame( Colony c, int x, int y, int w, int h, int color, int color2, String s ) {
    		this.c = c;
    		this.x = x;
    		this.y = y;
    		this.width = w;
    		this.height = h;
    		this.oldHeight = h;
    		this.color = color;
    		this.color2 = color2;
    		this.text = s;
    		this.setDraggable( true );
    	}
    	
     @override
    	public void update( ) {
    		this.draw( );
    	}
    	
     @override
    	public void draw( ) {
    		// TODO Auto-generated method stub
    		
    		if ( color2 > -1 ) {
    			ModGuiUtils.drawRect( x, y, x + width, y + oldHeight, color );
    			ModGuiUtils.drawRect( x, y, x + width, y + oldHeight, (int) ( color * 1.1 ) );
    		} else {
    			ModGuiUtils.drawGradientRect( x, y, x + width, y + oldHeight, color, color2 );
    			ModGuiUtils.drawRect( x, y + oldHeight, x + width, y + height, color2 );
    		}
    		
    		/**
    		 * Minimize button
    		 */
    		ModGuiUtils.drawFilledCircle( ( x + width ) - 8, y + 7, 2.5, 0xff00dd66 );
    		if ( minimized ) {
    			ModGuiUtils.drawFilledCircle( ( x + width ) - 8, y + 7, 2.5, 0xaa000000 );
    		}
    		
    		if ( pinnable ) {
    			ModGuiUtils.drawFilledCircle( ( x + width ) - 16, y + 7, 2.5, 0xff72a9dc );
    			if ( pinned ) {
    				ModGuiUtils.drawFilledCircle( ( x + width ) - 16, y + 7, 2.5, 0xaa000000 );
    			}
    		}
    		
    		ModGuiUtils.drawHorizontalLine( this.x + 2, ( this.x + this.width ) - 2, ( this.y + this.oldHeight ) - 6, 2, 0xff550055 );
    		
    		Colony.instance.minecraft.fontRenderer.drawString( this.text, this.x + 3, this.y + 3, 0xff87b5ff );
    		
    		if ( minimized ) {
    			this.height = oldHeight;
    			
    		} else {
    			this.height = (int) ( oldHeight + ( ( oldHeight * this.children.size( ) ) / 1.4 ) + 5 );
    		}
    		if ( !minimized ) {
    			for ( Item e : children ) {
    				e.x = ( this.x ) + 3;
    				int offset = oldHeight;
    				offset /= 2;
    				offset += 4;
    				e.y = ( this.y ) + ( offset * ( this.children.indexOf( e ) + 1 ) ) + 10;
    				e.update( );
    			}
    		}
    	}
    	
     @override
    	public void drag( int x, int y ) {
    		// TODO Auto-generated method stub
    		if ( !this.isDraggable( ) || !this.isDragging( ) ) {
    			return;
    		}
    		
    		this.x = x;
    		this.y = y;
    	}
    	
     @override
    	public void onClick( int x, int y ) {
    		// TODO Auto-generated method stub
    		// ModGuiUtils.drawFilledCircle( ( x + width ) - 8, y + 7, 2.5,
    		// 0xffaa0033 );
    		
    		if ( this.clickedInside( x, y ) ) {
    			if ( x >= ( ( this.x + this.width ) - 8 - 2.5 ) ) {
    				if ( x <= ( ( ( this.x + this.width ) - 8 ) + 2.5 ) ) {
    					if ( y >= ( ( this.y + 7 ) - 2.5 ) ) {
    						if ( y <= ( this.y + 7 + 2.5 ) ) {
    							this.minimized = !this.minimized;
    						}
    					}
    				}
    			} else if ( x >= ( ( this.x + this.width ) - 16 - 2.5 ) ) {
    				if ( x <= ( ( ( this.x + this.width ) - 16 ) + 2.5 ) ) {
    					if ( y >= ( ( this.y + 7 ) - 2.5 ) ) {
    						if ( y <= ( this.y + 7 + 2.5 ) ) {
    							this.pinned = !this.pinned;
    						}
    					}
    				}
    				
    			} else {
    				this.setDragging( true );
    			}
    		}
    		if ( !this.minimized ) {
    			for ( Item e : children ) {
    				e.onClick( x, y );
    			}
    		}
    	}
    	
    	public void mouseUp( ) {
    		this.setDragging( false );
    	}
    	
    	public void addChild( Item e ) {
    		children.add( e );
    		e.setParent( this, 0, 0 );
    	}
    	
    	public void removeChild( Item e ) {
    		children.remove( e );
    	}
    	
    	public void addLater( Item e ) {
    		toBeAdded.add( e );
    	}
    	
    	public void removeLater( Item e ) {
    		toBeRemoved.add( e );
    	}
    	
     @override
    	public boolean clickedInside( int x, int y ) {
    		if ( x > this.x ) {
    			if ( y > this.y ) {
    				if ( x < ( this.x + this.width ) ) {
    					if ( y < ( this.y + this.oldHeight ) ) {
    						return true;
    					}
    				}
    			}
    		}
    		return false;
    	}
    	
     @override
    	public boolean mouseOver( int x, int y ) {
    		// TODO Auto-generated method stub
    		return false;
    	}
    	
    	public void setPinnable( boolean state ) {
    		this.pinnable = state;
    	}
    }
    Right. This is kinda confusing, and not very commented. Let's break it down:

    -public Frame( Colony c, int x, int y, int w, int h, String s )
    This constructor just makes a very quick and basic frame. Used for testing and I never got around to changing it.
    Parameters are: Main hack class, x, y, width, height, title

    -public Frame( Colony c, int x, int y, int w, int h, int color, String s )
    Alright, bit more advanced. Like the above, only a color parameter is added.

    -public Frame( Colony c, int x, int y, int w, int h, int color, int color2, String s )
    The actual constructor. Has 2 color parameters so that we can do that beautiful gradient thing you see in the GUI of my client.
    The 'oldHeight' variable is used for handling minimizing. Yeah, there's probably a better way, but whatever. I threw this together at 2 in the morning.

    -public void update()
    The @override" annotation tells Java that this method overrides the update() method inherited from Item.java. All this does is call the frame's draw() method.

    -public void draw()
    Renders the frame onscreen. Breakdown:
    *if(color2 > -1) {...} else {...}
    This is used to determine whether we should do the gradient GUI. color2 defaults to -1 (As set in Item.java), so this always works.

    *if(minimized) {...}
    Change what the minimize button looks like when it's minimized. In this case, make it darker.

    *if(pinnable) {...}
    Same story as above.

    *if(minimized) {...}
    Handles height for minimized and not-minimized states.

    *if(!minimized) {for(Item e : children) {...} }
    Updates the child items.

    Everything else should be simple to understand.

    Now we need the child items that the frames can hold. The examples that I'll give are buttons and labels. First the buttons...

    Code:
    package com.godshawk.colony.gui.api.components;
    
    import com.godshawk.colony.core.Colony;
    import com.godshawk.colony.gui.api.render.ModGuiUtils;
    import com.godshawk.colony.mods.Mod;
    
    public class Button extends Item {
    	Frame parent;
    	Mod m = null;
    	int oldColor = 0;
    	
    	public Button( String s, int color, int color2 ) {
    		this( s, color, color2, null );
    	}
    	
    	public Button( String s, int color, int color2, Mod m ) {
    		this.text = s;
    		this.color = color;
    		this.color2 = color2;
    		this.oldColor = color2;
    		this.m = m;
    	}
    	
     @override
    	public void draw( ) {
    		// TODO Auto-generated method stub
    		ModGuiUtils.drawBorderedRect( x, y, x + width, y + height, 2, color, 0x77000077 );
    		Colony.instance.minecraft.fontRenderer.drawString( text, x + 2, y + 2, color2 );
    	}
    	
     @override
    	public void update( ) {
    		if ( this.m != null ) {
    			this.text = this.m.name;
    			if ( m.isActive( ) ) {
    				color2 = 0x00ff00;
    			} else {
    				color2 = oldColor;
    			}
    		}
    		this.draw( );
    	}
    	
     @override
    	public void drag( int x, int y ) {
    		// TODO Auto-generated method stub
    		return;
    	}
    	
     @override
    	public void onClick( int x, int y ) {
    		// TODO Auto-generated method stub
    		if ( this.clickedInside( x, y ) ) {
    			if ( this.m != null ) {
    				this.m.toggle( );
    			} else {
    				return;
    			}
    		}
    	}
    	
     @override
    	public void setParent( Frame e, int x, int y ) {
    		this.parent = e;
    		this.x = x;
    		this.y = y;
    	}
    	
    	public void setWidth( int w ) {
    		this.width = w;
    	}
    	
    	public void setHeight( int h ) {
    		this.height = h;
    	}
    	
     @override
    	public boolean mouseOver( int x, int y ) {
    		if ( x >= this.x ) {
    			if ( x <= ( this.x + this.width ) ) {
    				if ( y >= this.y ) {
    					if ( y <= ( this.y + this.height ) ) {
    						return true;
    					}
    				}
    			}
    		}
    		return false;
    	}
    }
    Bear in mind that this button will only be used for toggling hacks. You want it to do something else, you gotta change it yourself.
    And if you don't get this..... Well, I recommend learning some more Java. OOP is NOT for the faint of heart/noobs/skidz.

    Labels:

    Code:
    package com.godshawk.colony.gui.api.components;
    
    import com.godshawk.colony.core.Colony;
    
    public class Label extends Item {
    	Frame parent;
    	
    	public Label( String s, int color ) {
    		this.text = s;
    		this.color = color;
    	}
    	
     @override
    	public void update( ) {
    		this.draw( );
    	}
    	
     @override
    	public void draw( ) {
    		// TODO Auto-generated method stub
    		
    		Colony.instance.minecraft.fontRenderer.drawString( text, x + 3, y + 3, color );
    	}
    	
     @override
    	public void drag( int x, int y ) {
    		// TODO Auto-generated method stub
    		return;
    	}
    	
     @override
    	public void onClick( int x, int y ) {
    		// TODO Auto-generated method stub
    		return;
    	}
    	
     @override
    	public void setParent( Frame e, int x, int y ) {
    		this.parent = e;
    		this.x = x;
    		this.y = y;
    	}
    	
     @override
    	public boolean mouseOver( int x, int y ) {
    		// TODO Auto-generated method stub
    		return false;
    	}
    }
    That's it. Very, very, very simple.

    Now to pull it all together. We need a GuiScreen that holds all the items we make, so that it can be rendered.

    Here's an example one:

    Code:
    package com.godshawk.colony.gui.api.components;
    
    import java.util.ArrayList;
    
    import net.minecraft.src.Direction;
    import net.minecraft.src.GuiScreen;
    import net.minecraft.src.MathHelper;
    import net.minecraft.src.TcpConnection;
    import net.minecraft.src.Timer;
    
    import org.lwjgl.input.Keyboard;
    import org.lwjgl.opengl.GL11;
    
    import com.godshawk.colony.core.Colony;
    import com.godshawk.colony.gui.api.render.ModGuiUtils;
    import com.godshawk.colony.gui.api.testing.TestEntityRenderer;
    import com.godshawk.colony.mods.Mod;
    
    public class TestGui extends GuiScreen {
    	
    	public ArrayList<Frame> frames;
    	
    	public TestGui( ) {
    		frames = new ArrayList<Frame>( );
    		initFrames( );
    		for ( Frame e : frames ) {
    			e.minimized = true;
    		}
    	}
    	
     @override
    	public boolean doesGuiPauseGame( ) {
    		return false;
    	}
    	
     @override
    	public void initGui( ) {
    		Keyboard.enableRepeatEvents( true );
    	}
    	
     @override
    	public void onGuiClosed( ) {
    		Keyboard.enableRepeatEvents( true );
    	}
    	
     @override
    	protected void keyTyped( char c, int i ) {
    		if ( i == 1 ) {
    			mc.displayGuiScreen( null );
    			return;
    		}
    		
    		for ( Frame e : this.frames ) {
    			for ( Item t : e.children ) {
    				if ( t instanceof TextArea ) {
    					( (TextArea) t ).keyPressed( i );
    				}
    			}
    		}
    	}
    	
     @override
    	public void drawScreen( int i, int j, float f ) {
    		for ( Frame e : frames ) {
    			e.update( );
    			if ( e.toBeAdded.size( ) > 0 ) {
    				for ( Item q : e.toBeAdded ) {
    					e.addChild( q );
    				}
    				e.toBeAdded.clear( );
    			}
    			if ( e.toBeRemoved.size( ) > 0 ) {
    				for ( Item q : e.toBeRemoved ) {
    					e.removeChild( q );
    				}
    				e.toBeRemoved.clear( );
    			}
    		}
    		
    		this.mouseDragged( i, j );
    	}
    	
     @override
    	protected void mouseClicked( int i, int j, int k ) {
    		for ( Frame e : frames ) {
    			e.onClick( i, j );
    		}
    	}
    	
    	public void mouseDragged( int i, int j )
    	{
    		for ( Frame e : frames ) {
    			int q = ( e.x - i ) / 2;
    			int r = ( e.y - j ) / 2;
    			q += i - ( e.width / 4 );
    			r += j - ( e.oldHeight / 4 );
    			e.drag( q, r );
    		}
    	}
    	
     @override
    	protected void mouseMovedOrUp( int par1, int par2, int par3 ) {
    		for ( Frame e : frames ) {
    			e.mouseUp( );
    		}
    	}
    	
    	public void makeWorldFrame( ) {
    		Frame wFrame = new Frame( Colony.instance, 10, 10, 120, 20, 0xff550055, 0xaa000000, "World" );
    		for ( Mod m : Colony.instance.mmanager.worldMods ) {
    			Button b = new Button( m.name, 0xff000077, 0xffffff, m );
    			b.setWidth( wFrame.width - 6 );
    			b.setHeight( wFrame.oldHeight - 8 );
    			wFrame.addChild( b );
    		}
    		wFrame.setPinnable( false );
    		addFrame( wFrame );
    	}
    	
    	public void makePlayerFrame( ) {
    		Frame pFrame = new Frame( Colony.instance, 130, 10, 120, 20, 0xff550055, 0xaa000000, "Player" );
    		for ( Mod m : Colony.instance.mmanager.playerMods ) {
    			Button b = new Button( m.name, 0xff000077, 0xffffff, m );
    			b.setWidth( pFrame.width - 6 );
    			b.setHeight( pFrame.oldHeight - 8 );
    			pFrame.addChild( b );
    		}
    		addFrame( pFrame );
    	}
    	
    	public void makeInfoFrame( ) {
    		final Frame iFrame = new Frame( Colony.instance, 250, 30, 120, 20, 0xff550055, 0xaa000000, "Player Info" ) {
    		 @override
    			public void update( ) {
    				this.draw( );
    				String dim = "Overworld";
    				String dir = "NORTH";
    				int d = mc.thePlayer.dimension;
    				
    				if ( d == -1 ) {
    					dim = "Nether";
    				}
    				if ( d == 0 ) {
    					dim = "Overworld";
    				}
    				if ( d == 1 ) {
    					dim = "The End";
    				}
    				
    				int var24 = MathHelper.floor_double( ( ( mc.thePlayer****tationYaw * 4.0F ) / 360.0F ) + 0.5D ) & 3;
    				dir = Direction.directions [ var24 ];
    				try {
    					children.clear( );
    					addChild( new Label( "User: " + Colony.instance.minecraft.thePlayer.username, 0xffffff ) );
    					addChild( new Label( "FPS: " + mc.debugFPS, 0xffffff ) );
    					addChild( new Label( "Lagg: " + TcpConnection.field_74490_x, 0xffffff ) );
    					addChild( new Label( "X: " + (int) Colony.instance.minecraft.thePlayer.posX, 0xffffff ) );
    					addChild( new Label( "Y: " + (int) Colony.instance.minecraft.thePlayer.posY, 0xffffff ) );
    					addChild( new Label( "Z: " + (int) Colony.instance.minecraft.thePlayer.posZ, 0xffffff ) );
    					addChild( new Label( "Dimension: " + dim, 0xffffff ) );
    					addChild( new Label( "Facing " + dir, 0xffffff ) );
    					addChild( new Label( "Timer: " + Timer.timerSpeed, 0xffffff ) );
    					
    					addChild( new Label( "", 0xffffff ) );
    				} catch ( Exception e ) {
    					e.printStackTrace( );
    				}
    				
    			}
    			
    		 @override
    			public void draw( ) {
    				// TODO Auto-generated method stub
    				
    				if ( color2 > -1 ) {
    					ModGuiUtils.drawRect( x, y, x + width, y + oldHeight, color );
    					ModGuiUtils.drawRect( x, y, x + width, y + oldHeight, (int) ( color * 1.1 ) );
    				} else {
    					ModGuiUtils.drawGradientRect( x, y, x + width, y + oldHeight, color, color2 );
    					ModGuiUtils.drawRect( x, y + oldHeight, x + width, y + height, color2 );
    				}
    				
    				/**
    				 * Minimize button
    				 */
    				ModGuiUtils.drawFilledCircle( ( x + width ) - 8, y + 7, 2.5, 0xff00dd66 );
    				if ( minimized ) {
    					ModGuiUtils.drawFilledCircle( ( x + width ) - 8, y + 7, 2.5, 0xaa000000 );
    				}
    				
    				if ( pinnable ) {
    					ModGuiUtils.drawFilledCircle( ( x + width ) - 16, y + 7, 2.5, 0xff72a9dc );
    					if ( pinned ) {
    						ModGuiUtils.drawFilledCircle( ( x + width ) - 16, y + 7, 2.5, 0xaa000000 );
    					}
    				}
    				
    				ModGuiUtils.drawHorizontalLine( this.x + 2, ( this.x + this.width ) - 2, ( this.y + this.oldHeight ) - 6, 2, 0xff550055 );
    				
    				Colony.instance.minecraft.fontRenderer.drawString( this.text, this.x + 3, this.y + 3, 0xff87b5ff );
    				
    				if ( minimized ) {
    					this.height = oldHeight;
    				} else {
    					this.height = (int) ( oldHeight + ( ( oldHeight * this.children.size( ) ) / 1.4 ) + 5 ) / 2;
    				}
    				if ( !minimized ) {
    					GL11.glPushMatrix( );
    					GL11.glScaled( 0.5, 0.5, 0.5 );
    					for ( Item e : children ) {
    						e.x = ( ( this.x ) + 3 ) * 2;
    						int offset = oldHeight;
    						offset /= 8;
    						offset += 4;
    						e.y = ( ( this.y ) + ( offset * ( this.children.indexOf( e ) + 1 ) ) + 15 ) * 2;
    						
    						e.update( );
    						
    					}
    					GL11.glScaled( 1, 1, 1 );
    					GL11.glPopMatrix( );
    				}
    			}
    		};
    		iFrame.setPinnable( true );
    		addFrame( iFrame );
    	}
    	
    	public void addFrame( Frame e ) {
    		frames.add( e );
    	}
    	
    	public void initFrames( ) {
    		makeWorldFrame( );
    		makePlayerFrame( );
    		makeInfoFrame( );
    	}
    }
    We start by having a *public* ArrayList of frames. This is VERY IMPORTANT.
    The constructor just initializes and minimizes all the frames. Most of the rest is standard GuiScreen stuff, but adapted to fit our needs. Ie, the drawScreen(...) method updates and draws the frames and the children of each frame, the mouse methods deal with the frames, etc.

    The nice thing is that you're able to override methods of the Frame class while instantiating it; you can see an example of that in the info frame.
    The reason we needed the ModManager class is to make this:
    Code:
    	public void makeWorldFrame( ) {
    		Frame wFrame = new Frame( Colony.instance, 10, 10, 120, 20, 0xff550055, 0xaa000000, "World" );
    		for ( Mod m : Colony.instance.mmanager.worldMods ) {
    			Button b = new Button( m.name, 0xff000077, 0xffffff, m );
    			b.setWidth( wFrame.width - 6 );
    			b.setHeight( wFrame.oldHeight - 8 );
    			wFrame.addChild( b );
    		}
    		wFrame.setPinnable( false );
    		addFrame( wFrame );
    	}
    	
    	public void makePlayerFrame( ) {
    		Frame pFrame = new Frame( Colony.instance, 130, 10, 120, 20, 0xff550055, 0xaa000000, "Player" );
    		for ( Mod m : Colony.instance.mmanager.playerMods ) {
    			Button b = new Button( m.name, 0xff000077, 0xffffff, m );
    			b.setWidth( pFrame.width - 6 );
    			b.setHeight( pFrame.oldHeight - 8 );
    			pFrame.addChild( b );
    		}
    		addFrame( pFrame );
    	}
    work. These two methods go through the ArrayList<mod>s that we set up earlier and add the mods from those automatically. Now, if you want to add a hack, you just write it up and then add it in the ModManager, and it's automatically added to the GUI.

    That public ArrayList of Frames that we made is important. We can use it to render pinned frames onscreen like this:

    Code:
    	public void updatePinnedFrames( ) {
    		if ( ( minecraft.currentScreen == null ) || ( minecraft.currentScreen == (Gui) minecraft.ingameGUI ) ) {
    			for ( Frame frame : modgui.frames ) {
    				if ( frame.pinned && frame.pinnable ) {
    					frame.update( );
    				}
    			}
    		}
    	}
    See? Very easy.




    Questions? Comments? Concerns? Leave a reply!

  2. The Following 2 Users Say Thank You to godshawk For This Useful Post:

    Heterodon. (04-27-2013),LordPankake (05-04-2013)

  3. #2
    godshawk's Avatar
    Join Date
    Mar 2013
    Gender
    female
    Location
    root@google ~#
    Posts
    90
    Reputation
    14
    Thanks
    134
    My Mood
    Crappy
    Bump.

    /msg2short

  4. #3
    godshawk's Avatar
    Join Date
    Mar 2013
    Gender
    female
    Location
    root@google ~#
    Posts
    90
    Reputation
    14
    Thanks
    134
    My Mood
    Crappy
    Bumpity bump.

    /msglongenoughbutwhocares?

  5. #4
    Smaug's Avatar
    Join Date
    Apr 2011
    Gender
    male
    Posts
    2,518
    Reputation
    121
    Thanks
    1,192
    Nice tutorial.
    Member Level 1 since 4/20/11 - 8/4/14
    Member Level 2 since 8/4/14 - present

  6. #5
    Be there for others, but never leave yourself behind.
    Premium Member
    Heterodon.'s Avatar
    Join Date
    Aug 2012
    Gender
    male
    Location
    Middle Earth
    Posts
    1,530
    Reputation
    39
    Thanks
    176
    nice tut keep it up









    MPGH Member Since August 05th, 2012
    MPGH Donator Since March 18th, 2013








  7. #6
    godshawk's Avatar
    Join Date
    Mar 2013
    Gender
    female
    Location
    root@google ~#
    Posts
    90
    Reputation
    14
    Thanks
    134
    My Mood
    Crappy
    Bump.

    /noonecaresD8

  8. #7
    gamer_1_2_3's Avatar
    Join Date
    Apr 2013
    Gender
    male
    Posts
    25
    Reputation
    10
    Thanks
    3
    bumpy ride !!!!!

  9. #8
    Quck's Avatar
    Join Date
    Feb 2012
    Gender
    male
    Posts
    1,809
    Reputation
    45
    Thanks
    164
    My Mood
    Crappy
    Bumpity bump bumper bumped bumpily bump.

    /msgmakesnosensebutidontmind

  10. #9
    Dylan's Avatar
    Join Date
    Mar 2013
    Gender
    male
    Location
    Nowhere
    Posts
    1,893
    Reputation
    359
    Thanks
    1,988
    My Mood
    Sleepy
    Hmm, It works okay, also looks good.

    NewsForce December 2015 - April 2016
    Premium Member April 2013 - Current
    MPGH Member March 2013 - Current



Similar Threads

  1. How to make a game?
    By Dave84311 in forum General
    Replies: 4
    Last Post: 09-12-2006, 12:33 AM
  2. How to make a working NFV Hack
    By System79 in forum Game Hacking Tutorials
    Replies: 1
    Last Post: 09-04-2006, 04:56 AM
  3. How to make the server run
    By wowhaxor in forum Gunz General
    Replies: 3
    Last Post: 05-25-2006, 09:59 PM
  4. How to make a Zombie
    By arunforce in forum Art & Graphic Design
    Replies: 2
    Last Post: 01-27-2006, 08:07 AM
  5. How I make wallhack?
    By RaidenDXX in forum WarRock - International Hacks
    Replies: 6
    Last Post: 01-23-2006, 01:28 PM