We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpOther Libraries › ControlP5: Sprite buttons, lock in a sprite state
Page Index Toggle Pages: 1
ControlP5: Sprite buttons, lock in a sprite state (Read 1454 times)
ControlP5: Sprite buttons, lock in a sprite state
Feb 11th, 2010, 8:20am
 
Hi, I'm wondering if it's possible to 'lock in' the state for a given sprite used for a button w/ CP5.  

Basically, the button already has three states in the sprite (as required by the cp5 library, afaict), and the on-click state represents both what I want it to look like _when clicked_ and _after clicked_.  

For an idea of what I'm trying to achieve: As I have created groups of controls, I have a set of controls that allow you to switch between them.  The idea is that when you hit the control that brings a particular group forward, its control should show as 'selected' for as long as the group is displayed.  I can handle the display/hide, etc. part, but I can't seem to find a way to lock in a particular state -- namely, sprite.setState(2) results in no changes whatsoever in the control handler.

Alternatively, is it possible to use simple images for buttons?  I know that I could change the sprite after being clicked to one that has all states as the 'clicked' state (to achieve the above goal), but the problem is that I'm now using 3x the memory I need!  (I only have two states, but two sprites would require a total of six states.)

Any advice would be greatly appreciated!

!c
Re: ControlP5: Sprite buttons, lock in a sprite state
Reply #1 - Feb 11th, 2010, 9:46am
 
If you are using the same image/sprite for multiple states, surely there is only one actual object (copy) of each of these.

Are you certain that there is a memory issue here? Unless this is for some small embedded system, is the overhead of a couple of button images a problem?

Having said that, I'm not familiar with the library, and what you're describing sounds like a hack, so maybe there is another way.
Re: ControlP5: Sprite buttons, lock in a sprite state
Reply #2 - Feb 14th, 2010, 2:20pm
 
subpixel wrote on Feb 11th, 2010, 9:46am:
If you are using the same image/sprite for multiple states, surely there is only one actual object (copy) of each of these.

Are you certain that there is a memory issue here Unless this is for some small embedded system, is the overhead of a couple of button images a problem

Having said that, I'm not familiar with the library, and what you're describing sounds like a hack, so maybe there is another way.


