306 lines
6.9 KiB
C++
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 = ▭
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|