Browse Source

Redesigned Button functionality.

- Buttons now have a Button component at design time
- The Button.autoHide property controls automatic hiding when
displaying page text / waiting
- The Button.hideOnFlag property controls hiding when a named flag
value is set to true
- Added Button prefab asset
- Added default Button sprite texture
master
chrisgregan 11 years ago
parent
commit
1aaf67633b
  1. BIN
      Assets/Fungus/Prefabs/Button.prefab
  2. 4
      Assets/Fungus/Prefabs/Button.prefab.meta
  3. 103
      Assets/Fungus/Scripts/Button.cs
  4. 59
      Assets/Fungus/Scripts/ButtonController.cs
  5. 8
      Assets/Fungus/Scripts/ButtonController.cs.meta
  6. 55
      Assets/Fungus/Scripts/Commands.cs
  7. 27
      Assets/Fungus/Scripts/Game.cs
  8. 53
      Assets/Fungus/Scripts/GameController.cs
  9. 8
      Assets/Fungus/Scripts/Room.cs
  10. BIN
      Assets/Fungus/Sprites/Button.psd
  11. 45
      Assets/Fungus/Sprites/Button.psd.meta
  12. BIN
      Assets/FungusExample/Scenes/Example.unity
  13. 21
      Assets/FungusExample/Scripts/ButtonRoom.cs
  14. 9
      Assets/FungusExample/Scripts/SpriteRoom.cs

BIN
Assets/Fungus/Prefabs/Button.prefab

Binary file not shown.

4
Assets/Fungus/Prefabs/Button.prefab.meta

@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 2830c354320dd41fb8c7fe61f592942c
NativeFormatImporter:
userData:

103
Assets/Fungus/Scripts/Button.cs

@ -10,55 +10,110 @@ namespace Fungus
* When the user taps on the sprite, an Action delegate method is called
*/
[RequireComponent (typeof (SpriteRenderer))]
[RequireComponent (typeof (Collider2D))]
public class Button : MonoBehaviour
{
public SpriteRenderer spriteRenderer;
public bool autoDisplay;
/**
* Delegate method to call when the player clicks the button.
*/
public Action buttonAction;
/**
* Makes a sprite clickable by attaching a Button component (and BoxCollider2D if required).
* @param _spriteRenderer The sprite to be made clickable
* @param _buttonAction An Action delegate method to call when the player clicks on the sprite
* Automatically hide the button when displaying story text/options or waiting.
*/
public bool autoHide;
/**
* Hide the button when a value is set.
*/
public string hideOnFlag;
float targetAlpha;
bool showButton;
/**
* Set visibility of a button object and set the delegate method to call when clicked.
* If the object does not already have a Collider2D component, then a BoxCollider2D is added.
* @param _visible Setting this to true makes the button visible, unless overridden by property settings
* @param _buttonAction An Action delegate method to call when the player clicks on the button
*/
public static void MakeButton(SpriteRenderer _spriteRenderer, bool _autoDisplay, Action _buttonAction)
public void Show(bool _visible, Action _buttonAction)
{
if (_spriteRenderer == null)
SpriteRenderer spriteRenderer = renderer as SpriteRenderer;
if (spriteRenderer == null)
{
Debug.LogError("Sprite renderer must not be null");
return;
}
// Remove any previous button component that was added
Button oldButton = _spriteRenderer.gameObject.GetComponent<Button>();
if (oldButton != null)
// Add a BoxCollider2d if none currently exists
if (collider2D == null)
{
Destroy(oldButton);
gameObject.AddComponent<BoxCollider2D>();
}
// Add a BoxCollider2d if none currently exists
if (_spriteRenderer.gameObject.GetComponent<Collider2D>() == null)
showButton = _visible;
buttonAction = _buttonAction;
if (_visible)
{
targetAlpha = 1f;
}
else
{
_spriteRenderer.gameObject.AddComponent<BoxCollider2D>();
targetAlpha = 0f;
}
Button button = _spriteRenderer.gameObject.AddComponent<Button>();
button.spriteRenderer = _spriteRenderer;
button.autoDisplay = _autoDisplay;
button.buttonAction = _buttonAction;
UpdateTargetAlpha();
}
public void SetAlpha(float alpha)
{
SpriteRenderer spriteRenderer = renderer as SpriteRenderer;
Color color = spriteRenderer.color;
color.a = alpha;
spriteRenderer.color = color;
}
void UpdateTargetAlpha()
{
// Automatically display button when game is in idle state (not displaying story text/options or waiting)
if (autoHide)
{
if (showButton &&
Game.GetInstance().IsGameIdle())
{
targetAlpha = 1f;
if (_autoDisplay)
}
else
{
targetAlpha = 0f;
}
}
// Hide the button if the specified flag has been set to true
if (hideOnFlag.Length > 0 &&
Game.GetInstance().state.GetFlag(hideOnFlag))
{
// Use the current global alpha value for auto buttons
Color color = _spriteRenderer.color;
color.a = Game.GetInstance().buttonController.autoButtonAlpha;
_spriteRenderer.color = color;
targetAlpha = 0f;
}
}
void Update()
{
UpdateTargetAlpha();
SpriteRenderer spriteRenderer = renderer as SpriteRenderer;
Color color = spriteRenderer.color;
float fadeSpeed = (1f / Game.GetInstance().buttonFadeDuration);
color.a = Mathf.MoveTowards(color.a, targetAlpha, Time.deltaTime * fadeSpeed);
spriteRenderer.color = color;
}
void OnMouseUpAsButton()
{
SpriteRenderer spriteRenderer = renderer as SpriteRenderer;
// Ignore button press if sprite is not fully visible
if (spriteRenderer.color.a != 1f)
{

59
Assets/Fungus/Scripts/ButtonController.cs

@ -1,59 +0,0 @@
using UnityEngine;
using System.Collections;
namespace Fungus
{
public class ButtonController : MonoBehaviour
{
public float autoButtonAlpha;
void Update()
{
// Poll if active page has no content and game is not waiting
bool showAutoButtons = false;
Page page = Game.GetInstance().activePage;
if (page != null &&
page.mode == Page.Mode.Idle &&
!Game.GetInstance().waiting)
{
showAutoButtons = true;
}
float targetAlpha = 0f;
if (showAutoButtons)
{
targetAlpha = 1f;
}
float fadeSpeed = (1f / Game.GetInstance().buttonFadeDuration);
autoButtonAlpha = Mathf.MoveTowards(autoButtonAlpha, targetAlpha, Time.deltaTime * fadeSpeed);
SetAutoButtonAlpha(autoButtonAlpha);
}
void SetAutoButtonAlpha(float alpha)
{
Room room = Game.GetInstance().activeRoom;
if (room == null)
{
return;
}
Button[] buttons = room.gameObject.GetComponentsInChildren<Button>();
if (buttons == null)
{
return;
}
foreach (Button button in buttons)
{
if (button.autoDisplay)
{
Color color = button.spriteRenderer.color;
color.a = alpha;
button.spriteRenderer.color = color;
}
}
}
}
}

8
Assets/Fungus/Scripts/ButtonController.cs.meta

@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: b5ce8326f58fb4caeabc99cf7f95fb0e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

55
Assets/Fungus/Scripts/Commands.cs

@ -471,32 +471,32 @@ namespace Fungus
}
/**
* Makes a sprite behave as a clickable button
* Display a button and set the method to be called when player clicks.
*/
public class AddButtonCommand : CommandQueue.Command
public class ShowButtonCommand : CommandQueue.Command
{
SpriteRenderer spriteRenderer;
bool autoDisplay;
Button button;
bool visible;
Action buttonAction;
public AddButtonCommand(SpriteRenderer _spriteRenderer,
Action _buttonAction,
bool _autoDisplay)
public ShowButtonCommand(Button _button,
bool _visible,
Action _buttonAction)
{
if (_spriteRenderer == null)
if (_button == null)
{
Debug.LogError("Sprite renderer must not be null.");
Debug.LogError("Button must not be null.");
return;
}
spriteRenderer = _spriteRenderer;
autoDisplay = _autoDisplay;
button = _button;
visible = _visible;
buttonAction = _buttonAction;
}
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
Button.MakeButton(spriteRenderer, autoDisplay, buttonAction);
button.Show(visible, buttonAction);
if (onComplete != null)
{
@ -505,37 +505,6 @@ namespace Fungus
}
}
/**
* Makes a sprite stop behaving as a clickable button.
*/
public class RemoveButtonCommand : CommandQueue.Command
{
SpriteRenderer spriteRenderer;
public RemoveButtonCommand(SpriteRenderer _spriteRenderer)
{
if (_spriteRenderer == null)
{
Debug.LogError("Sprite renderer must not be null.");
return;
}
spriteRenderer = _spriteRenderer;
}
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
// Remove the button component
Button button = spriteRenderer.gameObject.GetComponent<Button>();
GameObject.Destroy(button);
if (onComplete != null)
{
onComplete();
}
}
}
/**
* Pans the camera to a view over a period of time.
*/

27
Assets/Fungus/Scripts/Game.cs

@ -90,9 +90,6 @@ namespace Fungus
[HideInInspector]
public CameraController cameraController;
[HideInInspector]
public ButtonController buttonController;
/**
* True when executing a Wait() or WaitForTap() command
*/
@ -120,7 +117,6 @@ namespace Fungus
// Add components for additional game functionality
commandQueue = gameObject.AddComponent<CommandQueue>();
cameraController = gameObject.AddComponent<CameraController>();
buttonController = gameObject.AddComponent<ButtonController>();
AudioSource audioSource = gameObject.AddComponent<AudioSource>();
audioSource.playOnAwake = false;
@ -158,9 +154,6 @@ namespace Fungus
// Calling private method on Room to hide implementation
activeRoom.gameObject.SendMessage("Enter");
// Hide all auto buttons when entering room
buttonController.autoButtonAlpha = 0f;
// Fade in screen
cameraController.Fade(1f, roomFadeDuration / 2f, null);
});
@ -177,5 +170,25 @@ namespace Fungus
}
audio.PlayOneShot(buttonClickClip);
}
/**
* Returns true if the game is in an idle state.
* The game is in and idle state if the active page is not currently displaying story text/options, and no Wait command is in progress
*/
public bool IsGameIdle()
{
if (waiting)
{
return false;
}
if (activePage == null ||
activePage.mode == Page.Mode.Idle)
{
return true;
}
return false;
}
}
}

53
Assets/Fungus/Scripts/GameController.cs

@ -212,7 +212,18 @@ namespace Fungus
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new Command.SetFlagCommand(key, value));
}
/**
* Sets a boolean flag value to true.
* This method returns immediately but it queues an asynchronous command for later execution.
* @param key The name of the flag
*/
public void SetFlag(string key)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new Command.SetFlagCommand(key, true));
}
/**
* Gets the current state of a flag.
* Flag values are set using SetFlag().
@ -356,7 +367,7 @@ namespace Fungus
}
/**
* Makes a sprite behave as a clickable button.
* Displays a button and sets
* Automatically adds a Button component to the object to respond to player input.
* If no Collider2D already exists on the object, then a BoxCollider2D is automatically added.
* Use RemoveButton() to make a sprite non-clickable again.
@ -364,25 +375,10 @@ namespace Fungus
* @param spriteRenderer The sprite to be made clickable
* @param buttonAction The Action delegate method to be called when the player clicks on the button
*/
public void AddButton(SpriteRenderer spriteRenderer, Action buttonAction)
public void ShowButton(Button button, Action buttonAction)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new Command.AddButtonCommand(spriteRenderer, buttonAction, false));
}
/**
* Makes a sprite behave as a clickable button.
* Same behaviour as AddButton(), except the button will be automatically hidden/shown by the game depending on the context.
* All auto buttons are automatically displayed when there is no page content and the player taps on the screen.
* If the player does not interact for a period, then all auto buttons are hidden again.
* This method returns immediately but it queues an asynchronous command for later execution.
* @param spriteRenderer The sprite to be made clickable
* @param buttonAction The Action delegate method to be called when the player clicks on the button
*/
public void AddAutoButton(SpriteRenderer spriteRenderer, Action buttonAction)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new Command.AddButtonCommand(spriteRenderer, buttonAction, true));
commandQueue.AddCommand(new Command.ShowButtonCommand(button, true, buttonAction));
}
/**
@ -391,27 +387,12 @@ namespace Fungus
* This method returns immediately but it queues an asynchronous command for later execution.
* @param spriteRenderer The sprite to be made non-clickable
*/
public void RemoveButton(SpriteRenderer spriteRenderer)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new Command.RemoveButtonCommand(spriteRenderer));
}
/**
* Makes a sprite stop behaving as a clickable button and fades out the button sprite.
* The fade duration is specified in Game.buttonFadeDuration
* This method returns immediately but it queues an asynchronous command for later execution.
* @param spriteRenderer The sprite to be made non-clickable
*/
public void RemoveAndFadeButton(SpriteRenderer spriteRenderer)
public void HideButton(Button button)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new Command.RemoveButtonCommand(spriteRenderer));
FadeSprite(spriteRenderer, 0f, Game.GetInstance().buttonFadeDuration);
commandQueue.AddCommand(new Command.ShowButtonCommand(button, false, null));
}
/**
* Sets an animator trigger to change the animation state for an animated sprite.
* This is the primary method of controlling Unity animations from a Fungus command sequence.

8
Assets/Fungus/Scripts/Room.cs

@ -138,6 +138,14 @@ namespace Fungus
// It is allowed for a room to not have any pages. In this case game.activePage will be null
game.activePage = gameObject.GetComponentInChildren<Page>();
// Hide all buttons in the room before entering
// Buttons must always be made visible using a ShowButton() command
Button[] buttons = game.activeRoom.GetComponentsInChildren<Button>();
foreach (Button button in buttons)
{
button.SetAlpha(0f);
}
// Rooms may have multiple child views and page. It is the responsibility of the client
// room script to set the appropriate view & page in its OnEnter method.

BIN
Assets/Fungus/Sprites/Button.psd

Binary file not shown.

45
Assets/Fungus/Sprites/Button.psd.meta

@ -0,0 +1,45 @@
fileFormatVersion: 2
guid: 83e4bd04047eb419fbb6b205dd1f2f91
TextureImporter:
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: .25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: -1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: .5, y: .5}
spritePixelsToUnits: 100
alphaIsTransparency: 1
textureType: 8
buildTargetSettings: []
spriteSheet:
sprites: []
spritePackingTag:
userData:

BIN
Assets/FungusExample/Scenes/Example.unity

Binary file not shown.

21
Assets/FungusExample/Scripts/ButtonRoom.cs

@ -8,18 +8,18 @@ public class ButtonRoom : Room
public AudioClip effectClip;
public SpriteRenderer homeSprite;
public SpriteRenderer musicSprite;
public SpriteRenderer questionSprite;
public Button homeButton;
public Button soundButton;
public Button questionButton;
void OnEnter()
{
// Normal button, always visible
AddButton(homeSprite, OnHomeClicked);
ShowButton(homeButton, OnHomeClicked);
// Auto buttons, hidden when story/options are being displayed
AddAutoButton(musicSprite, OnMusicClicked);
AddAutoButton(questionSprite, OnQuestionClicked);
// Auto hide buttons (hidden when story/options are being displayed)
ShowButton(soundButton, OnMusicClicked);
ShowButton(questionButton, OnQuestionClicked);
// NOTE: Add auto buttons before first Say() command to ensure they start hidden
@ -42,13 +42,14 @@ public class ButtonRoom : Room
{
PlaySound(effectClip);
// Hide this button once the player clicks it
RemoveAndFadeButton(musicSprite);
// The music button has been set to hide if this flag is set
SetFlag("PlayedSound");
}
void OnQuestionClicked()
{
// All Auto Buttons are automatically hidden as soon as the page has more content to show
// Set the Button.autoHide property to automatically hide buttons when displaying page text/options or waiting
// The Question and Sound buttons have the Auto Hide property set, but the Home button does not.
Say("What book was he reading?");
Say("Sadly we will never know for sure.");

9
Assets/FungusExample/Scripts/SpriteRoom.cs

@ -22,15 +22,8 @@ public class SpriteRoom : Room
SetAnimatorTrigger(blueAlienAnim, "StartBlueWalk");
Say("Blue Alien starts to dance.");
Say("Tap on Blue Alien to stop him dancing.");
AddButton(blueAlienSprite, StopDancing);
}
// This method is called from the Button component on the BlueAlien object
void StopDancing()
{
RemoveButton(blueAlienSprite);
Wait(4);
SetAnimatorTrigger(blueAlienAnim, "Stop");

Loading…
Cancel
Save