Exemplo n.º 1
0
bool StudioModel::PostLoadModel( const char *modelname )
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	CStudioHdr *pStudioHdr = GetStudioHdr();
	if (pStudioHdr == NULL)
		return false;

	SetSequence (0);
	SetController (0, 0.0f);
	SetController (1, 0.0f);
	SetController (2, 0.0f);
	SetController (3, 0.0f);
	SetBlendTime( DEFAULT_BLEND_TIME );
	// SetHeadTurn( 1.0f );  // FIXME:!!!

	int n;
	for (n = 0; n < pStudioHdr->numbodyparts(); n++)
	{
		SetBodygroup (n, 0);
	}

	SetSkin (0);

/*
	Vector mins, maxs;
	ExtractBbox (mins, maxs);
	if (mins[2] < 5.0f)
		m_origin[2] = -mins[2];
*/
	return true;
}
Exemplo n.º 2
0
bool SaveViewerSettings (const char *filename, StudioModel *pModel )
{
	LONG lResult;           // Registry function result code
	DWORD dwDisposition;    // Type of key opening event

	if (filename == NULL || pModel == NULL)
		return false;

	HKEY hModelKey;
	lResult = RegViewerSettingsKey( filename, &hModelKey, &dwDisposition);

	if (lResult != ERROR_SUCCESS)  // Failure
		return false;

	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
	CStudioHdr *hdr = pModel->GetStudioHdr();

	RegWriteQAngle( hModelKey, "Rot", pModel->m_angles );
	RegWriteVector( hModelKey, "Trans", pModel->m_origin );
	RegWriteColor( hModelKey, "bgColor", g_viewerSettings.bgColor );
	RegWriteColor( hModelKey, "gColor", g_viewerSettings.gColor );
	RegWriteColor( hModelKey, "lColor", g_viewerSettings.lColor );
	RegWriteColor( hModelKey, "aColor", g_viewerSettings.aColor );
	RegWriteQAngle( hModelKey, "lightrot", g_viewerSettings.lightrot );
	RegWriteString( hModelKey, "sequence", hdr->pSeqdesc( pModel->GetSequence() ).pszLabel() );
	RegWriteString( hModelKey, "overlaySequence0", hdr->pSeqdesc( pModel->GetOverlaySequence( 0 ) ).pszLabel() );
	RegWriteFloat( hModelKey, "overlayWeight0", pModel->GetOverlaySequenceWeight( 0 ) );
	RegWriteString( hModelKey, "overlaySequence1", hdr->pSeqdesc( pModel->GetOverlaySequence( 1 ) ).pszLabel() );
	RegWriteFloat( hModelKey, "overlayWeight1", pModel->GetOverlaySequenceWeight( 1 ) );
	RegWriteString( hModelKey, "overlaySequence2", hdr->pSeqdesc( pModel->GetOverlaySequence( 2 ) ).pszLabel() );
	RegWriteFloat( hModelKey, "overlayWeight2", pModel->GetOverlaySequenceWeight( 2 ) );
	RegWriteString( hModelKey, "overlaySequence3", hdr->pSeqdesc( pModel->GetOverlaySequence( 3 ) ).pszLabel() );
	RegWriteFloat( hModelKey, "overlayWeight3", pModel->GetOverlaySequenceWeight( 3 ) );
	RegWriteInt( hModelKey, "renderwidth", g_viewerSettings.width );
	RegWriteInt( hModelKey, "renderheight", g_viewerSettings.height );
	RegWriteFloat( hModelKey, "speedscale", g_viewerSettings.speedScale );
	RegWriteInt( hModelKey, "viewermode", g_viewerSettings.application_mode );
	RegWriteInt( hModelKey, "thumbnailsize", g_viewerSettings.thumbnailsize );
	RegWriteInt( hModelKey, "thumbnailsizeanim", g_viewerSettings.thumbnailsizeanim );
	RegWriteInt( hModelKey, "speechapiindex", g_viewerSettings.speechapiindex );
	RegWriteInt( hModelKey, "cclanguageid", g_viewerSettings.cclanguageid );
	RegWriteInt( hModelKey, "showground", g_viewerSettings.showGround );
	RegWriteInt( hModelKey, "showbackground", g_viewerSettings.showBackground );
	RegWriteInt( hModelKey, "showshadow", g_viewerSettings.showShadow );
	RegWriteInt( hModelKey, "showillumpos", g_viewerSettings.showIllumPosition );
	RegWriteInt( hModelKey, "enablenormalmapping", g_viewerSettings.enableNormalMapping );

	RegWriteString( hModelKey, "merge0", g_viewerSettings.mergeModelFile[0] );
	RegWriteString( hModelKey, "merge1", g_viewerSettings.mergeModelFile[1] );
	RegWriteString( hModelKey, "merge2", g_viewerSettings.mergeModelFile[2] );
	RegWriteString( hModelKey, "merge3", g_viewerSettings.mergeModelFile[3] );

	return true;
}
int IFaceposerModels::LoadModel( char const *filename )
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	int idx = FindModelByFilename( filename );
	if ( idx == -1 && Count() < MAX_FP_MODELS )
	{
		StudioModel *model = new StudioModel();

		StudioModel *save = g_pStudioModel;
		g_pStudioModel = model;
		if ( !model->LoadModel( filename ) )
		{
			delete model;
			g_pStudioModel = save;
			return 0; // ?? ERROR
		}
		g_pStudioModel = save;

		model->SetSequence( model->LookupSequence( "idle_subtle" ) );
		int idx = model->GetSequence();
		model->SetSequence( idx );

		SetupModelFlexcontrollerLinks( model );

		if (!LoadViewerSettings( filename, model ))
		{
			InitViewerSettings( "faceposer" );
		}
		model->ClearOverlaysSequences();


		CFacePoserModel *newEntry = new CFacePoserModel( filename, model );
		
		idx = m_Models.AddToTail( newEntry );

		g_MDLViewer->InitModelTab();
		
		g_MDLViewer->SetActiveModelTab( idx );

		//g_pControlPanel->CenterOnFace();
	}
	return idx;
}
bool CClientState::ProcessEntityMessage(SVC_EntityMessage *msg)
{
	// Look up entity
	IClientNetworkable *entity = entitylist->GetClientNetworkable( msg->m_nEntityIndex );

	if ( !entity )
	{
		// message was send to use, even we don't have this entity TODO change that on server side
		return true;
	}

	// route to entity 
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	// buffer for incoming user message
	byte entityData[ MAX_ENTITY_MSG_DATA ] = { 0 };
	bf_read entMsg( "EntityMessage(read)", entityData, sizeof( entityData ) );
	msg->m_DataIn.ReadBits( entityData, msg->m_nLength );
	entMsg.StartReading( entityData, Bits2Bytes( msg->m_nLength ) );

	entity->ReceiveMessage( msg->m_nClassID, entMsg );

	return true;
}
Exemplo n.º 5
0
bool StudioModel::LoadModel( const char *pModelName )
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	if (!pModelName)
		return 0;

	// In the case of restore, m_pModelName == modelname
	if (m_pModelName != pModelName)
	{
		// Copy over the model name; we'll need it later...
		if (m_pModelName)
		{
			delete[] m_pModelName;
		}
		m_pModelName = new char[Q_strlen(pModelName) + 1];
		strcpy( m_pModelName, pModelName );
	}

	m_MDLHandle = g_pMDLCache->FindMDL( pModelName );

	// allocate a pool for a studiohdr cache
	if (m_pStudioHdr != NULL)
	{
		delete m_pStudioHdr;
	}
	m_pStudioHdr = new CStudioHdr( g_pMDLCache->GetStudioHdr( m_MDLHandle ), g_pMDLCache );

	// manadatory to access correct verts
	SetCurrentModel();

	m_pPhysics = LoadPhysics( m_MDLHandle );

	// Copy over all of the hitboxes; we may add and remove elements
	m_HitboxSets.RemoveAll();

	CStudioHdr *pStudioHdr = GetStudioHdr();

	int i;
	for ( int s = 0; s < pStudioHdr->numhitboxsets(); s++ )
	{
		mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( s );
		if ( !set )
			continue;

		m_HitboxSets.AddToTail();

		for ( i = 0; i < set->numhitboxes; ++i )
		{
			mstudiobbox_t *pHit = set->pHitbox(i);
			int nIndex = m_HitboxSets[ s ].AddToTail( );
			m_HitboxSets[s][nIndex] = *pHit;
		}

		// Set the name
		hbsetname_s *n = &m_HitboxSetNames[ m_HitboxSetNames.AddToTail() ];
		strcpy( n->name, set->pszName() );
	}

	// Copy over all of the surface props; we may change them...
	for ( i = 0; i < pStudioHdr->numbones(); ++i )
	{
		mstudiobone_t* pBone = pStudioHdr->pBone(i);

		CUtlSymbol prop( pBone->pszSurfaceProp() );
		m_SurfaceProps.AddToTail( prop );
	}

	m_physPreviewBone = -1;

	bool forceOpaque = (pStudioHdr->flags() & STUDIOHDR_FLAGS_FORCE_OPAQUE) != 0;
	bool vertexLit = false;
	m_bIsTransparent = false;
	m_bHasProxy = false;

	studiohwdata_t *pHardwareData = g_pMDLCache->GetHardwareData( m_MDLHandle );
	if ( !pHardwareData )
	{
		Assert( 0 );
		return false;
	}

	for( int lodID = pHardwareData->m_RootLOD; lodID < pHardwareData->m_NumLODs; lodID++ )
	{
		studioloddata_t *pLODData = &pHardwareData->m_pLODs[lodID];
		for ( i = 0; i < pLODData->numMaterials; ++i )
		{
			if (pLODData->ppMaterials[i]->IsVertexLit())
			{
				vertexLit = true;
			}
			if ((!forceOpaque) && pLODData->ppMaterials[i]->IsTranslucent())
			{
				m_bIsTransparent = true;
				//Msg("Translucent material %s for model %s\n", pLODData->ppMaterials[i]->GetName(), pStudioHdr->name );
			}
			if (pLODData->ppMaterials[i]->HasProxy())
			{
				m_bHasProxy = true;
			}
		}
	}

	return true;
}
Exemplo n.º 6
0
int
MDLViewer::handleEvent (mxEvent *event)
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );
	
	switch (event->event)
	{
	case mxEvent::Action:
	{
		switch (event->action)
		{
		case IDC_FILE_LOADMODEL:
		{
			const char *ptr = mxGetOpenFileName (this, 0, "*.mdl");
			if (ptr)
			{
				LoadModelFile( ptr );
			}
		}
		break;

		case IDC_FILE_LOADMODEL_STEAM:
		{
			const char *pFilename = SteamGetOpenFilename();
			if ( pFilename )
			{
				LoadModelFile( pFilename );
			}
		}
		break;

		case IDC_FILE_LOADMERGEDMODEL:
		{
			const char *ptr = mxGetOpenFileName (this, 0, "*.mdl");
			if (ptr)
			{
				strcpy( g_viewerSettings.mergeModelFile[0], ptr );
				LoadModelFile( ptr, 0 );
			}
		}
		break;

		case IDC_FILE_LOADMERGEDMODEL_STEAM:
		{
			const char *pFilename = SteamGetOpenFilename();
			if ( pFilename )
			{
				strcpy( g_viewerSettings.mergeModelFile[0], pFilename );
				LoadModelFile( pFilename, 0 );
			}
		}
		break;

		case IDC_FILE_UNLOADMERGEDMODEL:
		{
			// FIXME: move to d_cpl
			if (g_pStudioExtraModel[0])
			{
				strcpy( g_viewerSettings.mergeModelFile[0], "" );
				g_pStudioExtraModel[0]->FreeModel( false );
				delete g_pStudioExtraModel[0];
				g_pStudioExtraModel[0] = NULL;
			}
		}
		break;

		case IDC_FILE_REFRESH:
		{
			Refresh();
			break;
		}

		case IDC_FILE_LOADBACKGROUNDTEX:
		case IDC_FILE_LOADGROUNDTEX:
		{
			const char *ptr = mxGetOpenFileName (this, 0, "*.*");
			if (ptr)
			{
				if (0 /* d_MatSysWindow->loadTexture (ptr, event->action - IDC_FILE_LOADBACKGROUNDTEX) */)
				{
					if (event->action == IDC_FILE_LOADBACKGROUNDTEX)
						d_cpl->setShowBackground (true);
					else
						d_cpl->setShowGround (true);

				}
				else
					mxMessageBox (this, "Error loading texture.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
			}
		}
		break;

		case IDC_FILE_UNLOADGROUNDTEX:
		{
			// d_MatSysWindow->loadTexture (0, 1);
			d_cpl->setShowGround (false);
		}
		break;

		case IDC_FILE_RECENTMODELS1:
		case IDC_FILE_RECENTMODELS2:
		case IDC_FILE_RECENTMODELS3:
		case IDC_FILE_RECENTMODELS4:
		case IDC_FILE_RECENTMODELS5:
		case IDC_FILE_RECENTMODELS6:
		case IDC_FILE_RECENTMODELS7:
		case IDC_FILE_RECENTMODELS8:
		{
			int i = event->action - IDC_FILE_RECENTMODELS1;
			LoadModelFile( recentFiles[i] );
		}
		break;

		case IDC_FILE_EXIT:
		{
			redraw ();
			mx::quit ();
		}
		break;

		case IDC_OPTIONS_COLORBACKGROUND:
		case IDC_OPTIONS_COLORGROUND:
		case IDC_OPTIONS_COLORLIGHT:
		case IDC_OPTIONS_COLORAMBIENT:
		{
			float *cols[4] = { g_viewerSettings.bgColor, g_viewerSettings.gColor, g_viewerSettings.lColor, g_viewerSettings.aColor };
			float *col = cols[event->action - IDC_OPTIONS_COLORBACKGROUND];
			int r = (int) (col[0] * 255.0f);
			int g = (int) (col[1] * 255.0f);
			int b = (int) (col[2] * 255.0f);
			if (mxChooseColor (this, &r, &g, &b))
			{
				col[0] = (float) r / 255.0f;
				col[1] = (float) g / 255.0f;
				col[2] = (float) b / 255.0f;
			}
		}
		break;

		case IDC_OPTIONS_CENTERVIEW:
			d_cpl->centerView ();
			break;
		case IDC_OPTIONS_VIEWMODEL:
		{
			d_cpl->viewmodelView();
		}
		break;

		case IDC_OPTIONS_MAKESCREENSHOT:
		{
			char *ptr = (char *) mxGetSaveFileName (this, "", "*.tga");
			if (ptr)
			{
				if (!strstr (ptr, ".tga"))
					strcat (ptr, ".tga");
				d_MatSysWindow->dumpViewport (ptr);
			}
		}
		break;

		case IDC_OPTIONS_DUMP:
			d_cpl->dumpModelInfo ();
			break;

		case IDC_VIEW_FILEASSOCIATIONS:
			g_FileAssociation->setAssociation (0);
			g_FileAssociation->setVisible (true);
			break;

		case IDC_VIEW_ACTIVITIES:
			g_viewerSettings.showActivities = !g_viewerSettings.showActivities;
			menuView->setChecked( event->action, g_viewerSettings.showActivities );
			d_cpl->initSequenceChoices();
			d_cpl->resetControlPanel();
			break;

		case IDC_VIEW_HIDDEN:
			g_viewerSettings.showHidden = !g_viewerSettings.showHidden;
			menuView->setChecked( event->action, g_viewerSettings.showHidden );
			d_cpl->initSequenceChoices();
			d_cpl->resetControlPanel();
			break;

#ifdef WIN32
		case IDC_HELP_GOTOHOMEPAGE:
			ShellExecute (0, "open", "http://www.swissquake.ch/chumbalum-soft/index.html", 0, 0, SW_SHOW);
			break;
#endif

		case IDC_HELP_ABOUT:
			mxMessageBox (this,
				"Half-Life Model Viewer v2.0 (c) 2004 Valve Corp.\n"
				"Portions (c) 1999 by Mete Ciragan\n\n"
				"Left-drag inside circle to spin.\n"
				"Left-drag outside circle to rotate.\n"
				"Right-drag to zoom.\n"
				"Shift-left-drag to x-y-pan.\n"
				"Shift-right-drag to z-pan.\n"
				"Ctrl-left-drag to move light.\n\n"
				"Build:\t" __DATE__ ".\n"
				"Email:\[email protected]\n"
				"Web:\thttp://www.swissquake.ch/chumbalum-soft/", "About Half-Life Model Viewer",
				MX_MB_OK | MX_MB_INFORMATION);
			break;

		case IDC_ACCEL_WIREFRAME:
			d_cpl->setOverlayWireframe( !g_viewerSettings.overlayWireframe );
			break;

		case IDC_ACCEL_ATTACHMENTS:
			d_cpl->setShowAttachments( !g_viewerSettings.showAttachments );
			break;

		case IDC_ACCEL_GROUND:
			d_cpl->setShowGround( !g_viewerSettings.showGround );
			break;

		case IDC_ACCEL_HITBOXES:
			d_cpl->setShowHitBoxes( !g_viewerSettings.showHitBoxes );
			break;

		case IDC_ACCEL_BONES:
			d_cpl->setShowBones( !g_viewerSettings.showBones );
			break;

		case IDC_ACCEL_BACKGROUND:
			d_cpl->setShowBackground( !g_viewerSettings.showBackground );
			break;

		case IDC_ACCEL_MOVEMENT:
			d_cpl->setShowMovement( !g_viewerSettings.showMovement );
			break;

		case IDC_ACCEL_NORMALS:
			d_cpl->setShowNormals( !g_viewerSettings.showNormals );
			break;

		case IDC_ACCEL_TANGENTS:
			d_cpl->setShowTangentFrame( !g_viewerSettings.showTangentFrame );
			break;

		case IDC_ACCEL_SHADOW:
			d_cpl->setShowShadow( !g_viewerSettings.showShadow );
			break;

		} //switch (event->action)

	} // mxEvent::Action
	break;

	case mxEvent::Size:
	{
		g_viewerSettings.xpos = x();
		g_viewerSettings.ypos = y();
		g_viewerSettings.width = w();
		g_viewerSettings.height = h();

		int w = event->width;
		int h = event->height;
		int y = mb->getHeight ();
#ifdef WIN32
#define HEIGHT 240
#else
#define HEIGHT 140
		h -= 40;
#endif

		d_MatSysWindow->setBounds (0, y, w, h - HEIGHT); // !!
		d_cpl->setBounds (0, y + h - HEIGHT, w, HEIGHT);
	}
	break;


	case mxEvent::PosChanged:
	{
		g_viewerSettings.xpos = x();
		g_viewerSettings.ypos = y();
	}
	break;

	case KeyDown:
		d_MatSysWindow->handleEvent(event);
		d_cpl->handleEvent(event);
	break;

	case mxEvent::Activate:
	{
		if (event->action)
		{
			mx::setIdleWindow( getMatSysWindow() );
		}
		else
		{
			mx::setIdleWindow( 0 );
		}
	}
	break;

	} // event->event

	return 1;
}
void CLocalNetworkBackdoor::EndEntityStateUpdate()
{
	ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_START );

	// Handle entities created.
	int i;
	for ( i=0; i < m_nEntsCreated; i++ )
	{
		MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

		int iEdict = m_EntsCreatedIndices[i];
		CCachedEntState *pCached = &m_CachedEntState[iEdict];
		IClientNetworkable *pNet = pCached->m_pNetworkable;

		pNet->PostDataUpdate( DATA_UPDATE_CREATED );
		pNet->NotifyShouldTransmit( SHOULDTRANSMIT_START );
		pCached->m_bDormant = false;
	}

	// Handle entities changed.
	for ( i=0; i < m_nEntsChanged; i++ )
	{
		MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

		int iEdict = m_EntsChangedIndices[i];
		m_CachedEntState[iEdict].m_pNetworkable->PostDataUpdate( DATA_UPDATE_DATATABLE_CHANGED );
	}

	ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_POSTDATAUPDATE_END );

	// Handle entities removed (= SV_WriteDeletions() in normal mode)
	int nDWords = m_PrevEntsAlive.GetNumDWords();

	// Handle entities removed.
	for ( i=0; i < nDWords; i++ )
	{
		unsigned long prevEntsAlive = m_PrevEntsAlive.GetDWord( i );
		unsigned long entsAlive = m_EntsAlive.GetDWord( i );
		unsigned long toDelete = (prevEntsAlive ^ entsAlive) & prevEntsAlive;

		if ( toDelete )
		{
			for ( int iBit=0; iBit < 32; iBit++ )
			{
				if ( toDelete & (1 << iBit) )
				{
					int iEdict = (i<<5) + iBit;
					if ( iEdict < MAX_EDICTS )
					{
						if ( m_CachedEntState[iEdict].m_pNetworkable )
						{
							m_CachedEntState[iEdict].m_pNetworkable->Release();
							m_CachedEntState[iEdict].m_pNetworkable = NULL;
						}
						else
						{
							AssertOnce( !"EndEntityStateUpdate:  Would have crashed with NULL m_pNetworkable\n" );
						}
					}
					else
					{
						AssertOnce( !"EndEntityStateUpdate:  Would have crashed with entity out of range\n" );
					}
				}
			}
		}
	}

	// Remember the previous state of which entities were around.
	m_PrevEntsAlive = m_EntsAlive;

	// end of all entity update activity
	ClientDLL_FrameStageNotify( FRAME_NET_UPDATE_END );

	/*
	#ifdef _DEBUG
	for ( i=0; i <= highest_index; i++ )
	{
	if ( !( m_EntsAlive[i>>5] & (1 << (i & 31)) ) )
	Assert( !m_CachedEntState[i].m_pNetworkable );

	if ( ( m_EntsAlive[i>>5] & (1 << (i & 31)) ) &&
	( m_EntsCreated[i>>5] & (1 << (i & 31)) ) )
	{
	Assert( FindInList( m_EntsCreatedIndices, m_nEntsCreated, i ) );
	}

	if ( (m_EntsAlive[i>>5] & (1 << (i & 31))) && 
	!(m_EntsCreated[i>>5] & (1 << (i & 31))) &&
	(m_EntsChanged[i>>5] & (1 << (i & 31)))
	)
	{
	Assert( FindInList( m_EntsChangedIndices, m_nEntsChanged, i ) );
	}
	}
	#endif
	*/
}
int
ControlPanel::handleEvent (mxEvent *event)
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	int iret = 0;
	
	if ( HandleToolEvent( event ) )
	{
		return iret;
	}

	switch ( event->event )
	{
	case mxEvent::Size:
		{
			PositionControls( event->width, event->height );
			iret = 1;
		}
		break;
	case mxEvent::Action:
		{
			iret = 1;
			switch (event->action)
			{
			case IDC_TOOLSDRIVEMOUTH:
				{
					g_viewerSettings.faceposerToolsDriveMouth = ((mxCheckBox *)event->widget)->isChecked();
				}
				break;
			case IDC_TAB:
				{
					g_viewerSettings.showTexture = (tab->getSelectedIndex() == 3);
				}
				break;
				
			case IDC_RENDERMODE:
				{
					int index = cRenderMode->getSelectedIndex();
					if (index >= 0)
					{
						setRenderMode (index);
					}
				}
				break;
				
			case IDC_GROUND:
				setShowGround (((mxCheckBox *) event->widget)->isChecked());
				break;
				
			case IDC_MOVEMENT:
				setShowMovement (((mxCheckBox *) event->widget)->isChecked());
				break;
				
			case IDC_BACKGROUND:
				setShowBackground (((mxCheckBox *) event->widget)->isChecked());
				break;
				
			case IDC_HITBOXES:
				g_viewerSettings.showHitBoxes = ((mxCheckBox *) event->widget)->isChecked();
				break;
				
			case IDC_PHYSICSMODEL:
				g_viewerSettings.showPhysicsModel = ((mxCheckBox *) event->widget)->isChecked();
				break;
				
			case IDC_BONES:
				g_viewerSettings.showBones = ((mxCheckBox *) event->widget)->isChecked();
				break;
				
			case IDC_ATTACHMENTS:
				g_viewerSettings.showAttachments = ((mxCheckBox *) event->widget)->isChecked();
				break;
				
			case IDC_SEQUENCE:
				{
					int index = cSequence->getSelectedIndex();
					if (index >= 0)
					{
						setSequence ( index );
					}
				}
				break;
			
			case IDC_SPEEDSCALE:
				{
					g_viewerSettings.speedScale = ((mxSlider *) event->widget)->getValue();
					lSpeedScale->setLabel( va( "Speed scale %.2f", g_viewerSettings.speedScale ) );
				}
				break;
				
			case IDC_PRIMARYBLEND:
				{
					setBlend( 0, ((mxSlider *) event->widget)->getValue() );
				}
				break;
				
			case IDC_SECONDARYBLEND:
				{
					setBlend( 1, ((mxSlider *) event->widget)->getValue() );
				}
				break;
				
			case IDC_BODYPART:
				{
					int index = cBodypart->getSelectedIndex();
					if (index >= 0)
					{
						setBodypart (index);
						
					}
				}
				break;
				
			case IDC_SUBMODEL:
				{
					int index = cSubmodel->getSelectedIndex();
					if (index >= 0)
					{
						setSubmodel (index);
						
					}
				}
				break;
				
			case IDC_CONTROLLER:
				{
					int index = cController->getSelectedIndex();
					if (index >= 0)
						setBoneController (index);
				}
				break;
				
			case IDC_CONTROLLERVALUE:
				{
					int index = cController->getSelectedIndex();
					if (index >= 0)
						setBoneControllerValue (index, slController->getValue());
				}
				break;
				
			case IDC_SKINS:
				{
					int index = cSkin->getSelectedIndex();
					if (index >= 0)
					{
						models->GetActiveStudioModel()->SetSkin (index);
						g_viewerSettings.skin = index;
						g_pMatSysWindow->redraw();
					}
				}
				break;
			default:
				iret = 0;
				break;
			}
		}
	}

	return iret;
}
int mxExpressionTray::handleEvent (mxEvent *event)
{
	MDLCACHE_CRITICAL_SECTION_( g_pMDLCache );

	int iret = 0;

	if ( HandleToolEvent( event ) )
	{
		return iret;
	}

	switch ( event->event )
	{
	case mxEvent::Action:
		{
			iret = 1;
			switch ( event->action )
			{
			default:
				iret = 0;
				break;
			case IDC_EXPRESSIONCLASS:
				{
					int index = g_pExpressionClass->getSelectedIndex();
					if ( index >= 0 )
					{
						CExpClass *current = expressions->GetClass( index );
						if ( current )
						{
							// Switch classname
							expressions->ActivateExpressionClass( current );
							current->SelectExpression( 0 );
						}
					}
				}
				break;
			case IDC_CONTEXT_NEWEXP:
				g_pFlexPanel->NewExpression();
				break;
			case IDC_CONTEXT_EDITEXP:
				if ( m_nClickedCell != -1 )
				{
					g_pFlexPanel->EditExpression();
				}
				break;
			case IDC_CONTEXT_REVERT:
				if ( m_nClickedCell != -1 )
				{
					g_pFlexPanel->RevertExpression( m_nClickedCell );
				}
				break;
			case IDC_CONTEXT_SAVEEXP:
				if ( m_nClickedCell != -1 )
				{
					g_pFlexPanel->SaveExpression( m_nClickedCell );
				}
				break;
			case IDC_CONTEXT_DELETEXP:
				if ( m_nClickedCell != -1 )
				{
					g_pControlPanel->DeleteExpression( m_nClickedCell );
				}
				break;
			case IDC_TRAYSCROLL:
				{
					if (event->modifiers == SB_THUMBTRACK)
					{
						int offset = event->height;
						
						slScrollbar->setValue( offset );
						
						m_nTopOffset = offset;
						
						redraw();
					}
					else if ( event->modifiers == SB_PAGEUP )
					{
						int offset = slScrollbar->getValue();
						
						offset -= m_nGranularity;
						offset = max( offset, slScrollbar->getMinValue() );
						
						slScrollbar->setValue( offset );
						InvalidateRect( (HWND)slScrollbar->getHandle(), NULL, TRUE );
						
						m_nTopOffset = offset;
						
						redraw();
					}
					else if ( event->modifiers == SB_PAGEDOWN )
					{
						int offset = slScrollbar->getValue();
						
						offset += m_nGranularity;
						offset = min( offset, slScrollbar->getMaxValue() );
						
						slScrollbar->setValue( offset );
						InvalidateRect( (HWND)slScrollbar->getHandle(), NULL, TRUE );
						
						m_nTopOffset = offset;
						
						redraw();
					}
				}
				break;
			case IDC_AB:
				{
					AB();	
				}
				break;
			case IDC_THUMBNAIL_INCREASE:
				{
					ThumbnailIncrease();
				}
				break;
			case IDC_THUMBNAIL_DECREASE:
				{
					ThumbnailDecrease();
				}
				break;
			case IDC_CONTEXT_CREATEBITMAP:
				{
					if ( m_nClickedCell >= 0 )
					{
						CExpClass *active = expressions->GetActiveClass();
						if ( active )
						{
							CExpression *exp = active->GetExpression( m_nClickedCell );
							if ( exp )
							{
								active->SelectExpression( m_nClickedCell );
								exp->CreateNewBitmap( models->GetActiveModelIndex() );
								redraw();
							}
						}
					}
				}
				break;
			}
			break;
		}
	case mxEvent::MouseDown:
		{
			if ( !( event->buttons & mxEvent::MouseRightButton ) )
			{
				// Figure out cell #
				int cell = GetCellUnderPosition( event->x, event->y );
				CExpClass *active = expressions->GetActiveClass();
				if ( active )
				{

					if ( cell == m_nCurCell && cell >= 0 && cell < active->GetNumExpressions() )
					{
						mxETButton *btn = GetItemUnderCursor( event->x, event->y );
						if ( btn && btn->m_fnCallback )
						{	
							(this->*(btn->m_fnCallback))( cell );
							return iret;
						}
					}
					
					if ( cell >= 0 && cell < active->GetNumExpressions() )
					{
						active->SelectExpression( cell, event->modifiers & mxEvent::KeyShift ? false : true );

						int cx, cy, cw, ch;
						if ( ComputeRect( cell, cx, cy, cw, ch ) )
						{
							m_bDragging = true;
							m_nDragCell = cell;
							
							m_nXStart = (short)event->x;
							m_nYStart = (short)event->y;

							m_rcFocus.left = cx;
							m_rcFocus.top = cy;
							m_rcFocus.right = cx + cw;
							m_rcFocus.bottom = cy + ch - m_nDescriptionHeight;

							POINT pt;
							pt.x = pt.y = 0;
							ClientToScreen( (HWND)getHandle(), &pt );

							OffsetRect( &m_rcFocus, pt.x, pt.y );

							m_rcOrig = m_rcFocus;

							DrawFocusRect();
						}
					}
					else
					{
						Deselect();
						active->DeselectExpression();
						redraw();
					}
				}
			}
			iret = 1;
		}
		break;
	case mxEvent::MouseDrag:
		{
			if ( m_bDragging )
			{
				// Draw drag line of some kind
				DrawFocusRect();
	
				// update pos
				m_rcFocus = m_rcOrig;
				OffsetRect( &m_rcFocus, ( (short)event->x - m_nXStart ), 
					( (short)event->y - m_nYStart ) );
				
				DrawFocusRect();
			}
			iret = 1;
		}
		break;
	case mxEvent::MouseUp:
		{
			iret = 1;

			if ( event->buttons & mxEvent::MouseRightButton )
			{
				SetClickedCell( GetCellUnderPosition( (short)event->x, (short)event->y ) );
				ShowRightClickMenu( (short)event->x, (short)event->y );
				return iret;
			}

			int cell = GetCellUnderPosition( event->x, event->y );
			CExpClass *active = expressions->GetActiveClass();

			if ( m_bDragging )
			{
				DrawFocusRect();
				m_bDragging = false;
				// See if we let go on top of the choreo view

				if ( active )
				{
					// Convert x, y to screen space
					POINT pt;
					pt.x = (short)event->x;
					pt.y = (short)event->y;
					ClientToScreen( (HWND)getHandle(), &pt );

					HWND maybeTool = WindowFromPoint( pt );

					// Now tell choreo view
					CExpression *exp = active->GetExpression( m_nDragCell );
					if ( exp && maybeTool )
					{
						if ( IsWindowOrChild( g_pChoreoView, maybeTool ) )
						{
							if ( g_pChoreoView->CreateExpressionEvent( pt.x, pt.y, active, exp ) )
							{
								return iret;
							}
						}
					
						if ( IsWindowOrChild( g_pExpressionTool, maybeTool ) )
						{
							if ( g_pExpressionTool->SetFlexAnimationTrackFromExpression( pt.x, pt.y, active, exp ) )
							{
								return iret;
							}
						}
					}
				}
			}

			if ( active )
			{
				// Over a new cell
				if ( cell >= 0 && 
					cell < active->GetNumExpressions() && 
					cell != m_nCurCell &&
					m_nCurCell != -1 )
				{
					// Swap cells
					CExpression *exp = active->GetExpression( m_nCurCell );
					if ( exp )
					{
						active->SwapExpressionOrder( m_nCurCell, cell );
						active->SetDirty( true );
						active->SelectExpression( cell );
					}
				}
			}
		}
		break;
	case mxEvent::Size:
		{
			int width = w2();

			int ch = GetCaptionHeight();

			g_pExpressionClass->setBounds( 5, 5 + ch, width - 120, 20 );

			m_pABButton->setBounds( width - 60, 4 + ch, 60, 16 );
			m_pThumbnailIncreaseButton->setBounds( width - 60 - 40, 4 + ch, 16, 16 );
			m_pThumbnailDecreaseButton->setBounds( width - 60 - 20, 4 + ch, 16, 16 );

			m_nTopOffset = 0;
			RepositionSlider();

			redraw();
			iret = 1;
		}
		break;
	case mxEvent::MouseWheeled:
		{
			// Figure out cell #
			POINT pt;

			pt.x = event->x;
			pt.y = event->y;

			ScreenToClient( (HWND)getHandle(), &pt );

			if ( event->height < 0 )
			{
				m_nTopOffset = min( m_nTopOffset + 10, slScrollbar->getMaxValue() );
			}
			else
			{
				m_nTopOffset = max( m_nTopOffset - 10, 0 );
			}
			RepositionSlider();
			redraw();
			iret = 1;
		}
		break;
	};

	if ( iret )
	{
		SetActiveTool( this );
	}
	return iret;
}