windows-nt/Source/XPSP1/NT/multimedia/opengl/test/misc/uidemo/loghot.cxx
2020-09-26 16:20:57 +08:00

306 lines
6.9 KiB
C++

/******************************Module*Header*******************************\
* Module Name: loghot.cxx
*
* Copyright (c) 1997 Microsoft Corporation
*
\**************************************************************************/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include "logon.hxx"
#include "resource.h"
static LOG_OBJECT *pHotObj;
static void DrawBanner();
static BOOL bFrameObjects; // whether to frame the objects or not
static float colorHot[3] = { 0.0f, 1.0f, 0.0f };
static float colorWhite[3] = { 1.0f, 1.0f, 1.0f };
#define HOT_CURSOR 1
/******************** HOT SEQUENCE ****************************************\
*
\**************************************************************************/
static LOG_OBJECT*
CheckForHit( int mouseX, int mouseY )
{
// Check mouse coords against rect of each object. Return ptr to object
// if within.
mouseY = InvertY( mouseY, winSize.height );
LOG_OBJECT *pObj;
GLIRECT rect, *pRect;
pRect = &rect;
for( int i = 0; i < nLogObj; i++ ) {
pObj = pLogObj[i];
pObj->GetRect( pRect );
if( ( mouseX >= pRect->x ) &&
( mouseX < (pRect->x + pRect->width) ) &&
( mouseY >= pRect->y ) &&
( mouseY < (pRect->y + pRect->height) ) )
{
// SS_DBGPRINT( "CheckForHit() recording a hit\n" );
return pObj;
}
}
return NULL;
}
static void
DrawObject( LOG_OBJECT *pObj, BOOL bHot )
{
if( !pObj )
return;
// Set ColorMaterial color, in case lighting is on for the frame
if( bHot ) {
glColor3fv( colorHot );
} else {
glColor3fv( colorWhite );
}
pObj->Draw();
}
// This redraws everything
static void DrawHotSequence(void)
{
ClearWindow();
LOG_OBJECT *pObj;
for( int i = 0; i < nLogObj; i++ ) {
pObj = pLogObj[i];
DrawObject( pObj, (pObj == pHotObj) );
}
Flush();
DrawBanner();
}
static void
FinishLogonHotSequence()
{
#ifndef HOT_CURSOR
// User has selected an object.
// Turn off hilite on current selection and return
DrawObject( pHotObj, FALSE );
Flush();
#endif
mtkWin->Return();
}
static BOOL
HotKey(int key, GLenum mask)
{
switch (key) {
case TK_RETURN:
if( pHotObj )
FinishLogonHotSequence();
break;
case TK_ESCAPE:
if( bDebugMode )
Quit();
break;
case TK_SPACE:
if( bDebugMode ) {
bRunAgain = TRUE;
FinishLogonHotSequence();
}
break;
default:
if( bDebugMode )
return AttributeKey( key, mask );
return FALSE;
}
return FALSE;
}
static BOOL
MouseButton(int mouseX, int mouseY, GLenum button)
{
// If left button click on an object, run end of logon sequence
if( !(button & TK_LEFTBUTTON) )
return GL_FALSE;
LOG_OBJECT *pObj;
if( pObj = CheckForHit( mouseX, mouseY ) ) {
pHotObj = pObj;
FinishLogonHotSequence();
}
return FALSE;
}
static BOOL
MouseMove(int mouseX, int mouseY, GLenum button)
{
// Handle a mouse move. Redraw only when necessary
LOG_OBJECT *pObj;
LOG_OBJECT *pLastHotObj = pHotObj;
if( pObj = CheckForHit( mouseX, mouseY ) ) {
if( pObj == pHotObj ) {
// State has not changed
return FALSE;
}
// New hot object
pHotObj = pObj;
SetCursor( hHotCursor );
} else {
SetCursor( hNormalCursor );
if( !pHotObj ) {
// State has not changed
return FALSE;
}
// No hot object
pHotObj = NULL;
}
#ifndef HOT_CURSOR
if( ! bSwapHints )
// Need to do complete redraw
return TRUE;
// Redraw only the objects that changed
if( pLastHotObj ) {
// remove hot indicator from old hot object
DrawObject( pLastHotObj, FALSE );
}
if( pHotObj ) {
// add hot indicator to new hot object
DrawObject( pHotObj, TRUE );
}
// Flush the changes
Flush();
#endif
return FALSE;
}
static void DrawBanner()
{
BitBlt( mtkWin->GetHdc(), 0, 0, bannerSize.width, bannerSize.height,
hdcMem, 0, 0, SRCCOPY );
GdiFlush();
}
LOG_OBJECT *
RunLogonHotSequence()
{
if( bDebugMode )
bRunAgain = FALSE;
// Stop animation, make quads 'hot'
SS_DBGPRINT( "RunLogonHotSequence()\n" );
// If the objects were flown in without context their origins would have
// been in centre of the image part. Since we want to add context now,
// have to offset the destination values. This is done inside next loop
// Calc window rects of the quads
bSwapHints = bSwapHintsEnabled;
UpdateLocalTransforms( UPDATE_ALL );
bFrameObjects = FALSE; // no framing currently
LOG_OBJECT *pObj;
for( int i = 0; i < nLogObj; i++ ) {
pObj = pLogObj[i];
pObj->ShowContext( TRUE );
if( !bFlyWithContext ) {
// offset x dest value to the left (again, size assumption)
pObj->OffsetDest( - OBJECT_WIDTH / 4.0f, 0.0f, 0.0f );
}
if( bFrameObjects )
pObj->ShowFrame( TRUE );
pObj->CalcWinRect();
}
pHotObj = NULL;
// Set any gl attributes
if( bFrameObjects ) {
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
bDepth = TRUE;
}
// Go to slower but nicer texture drawing while in this mode
for( i = 0; i < nLogObj; i++ ) {
pLogObj[i]->pTex->MakeCurrent();
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
}
// Set up mtk functions for this sequence
mtkWin->SetAnimateFunc( NULL );
mtkWin->SetKeyDownFunc(HotKey);
mtkWin->SetMouseMoveFunc( MouseMove );
mtkWin->SetMouseDownFunc( MouseButton );
mtkWin->SetDisplayFunc( DrawHotSequence );
// Now get the current pointer position and simulate a mouse move with it,
// in case it's over one of the objects.
IPOINT2D ptMouse;
mtkWin->GetMouseLoc( &ptMouse.x, &ptMouse.y );
// Need to check that mouse is inside window
if( (ptMouse.x >= 0) &&
(ptMouse.x < winSize.width) &&
(ptMouse.y >= 0) &&
(ptMouse.y < winSize.height) )
{
MouseMove( ptMouse.x, ptMouse.y, 0 );
}
// Draw everything (so nicer textures show up)
DrawHotSequence();
if( !mtkWin->Exec() )
return NULL;
// Restore gl attributes
for( i = 0; i < nLogObj; i++ ) {
pLogObj[i]->pTex->MakeCurrent();
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
}
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
bDepth = FALSE;
// Turn frames off for the objects
for( i = 0; i < nLogObj; i++ ) {
pLogObj[i]->ShowFrame( FALSE );
}
// Dump the cursor
SetCursor( NULL );
return pHotObj;
}