SleepIsDeath/gameSource/StateObjectDisplay.cpp

480 lines
12 KiB
C++

#include "StateObjectDisplay.h"
#include "common.h"
#include "SpriteResource.h"
#include "TilePicker.h"
#include "minorGems/graphics/openGL/gui/TextGL.h"
#include "minorGems/util/stringUtils.h"
extern TilePicker *mainTilePicker;
static clickMask blankMask;
StateObjectDisplay::StateObjectDisplay( int inAnchorX, int inAnchorY )
: GUIComponentGL( inAnchorX, inAnchorY,
G * P, G * P ),
mLastPixelClickX( 0 ), mLastPixelClickY( 0 ),
mLastGridClickX( 0 ), mLastGridClickY( 0 ),
mLastActionRelease( false ),
mLastActionPress( false ),
mMouseHover( false ),
mLastHoverX( 0 ), mLastHoverY( 0 ),
mShowSelected( true ),
mShowGrid( true ),
mUseTrans( true ),
mLastSelected( -2 ),
mBlinkCycle( 0 ) {
for( int y=0; y<P; y++ ) {
for( int x=0; x<P; x++ ) {
blankMask.opaque[y][x] = false;
}
}
mZoomFactor = 1.0;
}
StateObjectDisplay::~StateObjectDisplay() {
int numSprites = mObjectSprites.size();
for( int s=0; s<numSprites; s++ ) {
delete *( mObjectSprites.getElement( s ) );
delete *( mObjectSpriteHighlights.getElement( s ) );
}
}
void StateObjectDisplay::setStateObject( StateObject inStateObject,
char inUseTrans ) {
mUseTrans = inUseTrans;
mStateObject = inStateObject;
// clear old
int numSprites = mObjectSprites.size();
int i;
for( i=0; i<numSprites; i++ ) {
delete *( mObjectSprites.getElement( i ) );
delete *( mObjectSpriteHighlights.getElement( i ) );
}
mObjectSprites.deleteAll();
mObjectSpriteHighlights.deleteAll();
mObjectSpritePositions.deleteAll();
mObjectSpriteFades.deleteAll();
mObjectSpriteGlows.deleteAll();
mObjectMasks.deleteAll();
int centerScreenPosX = (int)( P * (G/2) / mZoomFactor );
int centerScreenPosY = (int)( P * (G/2 - mZoomFactor) / mZoomFactor );
// add new
numSprites = mStateObject.getNumLayers();
for( int s=0; s<numSprites; s++ ) {
SpriteResource resource( mStateObject.getLayerSprite( s ) );
mObjectSprites.push_back( resource.getSprite( mUseTrans ) );
mObjectSpriteHighlights.push_back( resource.getHighlightSprite() );
intPair p = mStateObject.getLayerOffset( s );
p.x += centerScreenPosX;
p.y += centerScreenPosY;
mObjectSpritePositions.push_back( p );
mObjectSpriteFades.push_back( mStateObject.getLayerTrans( s ) /
255.0f );
mObjectSpriteGlows.push_back( mStateObject.getLayerGlow( s ) );
clickMask mask;
for( int y=0; y<P; y++ ) {
for( int x=0; x<P; x++ ) {
mask.opaque[y][x] = ! resource.getTrans( x, y );
}
}
mObjectMasks.push_back( mask );
}
// last, add anchor sprite for this object, on top
mObjectSprites.push_back( new Sprite( "anchor.tga", true ) );
// no special highlight for anchor
mObjectSpriteHighlights.push_back( new Sprite( "anchor.tga", true ) );
intPair p = {0,0};
p.x += centerScreenPosX;
p.y += centerScreenPosY;
mObjectSpritePositions.push_back( p );
mObjectSpriteFades.push_back( 1.0f );
mObjectSpriteGlows.push_back( false );
mObjectMasks.push_back( blankMask );
}
void StateObjectDisplay::updateSpritePositions( StateObject inStateObject ) {
// don't need to touch masks
mStateObject = inStateObject;
int centerScreenPosX = (int)( P * (G/2) / mZoomFactor );
int centerScreenPosY = (int)( P * (G/2 - mZoomFactor) / mZoomFactor );
int numSprites = mStateObject.getNumLayers();
for( int s=0; s<numSprites; s++ ) {
intPair p = mStateObject.getLayerOffset( s );
p.x += centerScreenPosX;
p.y += centerScreenPosY;
*( mObjectSpritePositions.getElement( s ) ) = p;
*( mObjectSpriteFades.getElement( s ) ) =
mStateObject.getLayerTrans( s ) / 255.0f;
*( mObjectSpriteGlows.getElement( s ) ) =
mStateObject.getLayerGlow( s );
}
// anchor
intPair p = {0,0};
p.x += centerScreenPosX;
p.y += centerScreenPosY;
*( mObjectSpritePositions.getElement( numSprites ) ) = p;
}
void StateObjectDisplay::showGrid( char inShow ) {
mShowGrid = inShow;
}
double StateObjectDisplay::getZoom() {
return mZoomFactor;
}
void StateObjectDisplay::setZoom( double inZoom ) {
mZoomFactor = inZoom;
updateSpritePositions( mStateObject );
}
void StateObjectDisplay::fireRedraw() {
int gridLimit = (int)( G / mZoomFactor );
int selected = mStateObject.mSelectedLayer;
if( mLastSelected != selected || ! mShowGrid ) {
// reset
mBlinkCycle = 0;
mLastSelected = selected;
}
else {
mBlinkCycle ++;
}
if( mUseTrans ) {
// background of selected tile
Tile tile = (Tile)( mainTilePicker->getBackgroundTile() );
Sprite *tileSprite = tile.getSprite();
for( int y=0; y<gridLimit; y++ ) {
for( int x=0; x<gridLimit; x++ ) {
Vector3D pos( mAnchorX + ( x * P + P/2 ) * mZoomFactor,
mAnchorY + (y * P + P/2) * mZoomFactor,
0 );
tileSprite->draw( 0, 0, &pos, mZoomFactor );
}
}
delete tileSprite;
}
// now draw all sprites
int numSprites = mObjectSprites.size();
//printf( "Drawing %d sprites, %d selected\n", numSprites, selected );
for( int s=0; s<numSprites; s++ ) {
Sprite *sprite = *( mObjectSprites.getElement( s ) );
intPair pixelPos = *( mObjectSpritePositions.getElement( s ) );
float fadeFactor = *( mObjectSpriteFades.getElement( s ) );
Vector3D pos( mAnchorX + mZoomFactor * (pixelPos.x + P/2),
mAnchorY + mZoomFactor * (pixelPos.y + P/2), 0 );
char drawIt = true;
Color c( 1, 1, 1, 1 );
char isAnchor = false;
if( s == numSprites - 1 ) {
// an anchor
isAnchor = true;
fadeFactor *= 0.25;
if( !mShowGrid ) {
// hide anchors
drawIt = false;
}
}
/*
if( ! isAnchor &&
mShowGrid &&
s == selected ) {
// make it blink
double blinkFadeFactor = 0.35 * cos( mBlinkCycle / 3.0 ) + 0.65;
fadeFactor *= blinkFadeFactor;
}
*/
// skip sprites that are way out of bounds (due to zooming)
if( pos.mX < mAnchorX || pos.mX > mAnchorX + mWidth
||
pos.mY < mAnchorY || pos.mY > mAnchorY + mHeight ) {
drawIt = false;
}
if( drawIt ) {
char glow = *( mObjectSpriteGlows.getElement( s ) );
if( glow ) {
// brighten only
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
}
sprite->draw( 0, 0, &pos, mZoomFactor, fadeFactor, &c );
if( glow ) {
// back to normal blend
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
if( ! isAnchor &&
mShowGrid &&
mShowSelected &&
s == selected ) {
// blinking highlight on top
double blinkFadeFactor =
0.25 * cos( mBlinkCycle / 3.0 ) + 0.25;
Sprite *highlight =
*( mObjectSpriteHighlights.getElement( s ) );
highlight->draw( 0, 0, &pos,
mZoomFactor,
blinkFadeFactor, &c );
}
}
}
if( mShowGrid ) {
//grid lines
glColor4f( 1, 1, 1, 0.25f );
glBegin( GL_LINES ); {
for( int x=0; x<gridLimit+1; x++ ) {
glVertex2d( mAnchorX + x * P * mZoomFactor, mAnchorY );
glVertex2d( mAnchorX + x * P * mZoomFactor,
mAnchorY + mHeight );
}
for( int y=0; y<gridLimit+1; y++ ) {
glVertex2d( mAnchorX, mAnchorY + y * P * mZoomFactor );
glVertex2d( mAnchorX + mWidth,
mAnchorY + y * P * mZoomFactor );
}
}
glEnd();
}
/*
// thin white border, partly transparent
glColor4f( 1, 1, 1, 0.25f );
glBegin( GL_LINE_LOOP ); {
glVertex2d( mAnchorX, mAnchorY );
glVertex2d( mAnchorX + mWidth, mAnchorY );
glVertex2d( mAnchorX + mWidth, mAnchorY + mHeight );
glVertex2d( mAnchorX, mAnchorY + mHeight );
}
glEnd();
*/
}
void StateObjectDisplay::setLastMouse( double inX, double inY ) {
double tempX = ( inX - mAnchorX ) - P * (G/2);
double tempY = ( inY - mAnchorY ) - P * (G/2 - mZoomFactor);
mLastPixelClickX = (int)( floor( tempX / mZoomFactor ) );
mLastPixelClickY = (int)( floor( tempY / mZoomFactor ) );
mLastPixelClickX -= P/2;
mLastPixelClickY -= P/2;
mLastHoverX = mLastPixelClickX;
mLastHoverY = mLastPixelClickY;
mLastGridClickX = (int)( mLastPixelClickX / P );
mLastGridClickY = (int)( mLastPixelClickY / P );
}
void StateObjectDisplay::mouseDragged( double inX, double inY ) {
mLastActionRelease = false;
mLastActionPress = false;
if( isEnabled() && isInside( inX, inY ) ) {
setLastMouse( inX, inY );
fireActionPerformed( this );
}
}
void StateObjectDisplay::mousePressed( double inX, double inY ) {
mLastActionRelease = false;
mLastActionPress = true;
if( isEnabled() && isInside( inX, inY ) ) {
setLastMouse( inX, inY );
fireActionPerformed( this );
}
}
void StateObjectDisplay::mouseReleased( double inX, double inY ) {
mShowSelected = true;
mLastActionRelease = true;
mLastActionPress = false;
if( isEnabled() && isInside( inX, inY ) ) {
setLastMouse( inX, inY );
fireActionPerformed( this );
}
}
void StateObjectDisplay::mouseMoved( double inX, double inY ) {
if( isEnabled() && isInside( inX, inY ) ) {
mMouseHover = true;
setLastMouse( inX, inY );
}
else {
mMouseHover = false;
}
}
int StateObjectDisplay::getClickedLayer( int inPixelClickX,
int inPixelClickY,
int *outClickOffsetX,
int *outClickOffsetY ) {
//printf( "Checking clicked layer for %d, %d\n",
// inPixelClickX, inPixelClickY );
int centerScreenPosX = (int)( P * (G/2) / mZoomFactor ) + P / 2;
int centerScreenPosY =
(int)( P * (G/2 - mZoomFactor) / mZoomFactor ) + P / 2;
int numLayers = mObjectMasks.size();
// skip anchor, start at top, stop when a hit is found
for( int i=numLayers-2; i>=0; i-- ) {
intPair pos = *( mObjectSpritePositions.getElement( i ) );
int posX = pos.x - centerScreenPosX;
int posY = pos.y - centerScreenPosY;
//printf( " Layer %d at (%d,%d)\n", i, posX, posY );
// first, do bounding box
if( inPixelClickX >= posX && inPixelClickX < posX + P
&&
inPixelClickY >= posY && inPixelClickY < posY + P ) {
clickMask *mask = mObjectMasks.getElement( i );
int offsetY = P - ( inPixelClickY - posY ) - 1;
int offsetX = inPixelClickX - posX;
if( mask->opaque[ offsetY ][ offsetX ] ) {
// hit!
*outClickOffsetX = offsetX - P/2;
*outClickOffsetY = offsetY - P/2;
return i;
}
}
}
return -1;
}