📄 chmaze.cpp
字号:
}
else
{
userShadingPref = GetSettings()->GetRenderQuality();
}
m_RC.SetShadingPref(userShadingPref);
R3dClearBuffers( m_RC.GetRC(),
R3D_CI_DRAW_BUFFER | R3D_CI_ZBUFFER );
G3dClearStack( m_RC.GetGC() );
/* Turn off texturing except when
we encounter one; then do it at
draw prim time */
R3dSetState( m_RC.GetRC(), R3D_STA_DISABLES, R3D_SE_TEXTURING );
R3dSetState( m_RC.GetRC(), R3D_STA_TEX_ID, (Dword_t)(0) );
R3dSetState( m_RC.GetRC(), R3D_STA_DISABLES, R3D_SE_MODULATION );
G3dSetState( m_RC.GetGC(), G3DL_TEXTURE_MOD, &off );
//ChQvState state( this );
TRACE( "Drawing the tree\r\n" );
#if !defined(CH_VRML_VIEWER) && !defined(CH_VRML_PLUGIN )
// TODO
m_pMainInfo->StartFrameTime();
#else
StartFrameTime();
#endif
if (m_pRoot)
{
if(m_RC.Draw())
{
POINT ptCursor;
GetCursorPos( &ptCursor );
ScreenToClient( &ptCursor );
IsAnchor(ptCursor.x, ptCursor.y); // update the status line
}
}
#if !defined(CH_VRML_VIEWER) && !defined(CH_VRML_PLUGIN )
m_pMainInfo->EndFrameTime();
#else
EndFrameTime();
#endif
R3dSwapBuffers( m_RC.GetRC(), 0 );
}
}
#else
#endif // defined( CH_USE_3DR )
if (IsInMouseMove())
{
DrawMouseMoveCrosshair( pDC );
DrawMouseMoveVector( pDC );
}
/* Release the DC if it was one
we created */
if (0 == pDC)
{
ReleaseDC( pUseDC );
}
}
// Render the scene to the off-screen buffer
// pClipRect defaults to 0
void ChMazeWnd::Render(CRect* pClipRect)
{
}
bool ChMazeWnd::NotifyPaletteChange( UINT uMsg, CWnd* pFocusWnd )
{
bool boolIsProcessed = false;
if (IsCurrent())
{
switch( uMsg )
{
case WM_PALETTECHANGED:
{
OnPaletteChanged( pFocusWnd );
//SendMessage(WM_PALETTECHANGED, WORD(pFocusWnd->GetSafeHwnd( )));
break;
}
case WM_QUERYNEWPALETTE:
{
/* 3DR is apparently hooking the
window with the DC passed to
CreateRC to get this message */
boolIsProcessed = true;
SendMessage( WM_QUERYNEWPALETTE );
GetRenderContext()->SetDirty();
InvalidateRect( 0, false );
break;
}
}
}
return boolIsProcessed;
}
void ChMazeWnd::AdjustLight(string strCmd, int iLight, float fLevel)
{
ChQvState state(this, strCmd, iLight, fLevel);
if(m_pRoot) m_pRoot->traverse(&state);
GetRenderContext()->SetDirty();
InvalidateRect(0, false);
}
void ChMazeWnd::DoNodeCommand(string& strCmd, string &strNodeVRML )
{
// Build a new tree
string strVRML = EncapsulateVRML(strNodeVRML);
// make the vrml thing
char *buf = strVRML.GetBuffer(1);
istrstream is(buf);
bool boolSuccess = false;
QvDB::init();
ChQvInput in;
in.setFilePointer(&is);
QvNode *root;
if (QvDB::read(&in, root) && root != 0)
{
boolSuccess = true;
}
else
{
return ;
}
string strSubCmd;
string strKey;
ChQvState state(this, strCmd, strSubCmd, strKey, strNodeVRML, root);
if(m_pRoot) m_pRoot->traverse(&state);
ChQvState defstate(this, strCmd, strSubCmd, strKey, strNodeVRML, root);
// used to walk the default root here, but now camera is handled elsewhere
delete root;
GetRenderContext()->SetDirty();
InvalidateRect(0, false);
}
bool ChMazeWnd::CheckForTrailingJunk(QvInput &in ) //, FILE *f)
{
char ch;
in.get( ch );
#if 0
while( ch != EOF)
{
if(!isspace(ch))
{
//Trailing junk
if(ch == '#')
{
while( ch != EOF && ch != '\n' && ch != '\r') in.get(ch); // ignore comments
}
else
{
QvReadError::post(&in, "Trailing characters after toplevel node. (Only one toplevel node allowed.)");
return true;
}
}
else
{
in.get( ch );
}
}
#endif // Allow just about anything
return false;
}
bool ChMazeWnd::LoadScene( const string &strURL, const string &strFilename, chparam data )
{
if ( m_hParseThreadEvent == 0 && GetRenderContext()->IsThreaded() )
{ // Create the thread event
m_hParseThreadEvent = ::CreateEvent( 0, false, false, 0 );
ASSERT( m_hParseThreadEvent );
::InitializeCriticalSection( &m_syncParser );
}
// cancel all parse threads before we start a new thread
AbortParsing();
// Reset the event
::ResetEvent( GetEndParseEvent() );
ChParseInfo * pParseInfo = new ChParseInfo( this, strURL, strFilename );
ASSERT( pParseInfo );
pParseInfo->SetUserData2((void*)data);
// Add it to my list of parse threads running
AddParseInfo( pParseInfo );
if ( !pParseInfo->ParseVrmlFile( ChParseInfo::typeScene ))
{ // failed to initialize
m_parseThreadList.RemoveTail( );
delete pParseInfo;
}
return true;
}
bool ChMazeWnd::LoadWWWInline( const string &strURL, const string &strFilename,
QvWWWInline *pInlineNode )
{
ChParseInfo * pParseInfo = new ChParseInfo( this, strURL, strFilename );
ASSERT( pParseInfo );
pParseInfo->SetUserData( pInlineNode );
((ChQvWWWInlineRenderData*)(pInlineNode->GetRenderData()))->SetParseInfo(pParseInfo); // starting to parse
// Serialize this
// Add it to my list of parse threads running
AddParseInfo( pParseInfo );
if ( !pParseInfo->ParseVrmlFile( ChParseInfo::typeWWWInline ))
{ // failed to initialize
RemoveParseInfo( pParseInfo );
delete pParseInfo;
}
return true;
}
#define CAMERA_CLASS "QvPerspectiveCamera"
#define CAMERA_CLASS_ORTHO "QvOrthographicCamera"
ChMazeWnd* ChMazeWnd::SetScene( QvNode *root )
{
m_pRoot = root;
/* Get the global hints from the
tree */
SetGlobalHints();
SetupTreeDefaults();
// Reset the navigators
for(int j = 0; j < viewerModeCount; j++)
{
if(m_pNavigators[j])
{
m_pNavigators[j]->SetState(ChVrmlStateTransition::s_start);
}
}
#if !defined(CH_VRML_VIEWER) && !defined(CH_VRML_PLUGIN )
GetMainInfo()->GetCore()->AbortRequests( false,
GetMainInfo()->GetStream() );
#else
GetHTTPConn()->AbortRequests( false, GetHTTPConn()->GetStreamMgr() );
#endif
// Set the node count to zero
GetRenderContext()->ResetScene();
// Delete the old instance tree, and
// make a new one
ChQvBuildState bldIt(this);
m_pRoot->traverse(&bldIt);
// TODO !! fix this for trivial trees
GetRenderContext()->SetRoot((ChQvInstance*)(bldIt.GetCurrentParent()));
// Compute bounds on instance tree
if (!m_pBounds) m_pBounds = new ChQvBounds;
//m_pBounds->Apply(m_pRoot, this);
m_pBounds->Apply(GetRenderContext()->GetRoot(), GetRenderContext());
// Set the initial camera
ChQvQuery cameraQuery( this, CAMERA_CLASS, ChQvQuery::byClassName );
cameraQuery.Apply( m_pRoot );
// Try to get the camera node
QvPerspectiveCamera* pCameraNode = (QvPerspectiveCamera*)cameraQuery.GetNode();
if(!pCameraNode)
{
// No perspective camera, maybe an ortho one?
ChQvQuery cameraQuery( this, CAMERA_CLASS_ORTHO, ChQvQuery::byClassName );
cameraQuery.Apply( m_pRoot );
// Try to get the camera node
pCameraNode = (QvPerspectiveCamera*)cameraQuery.GetNode();
}
if(pCameraNode)
{
GetRenderContext()->SetCurrentCamera(pCameraNode);
//GetRenderContext()->SetCurrentCamera(pCameraNode); // ????????
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
else
{
GetRenderContext()->SetCurrentCamera();
}
#endif
GetCameraControl()->Init();
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
GetRenderContext()->StartConstruction(); // Start the actual scene building
// in reality lab - done in
// another thread
#endif
if (!m_uiTickTimer)
{
// Start the timer
m_uiTickTimer = SetTimer( moveTimerID+1, moveTimerDuration, 0 );
}
GetRenderContext()->SetDirty();
Invalidate(false);
OnLoadComplete(); // Call the UI or whoever to tell it we're loaded
return this;
}
void ChMazeWnd::Spawn(const string & strURL)
{
ChQvSpawnState state(this, strURL);
if(m_pRoot) m_pRoot->traverse(&state);
return;
}
#if defined(CH_USE_3DR)
void ChMazeWnd::AddAnchor(ChQvAnchorSensor *pAnchor)
{
pAnchor->SetID(m_anchors.GetCount());
m_anchors.AddTail(pAnchor);
}
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
// no need to
#else
#pragma message("Not adding/clearing anchors")
#endif
void ChMazeWnd::ClearAnchors()
{
#if defined(CH_USE_3DR)
ChQvAnchorSensor *pAnchor;
while(!m_anchors.IsEmpty())
{
pAnchor = m_anchors.RemoveHead();
delete pAnchor;
}
#endif
}
/*----------------------------------------------------------------------------
ChMazeWnd Pueblo helper functions
----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
ChMazeWnd static functions
----------------------------------------------------------------------------*/
string ChMazeWnd::EncapsulateVRML( string strNodeVRML )
{
string strBuf( "#VRML V1.0 ascii\n " );
//strBuf += " Separator {");
strBuf += strNodeVRML;
//strBuf += " }";
return strBuf;
}
/*----------------------------------------------------------------------------
ChMazeWnd diagnostics
----------------------------------------------------------------------------*/
#if defined( _DEBUG )
void ChMazeWnd::AssertValid() const
{
ChGraphicView::AssertValid();
}
void ChMazeWnd::Dump( CDumpContext& dc ) const
{
ChGraphicView::Dump( dc );
}
#endif // defined( _DEBUG )
/*----------------------------------------------------------------------------
ChMazeWnd protected methods
----------------------------------------------------------------------------*/
bool ChMazeWnd::NewBackground( ChDib* pDIB )
{ /* Create a new buffer and
palette to match a new
background DIB */
return true;
}
bool ChMazeWnd::IsAnchor( int iX, int iY, pChQvAnchorSensor &pHitAnchor )
{
bool boolIsAnchor = false;
#if defined(CH_USE_3DR)
if(!GetScene()) return false;
/* X and Y are in window
coordinates */
G3dSetActiveStack(GetGC(), G3DT_CAM_CLIP);
G3dPushTransform(GetGC());
G3dSetActiveStack(GetGC(), G3DT_MODEL);
G3dPushTransform(GetGC());
// Now do the hittest on each anchor in the list. If -any- get a hit, we choose the closest.
if (!m_anchors.IsEmpty())
{
float fNearZ;
ChQvAnchorSensor *pAnchor, *pNearAnchor = 0;
ChPosition pos = m_anchors.GetHeadPosition();
while (pos) {
pAnchor = m_anchors.GetNext(pos);
float fZ;
if( pAnchor->HitTest(GetGC(), iX, iY, fZ))
{
if(!pNearAnchor || fZ > fNearZ)
{
fNearZ = fZ;
pNearAnchor = pAnchor;
}
}
}
if (pNearAnchor)
{
boolIsAnchor = true;
QvWWWAnchor *pAnchorNode = pNearAnchor->GetAnchorNode();
string hint;
pNearAnchor->GetHint(hint);
OnHotSpot(0, hint);
m_boolIsHintDisplayed = true;
pHitAnchor = pNearAnchor;
m_hCursor = m_hAnchorCursor;
::SetCursor(m_hAnchorCursor);
}
else
{
if(m_boolIsHintDisplayed)
{
string hint;
OnHotSpot(0, hint);
m_boolIsHintDisplayed = false;
HCURSOR hCurs = m_hCursor = HCURSOR(GetClassLong(GetSafeHwnd(), GCL_HCURSOR));
::SetCursor(hCurs);
}
}
}
G3dSetActiveStack(GetGC(), G3DT_CAM_CLIP);
G3dPopTransform(GetGC());
G3dSetActiveStack(GetGC(), G3DT_MODEL);
G3dPopTransform(GetGC());
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
{
// Hand it to RC; it has scene data
GetRenderContext()->LockScene();
boolIsAnchor = GetRenderContext()->IsAnchor(iX, iY, pHitAnchor);
if(boolIsAnchor)
{
string hint;
pHitAnchor->GetHint(hint);
OnHotSpot(0, hint);
m_boolIsHintDisplayed = true;
m_hCursor = m_hAnchorCursor;
::SetCursor(m_hAnchorCursor);
}
else if(m_boolIsHintDisplayed)
{
string hint;
OnHotSpot(0, hint);
m_boolIsHintDisplayed = false;
HCURSOR hCurs = m_hCursor = HCURSOR(GetClassLong(GetSafeHwnd(), GCL_HCURSOR));
::SetCursor(hCurs);
}
GetRenderContext()->UnlockScene();
}
#else
#pragma message("Not testing anchors")
#endif
return boolIsAnchor;
}
void ChMazeWnd::WriteStatus( UINT uMsgID )
{
// iMessage should be > 0 for all valid messages and 0 to remove
// any progress message. If you want to define any new message,
// add it to the list in ChMaze.h
// The status messages could be generated by worker threads, so
// we post the message to the thread that created this window and
// retrive the message and let the virtual functions to the work
PostMessage( WM_VRML_PROGRESS, uMsgID );
}
void ChMazeWnd::OnHotSpot( chparam userData,
const string& strDocURL )
{
#if !defined(CH_VRML_VIEWER) && !defined(CH_VRML_PLUGIN )
GetMainInfo()->WriteStatus(strDocURL);
#else
#endif
}
void ChMazeWnd::StartAnchor( int iX, int iY )
{
#if defined(CH_USE_3DR)
/* We can't be in both mouse move
and anchor states */
ChQvAnchorSensor *pAnchor;
ASSERT( !IsInMouseMove() );
IsAnchor(iX, iY, pAnchor);
// Save the current anchor by
// making a copy of the sensor
m_pAnchor = new ChQvAnchorSensor(0);
*m_pAnchor = *pAnchor;
m_boolInMouseAnchor = true;
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
/* We can't be in both mouse move
and anchor states */
ChQvAnchorSensor *pAnchor;
ASSERT( !IsInMouseMove() );
IsAnchor(iX, iY, pAnchor);
// Don't make a copy for rlab
m_pAnchor = pAnchor;
m_boolInMouseAnchor = true;
#else
#pragma message("Not starting anchors")
#endif
}
void ChMazeWnd::UpdateAnchor( int iX, int iY )
{
IsAnchor(iX, iY); // update the status line
}
void ChMazeWnd::EndAnchor( int iX, int iY )
{
#if defined(CH_USE_3DR) || defined(CH_USE_RLAB) || defined(CH_USE_D3D)
ChQvAnchorSensor *pAnchor;
// get the anchor currently under mouse, if any
// and test to see if it's the one that started us
if(IsAnchor(iX, iY, pAnchor) && pAnchor /*&& *pAnchor == *m_pAnchor*/) // jwd - changed to use click
{
//WriteStatus("Request Initiated"); // just for debugging
// Tell my info who will tell the pane mgr
// It's their job to notify
string command;
command = pAnchor->GetCommand();
if(!command.IsEmpty())
{
#if !defined(CH_VRML_VIEWER) && !defined(CH_VRML_PLUGIN )
GetMainInfo()->NotifyAnchor(command);
#else
GetURL(command, 0, GetCurrentURL());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -