Home > Devices > Fire Phone

Creating a Custom Control using ZSceneView

Introduction

The Fire Phone SDK provides many stock controls for your app. If your app needs a 3D control not provided by Euclid, you can create your own custom control. This page provides instructions on creating your own custom 3D control using an example of the "star rating" system commonly seen on user review pages.

The sample custom control described on this page is a "star rating" custom control. (The star is an artist-created graphic mesh, so a designer must create the 3D star asset using a 3D visual tool. See Using the Custom Control Authoring Tools for Fire Phone for information on creating custom assets.) With this control, a user can "rate" an item with a score of 1-5 stars by touching a star. You can implement this control by creating a single 5-star object that has five different rating "states". The following image shows an example of this control with three stars filled:

Process Overview

Most custom controls wrap a behavior around a specific visual presentation. For most Euclid 3D widgets, creating a custom control is a two-step process:

  1. Incorporate your 3D assets into your layout and code.
  2. Hook up the input events that trigger the appropriate animations and state changes.

Euclid provides a ZSceneView widget that simplifies these steps for basic widgets. One approach is to subclass ZSceneView to drive an artist-provided model of 5 stars (one object, five states).

In the implementation described in this example, the visual presentation of the custom control is fully controlled by the graphic artist and can be easily customized without writing any new code. Additionally, the actual quantity of code that must be written is quite small, with the tradeoff being that the designer has to create the state machine and correctly hook up the animations.

Creating a Control with Multiple States Using ZSceneView

The example described in this section uses the scenario of a single "star rating" object that has five states. With the help of a graphic artist, you can create this control using the following process:

  1. The graphic artist draws the entire collection of five stars in Maya as a single object and then defines a series of valid states:
    • "One star filled"
    • "Two stars filled"
    • "Three stars filled"
    • "Four stars filled"
    • "Five stars filled"
  2. The artist creates transition animations to connect the states. The artist has the following options for creating the transition animations:
    • The artist can create one transition animation for each pair of "M star filled" to "N stars filled".
    • The artist can create one animation that sequentially fills in the stars, one that empties the stars in reverse order, and a state machine matrix that plays the correct animation segment for each state transition.
  3. The ZSceneView object reads the mesh file and the artist-generated states and state transitions. You can then use the setGoalState() method to specify your goal end state. The ZSceneView object selects and runs the correct transition animations.

In this code sample, the programmer looks for the initial touch event in the mesh object, calculates which star was touched, and switches the state of the ZSceneView to display this state. The ZSceneView runs the appropriate animation:

public class StarRating extends ZSceneView {
    private int mRating;
    private final static String[] sStates = {"one star filled", "two stars filled",
       "three stars filled", "four stars filled", "five stars filled"};

    public void initialize() {
      getDelegate().setScene("star_rating.scene");
    }

    public boolean onTouchEvent(MotionEvent event) {
      if (event.getAction() == ACTION_DOWN) {
        final float x = event.getX();
        final int star_hit = (int) ((x * 5f) / this.getWidth()) + 1;
       setRating(star_hit);
      }
      return true;
    }

    public int getRating() {
      return mRating;
    }

    public void setRating(int rating) {
      if (rating != mRating && rating >= 1 && rating <= 5) {
        mRating = rating;       
        ZSceneTree tree = getDelegate().getSceneTree();
        ZStateMachine sm = tree.getStateMachine();
        sm.setGoalState(sStates[mRating-1]);
       }
    }
  }