greenhouse
a creative coding toolkit for spatial interfaces

Displacement Events

Handling Displacement events generated from hantenna devices. For more of an overview on input handling and what a Displacement event is, check out the learning pages on handling user input.

  • DisplacementAppear ()
  • DisplacementVanish ()
  • DisplacementMove ()
  • LocOffset ()
  • LinearOffset ()
  • EstabLoc ()

Example

// This application grids up a set of images and allows the user to navigate
// the grid by using their palm facing out, fingers together, thumb out.
// Imagine giving someone a high five. After the gesture has been dropped, if
// the gesture is not made again after a second, the grid will settle on the
// centermost image.

#include "Greenhouse.h"

class ImageGrid : public Thing
{
private:
  int64 num_cols, num_rows;
  int64 cur_col, cur_row;
  float64 vert_offset, horz_offset;
  float64 max_vert_offset, max_horz_offset;
  bool settled;

public:
  ImageGrid () : Thing ()
    { num_rows = num_cols = 1;
      cur_row = cur_col = 0;
      vert_offset = 1.02 * Feld () -> Height ();
      horz_offset = Feld () -> Width () + 0.02 * Feld () -> Height ();
      max_horz_offset = horz_offset;
      max_vert_offset= vert_offset;
      settled = true;

      SlapOnFeld ();
    }

  void AppendImage (Image *img)
    { img -> SetTranslation (cur_row * vert_offset * Up ()
                             + cur_col * horz_offset * Over ());
      img -> SetHeightUniformly(Feld () -> Height ());
      AppendKid(img);

      if (cur_row == num_rows)
        num_rows++;
      if (cur_col == num_cols)
        num_cols++;

      max_horz_offset = horz_offset * (num_cols - 1);
      max_vert_offset = horz_offset * (num_cols - 1);

      if (cur_col == cur_row)
        { cur_col = num_cols;
          cur_row = 0;
        }
      else if (cur_row < (num_rows-1))
        cur_row++;
      else if (cur_col < cur_row)
        cur_col++;
      else if (cur_row == (num_rows-1))
        { cur_row = num_rows;
          cur_col = 0;
        }
    }

  void CenterOnClosestKid ()
    { Image *closestKid = NthKid <Image> (0);
      if (! closestKid)
        return;

      Vect cent = Feld () -> Loc ();

      float64 closest_dist = cent . DistFrom (closestKid -> Loc ());
      for (int i = 1; i < KidCount(); i++)
        { Image *kid = NthKid <Image> (i);
          if (kid)
            { float64 dist = cent . DistFrom (kid -> Loc ());
              if (dist < closest_dist)
                { closest_dist = dist;
                  closestKid = kid;
                }
            }
        }

      SetTranslation (Feld () -> Loc () - closestKid -> Translation ());
    }

  void Travail ()
    { if (CurTime() > 1.0 && ! settled)
        { CenterOnClosestKid ();
          settled = true;
        }
    }

  void DisplacementAppear (DisplacementEvent *e)
    { if (IsHeedless ())
        { Heed (e);
          INFORM ("Pose began at: " + ToStr (e -> EstabLoc ()));
        }
    }

  void DisplacementMove (DisplacementEvent *e)
    { if (IsHeedless ())
        { Heed (e);
          INFORM ("Pose began at: " + ToStr (e -> EstabLoc ()));
        }
      if (IsHeeding (e))
        { IncTranslationHard (4.0 * e -> CurLinearDelta ());
          Vect total_disp = e -> CumuLinearOffset ();
          INFORM ("Total Displacement: " + ToStr (total_disp));
          ZeroTime();
          settled = false;
        }
    }

  void DisplacementVanish (DisplacementEvent *e)
    { if (IsHeeding (e))
        StopHeeding ();
    }
};


void Setup ()
{ ImageGrid *tg = new ImageGrid ();

  for (int i = 1; i <= 6; i++)
    { Image *img = new Image ("images/" + ToStr (i) + ".jpg");
      img -> SetName (ToStr (i) + ".jpg");
      tg -> AppendImage (img);
    }

  tg -> SlapOnFeld ();
  tg -> TranslationAnimateQuadratic(1.0);

  DoNotRegisterForDefaultEvents ();
  RegisterDisplacement("pushback", OpenPalmFingersTogetherPose);
}