package org.flixel.ui; import org.flixel.FlxCamera; import org.flixel.FlxG; import org.flixel.FlxSound; import org.flixel.ui.event.IFlxUIListener; import flash.events.Event; import flash.events.IEventListener; import flash.events.MouseEvent; /** * The parent class for touchable UI components. * * @author Ka Wing Chin */ public class FlxUITouchable extends FlxUIComponent { /** * Used with public variable <code>status</code>, means not highlighted or * pressed. */ static public final int NORMAL = 0; /** * Used with public variable <code>status</code>, means highlighted (usually * from mouse over). */ static public final int HIGHLIGHT = 1; /** * Used with public variable <code>status</code>, means pressed (usually * from mouse click). */ static public final int PRESSED = 2; /** * This function is called when the component is released. We recommend * assigning your main component behavior to this function via the * <code>FlxUITouchable</code> constructor. */ public IFlxUIListener onUp; /** * This function is called when the component is pressed down. */ public IFlxUIListener onDown; /** * This function is called when the mouse goes over the component. */ public IFlxUIListener onOver; /** * This function is called when the mouse leaves the component area. */ public IFlxUIListener onOut; /** * Set this to play a sound when the mouse goes over the component. We * recommend using the helper function setSounds()! */ public FlxSound soundOver; /** * Set this to play a sound when the mouse leaves the component. We * recommend using the helper function setSounds()! */ public FlxSound soundOut; /** * Set this to play a sound when the component is pressed down. We recommend * using the helper function setSounds()! */ public FlxSound soundDown; /** * Set this to play a sound when the component is released. We recommend * using the helper function setSounds()! */ public FlxSound soundUp; /** * Used for checkbox-style behavior. */ protected boolean _onToggle; /** * Tracks whether or not the component is currently pressed. */ protected boolean _pressed; /** * Whether or not the component has initialized itself yet. */ private boolean _initialized; /** * Creates a new <code>FlxUITouchable</code> object. * * @param X The x-position of the component. * @param Y The y-position of the component. * @param UISkin The skin that needs to be applied. * @param Label The label along side the component. * @param Width The width of the component. Default auto. * @param Height The height of the component. Default auto. */ public FlxUITouchable(float X, float Y, FlxUISkin Skin, String Label, int Width, int Height) { super(X, Y, Skin, Label, Width, Height); onUp = null; onDown = null; onOut = null; onOver = null; soundOver = null; soundOut = null; soundDown = null; soundUp = null; status = skin.NORMAL; _onToggle = false; _pressed = false; _initialized = false; } /** * Creates a new <code>FlxUITouchable</code> object. * * @param X The x-position of the component. * @param Y The y-position of the component. * @param UISkin The skin that needs to be applied. * @param Label The label along side the component. * @param Width The width of the component. Default auto. */ public FlxUITouchable(float X, float Y, FlxUISkin Skin, String Label, int Width) { this(X, Y, Skin, Label, Width, 0); } /** * Creates a new <code>FlxUITouchable</code> object. * * @param X The x-position of the component. * @param Y The y-position of the component. * @param UISkin The skin that needs to be applied. * @param Label The label along side the component. */ public FlxUITouchable(float X, float Y, FlxUISkin Skin, String Label) { this(X, Y, Skin, Label, 0, 0); } /** * Creates a new <code>FlxUITouchable</code> object. * * @param X The x-position of the component. * @param Y The y-position of the component. * @param UISkin The skin that needs to be applied. */ public FlxUITouchable(float X, float Y, FlxUISkin Skin) { this(X, Y, Skin, null, 0, 0); } @Override public void destroy() { if(FlxG.getStage() != null) FlxG.getStage().removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); onMouseUp = null; onUp = null; onDown = null; onOut = null; onOver = null; if(soundOver != null) soundOver.destroy(); if(soundOut != null) soundOut.destroy(); if(soundDown != null) soundDown.destroy(); if(soundUp != null) soundUp.destroy(); super.destroy(); } @Override public void setDefaultSkin() { FlxG.log("You don't have a skin provided in your subclass"); } /** * Initialize the mouse listener. */ protected void init() { FlxG.getStage().addEventListener(MouseEvent.MOUSE_UP, onMouseUp); _initialized = true; } @Override public void preUpdate() { super.preUpdate(); if(!_initialized) { if(FlxG.getStage() != null) init(); } } @Override public void update() { super.update(); if(enabled) updateComponent(); } /** * Basic component update logic */ protected void updateComponent() { if(status == PRESSED) status = NORMAL; if(FlxG.mouse.getVisible()) { if(cameras == null) cameras = FlxG.cameras; FlxCamera camera; int i = 0; int l = cameras.size; int pointerId = 0; int totalPointers = FlxG.mouse.activePointers + 1; boolean offAll = true; while(i < l) { camera = cameras.get(i++); while(pointerId < totalPointers) { FlxG.mouse.getWorldPosition(pointerId, camera, _point); if(overlapsPoint(_point, true, camera)) { offAll = false; if(FlxG.mouse.pressed(pointerId)) { status = PRESSED; skinStatus = activated ? skin.ACTIVE_PRESSED : skin.PRESSED; if(FlxG.mouse.justPressed(pointerId)) { if(onDown != null) onDown.callback(); if(soundDown != null) soundDown.play(true); } } if(status == NORMAL || (activated && skinStatus == skin.ACTIVE_NORMAL)) { status = HIGHLIGHT; skinStatus = activated ? skin.ACTIVE_HIGHTLIGHT : skin.HIGHLIGHT; if(onOver != null) onOver.callback(); if(soundOver != null) soundOver.play(true); } } ++pointerId; } } if(offAll) { if(status != NORMAL) { if(onOut != null) onOut.callback(); if(soundOut != null) soundOut.play(true); } status = NORMAL; skinStatus = activated ? skin.ACTIVE_NORMAL : skin.NORMAL; } } if((status == HIGHLIGHT) && FlxG.mobile) { if(activated) skinStatus = enabled ? skin.ACTIVE_NORMAL : skin.ACTIVE_DISABLED; else skinStatus = enabled ? skin.NORMAL : skin.DISABLED; setFrame(skinStatus); } else setFrame(skinStatus); } /** * Use this to toggle checkbox-style behavior. * * @param boolean */ public void setOn(boolean On) { _onToggle = On; } /** * Whether the component has a checkbox-style behavior. * * @return */ public boolean getOn() { return _onToggle; } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. * @param SoundOverVolume How load the that sound should be. * @param SoundOut What embedded sound effect to play when the mouse leaves * the button area. Default is null, or no sound. * @param SoundOutVolume How load the that sound should be. * @param SoundDown What embedded sound effect to play when the mouse * presses the button down. Default is null, or no sound. * @param SoundDownVolume How load the that sound should be. * @param SoundUp What embedded sound effect to play when the mouse releases * the button. Default is null, or no sound. * @param SoundUpVolume How load the that sound should be. */ public void setSounds(String SoundOver, float SoundOverVolume, String SoundOut, float SoundOutVolume, String SoundDown, float SoundDownVolume, String SoundUp, float SoundUpVolume) { if(SoundOver != null) soundOver = FlxG.loadSound(SoundOver, SoundOverVolume); if(SoundOut != null) soundOut = FlxG.loadSound(SoundOut, SoundOutVolume); if(SoundDown != null) soundDown = FlxG.loadSound(SoundDown, SoundDownVolume); if(SoundUp != null) soundUp = FlxG.loadSound(SoundUp, SoundUpVolume); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. * @param SoundOverVolume How load the that sound should be. * @param SoundOut What embedded sound effect to play when the mouse leaves * the button area. Default is null, or no sound. * @param SoundOutVolume How load the that sound should be. * @param SoundDown What embedded sound effect to play when the mouse * presses the button down. Default is null, or no sound. * @param SoundDownVolume How load the that sound should be. * @param SoundUp What embedded sound effect to play when the mouse releases * the button. Default is null, or no sound. */ public void setSounds(String SoundOver, float SoundOverVolume, String SoundOut, float SoundOutVolume, String SoundDown, float SoundDownVolume, String SoundUp) { setSounds(SoundOver, SoundOverVolume, SoundOut, SoundOutVolume, SoundDown, SoundDownVolume, SoundUp, 1.0f); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. * @param SoundOverVolume How load the that sound should be. * @param SoundOut What embedded sound effect to play when the mouse leaves * the button area. Default is null, or no sound. * @param SoundOutVolume How load the that sound should be. * @param SoundDown What embedded sound effect to play when the mouse * presses the button down. Default is null, or no sound. * @param SoundDownVolume How load the that sound should be. */ public void setSounds(String SoundOver, float SoundOverVolume, String SoundOut, float SoundOutVolume, String SoundDown, float SoundDownVolume) { setSounds(SoundOver, SoundOverVolume, SoundOut, SoundOutVolume, SoundDown, SoundDownVolume, null, 1.0f); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. * @param SoundOverVolume How load the that sound should be. * @param SoundOut What embedded sound effect to play when the mouse leaves * the button area. Default is null, or no sound. * @param SoundOutVolume How load the that sound should be. * @param SoundDown What embedded sound effect to play when the mouse * presses the button down. Default is null, or no sound. */ public void setSounds(String SoundOver, float SoundOverVolume, String SoundOut, float SoundOutVolume, String SoundDown) { setSounds(SoundOver, SoundOverVolume, SoundOut, SoundOutVolume, SoundDown, 1.0f, null, 1.0f); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. * @param SoundOverVolume How load the that sound should be. * @param SoundOut What embedded sound effect to play when the mouse leaves * the button area. Default is null, or no sound. * @param SoundOutVolume How load the that sound should be. */ public void setSounds(String SoundOver, float SoundOverVolume, String SoundOut, float SoundOutVolume) { setSounds(SoundOver, SoundOverVolume, SoundOut, SoundOutVolume, null, 1.0f, null, 1.0f); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. * @param SoundOverVolume How load the that sound should be. * @param SoundOut What embedded sound effect to play when the mouse leaves * the button area. Default is null, or no sound. */ public void setSounds(String SoundOver, float SoundOverVolume, String SoundOut) { setSounds(SoundOver, SoundOverVolume, SoundOut, 1.0f, null, 1.0f, null, 1.0f); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. * @param SoundOverVolume How load the that sound should be. */ public void setSounds(String SoundOver, float SoundOverVolume) { setSounds(SoundOver, SoundOverVolume, null, 1.0f, null, 1.0f, null, 1.0f); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. * * @param SoundOver What embedded sound effect to play when the mouse goes * over the button. Default is null, or no sound. */ public void setSounds(String SoundOver) { setSounds(SoundOver, 1.0f, null, 1.0f, null, 1.0f, null, 1.0f); } /** * Set sounds to play during mouse-button interactions. These operations can * be done manually as well, and the public sound variables can be used * after this for more fine-tuning, such as positional audio, etc. */ public void setSounds() { setSounds(null, 1.0f, null, 1.0f, null, 1.0f, null, 1.0f); } /** * Internal function for handling the actual callback call (for UI thread * dependent calls like <code>FlxU.openURL()</code>). */ IEventListener onMouseUp = new IEventListener() { @Override public void onEvent(Event e) { if(!exists || !visible || !active || (status != PRESSED)) return; if(_onToggle) { activated = !activated; skinStatus = activated ? skin.ACTIVE_NORMAL : skin.NORMAL; setFrame(skinStatus); } onChange(); if(onUp != null) onUp.callback(); if(soundUp != null) soundUp.play(true); } }; /** * This method will be called on mouse up. It's used for internal behavior. * Override this in subclass. */ protected void onChange() { // Override this in subclass. } }