Alas, it is not a hack - just trying to control the behavior of the library such that I can use it efficiently, and understand how one is supposed to achieve such behavior without changing it.  (Yes, I'm targeting other platforms as well as desktop machines, PDAs, etc. - A couple of buttons duplicated is fine, until you consider I have dozens, fifty or more that will end up this way - uses too much memory and way too much work to prep sprites and maintain them.)

The problem, quite succinctly, is that CP5 buttons can only use CP5 sprites, AFAICT.  And, CP5 sprites require exactly 3 states, whether or not you only want two, or one.  CP5 also does not seem to support normal images for buttons, just CP5 sprites (see previous statement).

Therefore, to get by for now, I've hacked up the CP5 ControllerSprite class to support fewer than 3 states in sprites, and forcing a given state (no matter what else happens), so I can indicate that a button should stay lit until another button of a specific list is hit.

I just hate having to modify the lib, as it means I will have to distribute a modified version of the lib, and if anyone wants to re-build in processing, that means they'll also need the JDK to compile the changes.

!c
Re: ControlP5: Sprite buttons, lock in a sprite state
Reply #3 - Feb 14th, 2010, 7:29pm
 
hi, would be happy to improve and implement what you are describing. if the code and modifications are too long and too specific for a post here, send me a pm or email. best, andreas
Re: ControlP5: Sprite buttons, lock in a sprite state
Reply #4 - Feb 15th, 2010, 9:22am
 
Andreas, that would be great!

Here's my modified form of your ControllerSprite.java, I added a new constructor, and a couple of methods (one of which allows setting total sprite states w/o using the new constructor, one to force into a given display state [this is used at display update time only, does not affect other activities], and one to count the total number of states a sprite has).

The only oddity is that I thought it would be nice to specify the count of states by their actual count, rather than index, so one would say there are 2 states, but lock into state #1 to get the second position.

Code:

package controlP5;

import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PVector;

public class ControllerSprite {

// cc - andreas - I had to remove comment so I could post to BB

protected PImage sprite;
protected PImage display;
protected PImage mask;
protected int offsetX;
protected int offsetY;
protected int width;
protected int height;
protected int wh;
protected boolean isMask;
protected int _myState;
// cc - added to support forcing of state
// and count of total states
protected int _forceState = 0;
// default value (3 total states 0-2)
protected int _totalStates = 2;


public ControllerSprite(ControlP5 theControlP5,
 PImage theImage,
 int theWidth,
 int theHeight) {
sprite = theImage;
width = theWidth;
height = theHeight;
wh = width*height;
_myState = 0;

display = new PImage(theWidth, theHeight);
display = theControlP5.papplet.createImage(theWidth, theHeight,PApplet.RGB);
update();

}

public ControllerSprite(ControlP5 theControlP5,
 PImage theImage,
 int theWidth,
 int theHeight,
int theStates) {
sprite = theImage;
width = theWidth;
height = theHeight;
wh = width*height;
_myState = 0;

// cc - added to support a specified # of states
// specify total states, not index - e.g.:
// two total states arg should = 2, even though
// max state index is 1.

theStates--;

// cc - make sure we have at least one state
_totalStates = (theStates >= 0) ? theStates : 0;

display = new PImage(theWidth, theHeight);
display = theControlP5.papplet.createImage(theWidth, theHeight,PApplet.RGB);
update();

}

public void draw(
 PApplet theApplet) {
theApplet.pushStyle();
theApplet.imageMode(PApplet.CORNER);
if(isMask) {
display.mask(mask);
}
theApplet.image(display, 0, 0);
theApplet.popStyle();
}

public void update() {

// cc - added to limit to a given # of
// states, also force state if forced state
// is greater than 0

int state = _forceState > 0 ? _forceState : _myState;

if( state > _totalStates )
state = _totalStates;

display.loadPixels();
System.arraycopy(sprite.pixels,wh * state,display.pixels,0,wh);
display.updatePixels();
}

// cc - added to support a specified # of states
// specify total states, not index - e.g.:
// two total states arg should = 2, even though
// max state index is 1.

public void setTotalStates(int count) {
// reduce index value
count--;
// cc - make sure we have at least one state
_totalStates = (count >= 0) ? count : 0;
}

// cc - added, to force state

public void setForceState( int state ) {
_forceState = state;
offsetY = height * _forceState;
update();

}

// cc - added to query count of states

public int getStateCount() {
return _totalStates;
}

public void setOffset(
 int theX,
 int theY) {
offsetX = theX;
offsetY = theY;
update();
}

public void setState(int theState) {
if(theState!=_myState) {
_myState = theState;
offsetY = height * _myState;
update();
}
}

public int getState() {
return _myState;
}

public int width() {
return width;
}

public int height() {
return height;
}

public void setMask(
 PImage theImage) {
mask = theImage;
}

public void enableMask() {
isMask = true;
}

public void disableMask() {
isMask = true;
}

}


And here's an example of how I'm using it:

Code:


...

 if( sprite_img.exists() ) {
   ControllerSprite sprite = new ControllerSprite(panel,loadImage(img_path),w,h,2);
   b.setSprite(sprite);
   sprite_hm.put(b_name, sprite);
 }

...



void show_panel(String grp_name, String spr_name) {

 // look for a sprite that would represent the current button being
 // displayed
ControllerSprite sprite = (ControllerSprite) get_sprite(current_spr);

 // get the group that is currently being displayed
ControlGroup this_grp  = (ControlGroup) get_group(current_grp);

if( ! grp_name.equals(current_grp) ) {

   // let go of the clicked status
   // for a given nav menu button, if
   // currently clicked - only if the
   // supplied sprite is valid

  if( ! spr_name.equals("") ) {
   
// set previous sprite to no longer be
// forced into a state...

    if( sprite != null )
sprite.setForceState(0);

// set new sprite (if available) as
// pressed.

    sprite = (ControllerSprite) get_sprite(spr_name);

// force into 'pressed' state
    if( sprite != null )
sprite.setForceState(1);
 
    current_spr = spr_name;
  }
 
    // hide the previous group of controls
   
  if( this_grp != null )
    this_grp.hide();
 
    // show the requested view
   
  this_grp = (ControlGroup) get_group(grp_name);
 
  if( this_grp != null )
    this_grp.show();
 
    // if provided, set the current sprite name argument
    // locked into position #1 (mouse-over/clicked)
   
  current_grp = grp_name;
}


}


Thanks again,
Chris
Page Index Toggle Pages: 1