// dxtexView.cpp : implementation of the CDxtexView class // #include "stdafx.h" #include "dxtex.h" #include "dxtexDoc.h" #include "dxtexView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Our custom vertex type struct CUSTOMVERTEX { FLOAT x, y, z; FLOAT rhw; DWORD color; FLOAT tu, tv; // The texture coordinates }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1) IMPLEMENT_DYNCREATE(CDxtexView, CScrollView) BEGIN_MESSAGE_MAP(CDxtexView, CScrollView) //{{AFX_MSG_MAP(CDxtexView) ON_WM_LBUTTONUP() ON_COMMAND(ID_FILE_OPENSUBSURFACE, OnFileOpenSubsurface) ON_COMMAND(ID_FILE_OPENALPHASUBSURFACE, OnFileOpenAlphaSubsurface) ON_COMMAND(ID_FILE_OPENFACE, OnFileOpenFace) ON_COMMAND(ID_FILE_OPENALPHAFACE, OnFileOpenAlphaFace) ON_COMMAND(ID_VIEW_ORIGINAL, OnViewOriginal) ON_COMMAND(ID_VIEW_COMPRESSED, OnViewCompressed) ON_COMMAND(ID_VIEW_SMALLERMIPLEVEL, OnViewSmallerMipLevel) ON_COMMAND(ID_VIEW_LARGERMIPLEVEL, OnViewLargerMipLevel) ON_COMMAND(ID_VIEW_ALPHACHANNEL, OnViewAlphaChannel) ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomIn) ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomOut) ON_COMMAND(ID_VIEW_CHANGEBACKGROUNDCOLOR, OnViewChangeBackgroundColor) ON_COMMAND(ID_VIEW_NEGX, OnViewNegX) ON_COMMAND(ID_VIEW_POSX, OnViewPosX) ON_COMMAND(ID_VIEW_NEGY, OnViewNegY) ON_COMMAND(ID_VIEW_POSY, OnViewPosY) ON_COMMAND(ID_VIEW_NEGZ, OnViewNegZ) ON_COMMAND(ID_VIEW_POSZ, OnViewPosZ) ON_COMMAND(ID_VIEW_HIGHERVOLUMESLICE, OnViewHigherVolumeSlice) ON_COMMAND(ID_VIEW_LOWERVOLUMESLICE, OnViewLowerVolumeSlice) ON_UPDATE_COMMAND_UI(ID_FILE_OPENSUBSURFACE, OnUpdateFileOpenSubsurface) ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHASUBSURFACE, OnUpdateFileOpenAlphaSubsurface) ON_UPDATE_COMMAND_UI(ID_FILE_OPENFACE, OnUpdateFileOpenFace) ON_UPDATE_COMMAND_UI(ID_FILE_OPENALPHAFACE, OnUpdateFileOpenAlphaFace) ON_UPDATE_COMMAND_UI(ID_VIEW_ORIGINAL, OnUpdateViewOriginal) ON_UPDATE_COMMAND_UI(ID_VIEW_COMPRESSED, OnUpdateViewCompressed) ON_UPDATE_COMMAND_UI(ID_VIEW_ALPHACHANNEL, OnUpdateViewAlphaChannel) ON_UPDATE_COMMAND_UI(ID_VIEW_LARGERMIPLEVEL, OnUpdateViewLargerMipLevel) ON_UPDATE_COMMAND_UI(ID_VIEW_SMALLERMIPLEVEL, OnUpdateViewSmallerMipLevel) ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMIN, OnUpdateViewZoomIn) ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMOUT, OnUpdateViewZoomOut) ON_UPDATE_COMMAND_UI(ID_VIEW_NEGX, OnUpdateViewNegX) ON_UPDATE_COMMAND_UI(ID_VIEW_POSX, OnUpdateViewPosX) ON_UPDATE_COMMAND_UI(ID_VIEW_NEGY, OnUpdateViewNegY) ON_UPDATE_COMMAND_UI(ID_VIEW_POSY, OnUpdateViewPosY) ON_UPDATE_COMMAND_UI(ID_VIEW_NEGZ, OnUpdateViewNegZ) ON_UPDATE_COMMAND_UI(ID_VIEW_POSZ, OnUpdateViewPosZ) ON_UPDATE_COMMAND_UI(ID_VIEW_HIGHERVOLUMESLICE, OnUpdateViewHigherVolumeSlice) ON_UPDATE_COMMAND_UI(ID_VIEW_LOWERVOLUMESLICE, OnUpdateViewLowerVolumeSlice) //}}AFX_MSG_MAP END_MESSAGE_MAP() CDxtexView::CDxtexView() { m_pVB = NULL; m_ptexCur = NULL; m_pSwapChain = NULL; m_lwMipCur = 0; m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD; m_lwSliceCur = -1; m_fZoom = 1.0f; m_bViewOrig = TRUE; m_bViewAlpha = FALSE; } CDxtexView::~CDxtexView() { ReleasePpo(&m_pVB); ReleasePpo(&m_ptexCur); ReleasePpo(&m_pSwapChain); } // Note: repaints don't require re-rendering, just recopy from back buffer to view's DC void CDxtexView::OnDraw(CDC* pDC) { CDxtexDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); HRESULT hr; CRect rcSrc; CRect rcDest; rcSrc = m_rcSrc; rcDest = m_rcDest; rcDest.OffsetRect(pDC->GetViewportOrg()); // REVIEW: only update dirty region? if (m_pSwapChain != NULL) hr = m_pSwapChain->Present(&rcSrc, &rcDest, GetSafeHwnd(), NULL); } #ifdef _DEBUG void CDxtexView::AssertValid() const { CScrollView::AssertValid(); } void CDxtexView::Dump(CDumpContext& dc) const { CScrollView::Dump(dc); } CDxtexDoc* CDxtexView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDxtexDoc))); return (CDxtexDoc*)m_pDocument; } #endif //_DEBUG void CDxtexView::OnLButtonUp(UINT nFlags, CPoint point) { // Button click means toggle compressed / uncompressed view if (m_bViewOrig) OnViewCompressed(); else OnViewOriginal(); CScrollView::OnLButtonUp(nFlags, point); } void CDxtexView::OnInitialUpdate() { #ifdef _WIN64 SetClassLongPtr(GetSafeHwnd(), GCLP_HBRBACKGROUND, (LONG_PTR)CreateSolidBrush(RGB(100, 100, 120))); #else SetClassLong(GetSafeHwnd(), GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(100, 100, 120))); #endif if (GetDocument()->IsCubeMap()) m_CubeFaceCur = D3DCUBEMAP_FACE_POSITIVE_X; else m_CubeFaceCur = D3DCUBEMAP_FACE_FORCE_DWORD; if (GetDocument()->IsVolumeMap()) m_lwSliceCur = 0; BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); UpdateDevice(); CreateVertexBuffer(); RenderScene(); SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height())); ResizeParentToFit(); CScrollView::OnInitialUpdate(); m_bTitleModsChanged = TRUE; // force title bar update } VOID CDxtexView::GetImageInfo(CString& strInfo) { LPDIRECT3DBASETEXTURE8 ptex; D3DSURFACE_DESC sd; D3DVOLUME_DESC vd; D3DFORMAT fmt; DWORD dwWidth; DWORD dwHeight; DWORD dwDepth; CString strFormat; TCHAR sz[100]; DWORD dwBytes = 0; UINT iLevel; if (m_bViewOrig) ptex = GetDocument()->PtexOrig(); else ptex = GetDocument()->PtexNew(); if (GetDocument()->IsVolumeMap()) { ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(0, &vd); fmt = vd.Format; dwWidth = vd.Width; dwHeight = vd.Height; dwDepth = vd.Depth; } else if (!GetDocument()->IsCubeMap()) { ((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(0, &sd); fmt = sd.Format; dwWidth = sd.Width; dwHeight = sd.Height; dwDepth = 0; } else { ((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(0, &sd); fmt = sd.Format; dwWidth = sd.Width; dwHeight = sd.Height; dwDepth = 0; } strFormat = FormatName(fmt); // Count bytes in main surface chain if (GetDocument()->IsVolumeMap()) { for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++) { ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(iLevel, &vd); dwBytes += vd.Size; } } else if (!GetDocument()->IsCubeMap()) { dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_FORCE_DWORD, ptex); } else { dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_X, ptex); dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_X, ptex); dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Y, ptex); dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Y, ptex); dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_POSITIVE_Z, ptex); dwBytes += NumBytesInSurfaces(D3DCUBEMAP_FACE_NEGATIVE_Z, ptex); } if (dwDepth == 0) wsprintf(sz, "%d x %d, %s, %d bytes", dwWidth, dwHeight, strFormat, dwBytes); else wsprintf(sz, "%d x %d x %d, %s, %d bytes", dwWidth, dwHeight, dwDepth, strFormat, dwBytes); strInfo = sz; } DWORD CDxtexView::NumBytesInSurfaces(D3DCUBEMAP_FACES FaceType, LPDIRECT3DBASETEXTURE8 ptex) { DWORD dwBytes = 0; LPDIRECT3DTEXTURE8 pmiptex = NULL; LPDIRECT3DCUBETEXTURE8 pcubetex = NULL; D3DSURFACE_DESC sd; DWORD iLevel; if (FaceType == D3DCUBEMAP_FACE_FORCE_DWORD) pmiptex = (LPDIRECT3DTEXTURE8)ptex; else pcubetex = (LPDIRECT3DCUBETEXTURE8)ptex; for (iLevel = 0; iLevel < GetDocument()->NumMips(); iLevel++) { if (pmiptex != NULL) pmiptex->GetLevelDesc(iLevel, &sd); else pcubetex->GetLevelDesc(iLevel, &sd); dwBytes += sd.Size; } return dwBytes; } HRESULT CDxtexView::UpdateDevice(VOID) { HRESULT hr; LPDIRECT3D8 pd3d = PDxtexApp()->Pd3d(); LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev(); D3DDISPLAYMODE dispMode; D3DPRESENT_PARAMETERS presentParams; pd3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode); ReleasePpo(&m_pSwapChain); ZeroMemory(&presentParams, sizeof(presentParams)); presentParams.Windowed = TRUE; presentParams.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC; presentParams.BackBufferWidth = m_rcSrc.Width(); presentParams.BackBufferHeight = m_rcSrc.Height(); presentParams.BackBufferFormat = dispMode.Format; if (FAILED(hr = pd3ddev->CreateAdditionalSwapChain(&presentParams, &m_pSwapChain))) return hr; COLORREF crBkgd; crBkgd = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255)); m_dwClearColor = D3DCOLOR_RGBA(GetRValue(crBkgd), GetGValue(crBkgd), GetBValue(crBkgd), 255); return S_OK; } HRESULT CDxtexView::CreateVertexBuffer(VOID) { LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev(); // Create the the vertex buffer if( FAILED( pd3ddev->CreateVertexBuffer( 6 * sizeof(CUSTOMVERTEX), 0 /* Usage */, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB ) ) ) { return E_FAIL; } return S_OK; } HRESULT CDxtexView::RenderScene(VOID) { CWaitCursor waitCursor; HRESULT hr; LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev(); LPDIRECT3DSURFACE8 psurf; if (m_pSwapChain == NULL) return E_FAIL; // Vertices for our quad CUSTOMVERTEX vertexArray[] = { // x, y, z, rhw, color { 0.0f, 0.0f, 0.5f, 1.0f, 0xffffffff, 0.0, 0.0, }, { (FLOAT)m_rcSrc.right, 0.0f, 0.5f, 1.0f, 0xffffffff, 1.0, 0.0, }, { (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, }, { (FLOAT)m_rcSrc.right, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 1.0, 1.0, }, { 0.0f, (FLOAT)m_rcSrc.bottom, 0.5f, 1.0f, 0xffffffff, 0.0, 1.0, }, { 0.0f, 0.0f, 0.5f, 1.0f, 0xffffffff, 0.0, 0.0, }, }; // Copy the global vertex data into the vertex buffer VOID* pVertices; if( FAILED( m_pVB->Lock( 0, sizeof(vertexArray), (BYTE**)&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, vertexArray, sizeof(vertexArray) ); m_pVB->Unlock(); hr = m_pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &psurf); hr = pd3ddev->SetRenderTarget(psurf, NULL); ReleasePpo(&psurf); hr = pd3ddev->Clear(0, NULL, D3DCLEAR_TARGET, m_dwClearColor, 0.0f, 0); hr = pd3ddev->BeginScene(); // If the texture uses premultiplied alpha, the source blend should be D3DBLEND_ONE // since RGB is already at the level we want. With nonpremultiplied alpha, the // source blend should be D3DBLEND_SRCALPHA. D3DSURFACE_DESC sd; m_ptexCur->GetLevelDesc(0, &sd); if (!m_bViewAlpha && (sd.Format == D3DFMT_DXT2 || sd.Format == D3DFMT_DXT4)) { if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE))) return hr; } else { if (FAILED(hr = pd3ddev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA))) return hr; } hr = pd3ddev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); hr = pd3ddev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pd3ddev->SetTexture(0, m_ptexCur); pd3ddev->SetStreamSource( 0, m_pVB, sizeof(CUSTOMVERTEX) ); pd3ddev->SetVertexShader( D3DFVF_CUSTOMVERTEX ); pd3ddev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ); pd3ddev->SetTexture(0, NULL); hr = pd3ddev->EndScene(); return S_OK; } void CDxtexView::OnViewOriginal() { if (GetDocument()->PtexOrig() == NULL) return; BuildViewSurface(TRUE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); RenderScene(); m_bTitleModsChanged = TRUE; // force title bar update InvalidateRect(&m_rcDest, FALSE); // force redraw of this view } void CDxtexView::OnViewCompressed() { if (GetDocument()->PtexNew() == NULL) return; BuildViewSurface(FALSE, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); RenderScene(); m_bTitleModsChanged = TRUE; // force title bar update InvalidateRect(&m_rcDest, FALSE); // force redraw of this view } void CDxtexView::OnUpdateViewOriginal(CCmdUI* pCmdUI) { if (GetDocument()->PtexOrig() == NULL) { pCmdUI->Enable(FALSE); pCmdUI->SetCheck(0); } else { pCmdUI->Enable(TRUE); pCmdUI->SetCheck(m_bViewOrig); } } void CDxtexView::OnUpdateViewCompressed(CCmdUI* pCmdUI) { if (GetDocument()->PtexNew() == NULL) { pCmdUI->Enable(FALSE); pCmdUI->SetCheck(0); } else { pCmdUI->Enable(TRUE); pCmdUI->SetCheck(!m_bViewOrig); } } void CDxtexView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { m_bTitleModsChanged = TRUE; // force title bar update if (lHint == 1) { BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); RenderScene(); } else if (lHint == 2) { UpdateDevice(); RenderScene(); } else if (lHint == 3) { RenderScene(); } CScrollView::OnUpdate(pSender, lHint, pHint); } void CDxtexView::OnViewSmallerMipLevel() { m_lwMipCur++; if (m_lwSliceCur > 0) m_lwSliceCur /= 2; BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); UpdateDevice(); RenderScene(); m_bTitleModsChanged = TRUE; // force title bar update SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height())); Invalidate(); // force redraw of this view } void CDxtexView::OnViewLargerMipLevel() { m_lwMipCur--; if (m_lwSliceCur > 0) m_lwSliceCur *= 2; BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); UpdateDevice(); RenderScene(); m_bTitleModsChanged = TRUE; // force title bar update SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height())); Invalidate(); // force redraw of this view } void CDxtexView::OnViewAlphaChannel(VOID) { BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, !m_bViewAlpha); RenderScene(); Invalidate(); // force redraw of this view m_bTitleModsChanged = TRUE; // force title bar update } void CDxtexView::OnUpdateViewAlphaChannel(CCmdUI* pCmdUI) { pCmdUI->SetCheck(m_bViewAlpha); } void CDxtexView::OnUpdateViewLargerMipLevel(CCmdUI* pCmdUI) { if (m_lwMipCur > 0) pCmdUI->Enable(TRUE); else pCmdUI->Enable(FALSE); } void CDxtexView::OnUpdateViewSmallerMipLevel(CCmdUI* pCmdUI) { if (m_lwMipCur < (LONG)GetDocument()->NumMips() - 1) pCmdUI->Enable(TRUE); else pCmdUI->Enable(FALSE); } void CDxtexView::OnViewZoomIn() { if (m_fZoom < 8.0f) m_fZoom *= 2.0f; m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom); m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom); SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height())); m_bTitleModsChanged = TRUE; // force title bar update Invalidate(); // force redraw of this view } void CDxtexView::OnViewZoomOut() { if (m_fZoom > 0.125f) m_fZoom /= 2.0f; m_rcDest.right = (LONG)(m_rcSrc.right * m_fZoom); m_rcDest.bottom = (LONG)(m_rcSrc.bottom * m_fZoom); SetScrollSizes(MM_TEXT, CSize(m_rcDest.Width(), m_rcDest.Height())); m_bTitleModsChanged = TRUE; // force title bar update Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewZoomIn(CCmdUI* pCmdUI) { pCmdUI->Enable(m_fZoom < 8.0f); } void CDxtexView::OnUpdateViewZoomOut(CCmdUI* pCmdUI) { pCmdUI->Enable(m_fZoom > 0.125f); } CString CDxtexView::GetStrTitleMods(VOID) { CString strTitleMods; strTitleMods = "("; // Append alpha, if in alpha mode if (m_bViewAlpha) strTitleMods += "Alpha, "; // Show format LPDIRECT3DBASETEXTURE8 ptex; CString strFormat; D3DFORMAT fmt; if (m_bViewOrig) ptex = GetDocument()->PtexOrig(); else ptex = GetDocument()->PtexNew(); if (GetDocument()->IsVolumeMap()) { D3DVOLUME_DESC vd; ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(0, &vd); fmt = vd.Format; } else if (!GetDocument()->IsCubeMap()) { D3DSURFACE_DESC sd; ((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(0, &sd); fmt = sd.Format; } else { D3DSURFACE_DESC sd; ((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(0, &sd); fmt = sd.Format; } strTitleMods += FormatName(fmt); strTitleMods += TEXT(", "); // Append cube map info, if a cube map switch (m_CubeFaceCur) { case D3DCUBEMAP_FACE_NEGATIVE_X: strTitleMods += "Negative X, "; break; case D3DCUBEMAP_FACE_POSITIVE_X: strTitleMods += "Positive X, "; break; case D3DCUBEMAP_FACE_NEGATIVE_Y: strTitleMods += "Negative Y, "; break; case D3DCUBEMAP_FACE_POSITIVE_Y: strTitleMods += "Positive Y, "; break; case D3DCUBEMAP_FACE_NEGATIVE_Z: strTitleMods += "Negative Z, "; break; case D3DCUBEMAP_FACE_POSITIVE_Z: strTitleMods += "Positive Z, "; break; } if (m_lwSliceCur >= 0) { CString strSlice; strSlice.Format("Slice %d of %d, ", m_lwSliceCur + 1, GetDocument()->DwDepthAt(m_lwMipCur)); strTitleMods += strSlice; } // Append mip info, if multiple mip levels DWORD dwNumMips = GetDocument()->NumMips(); if (dwNumMips > 1) { CString strMipInfo; strMipInfo.Format("Mip %d of %d, ", m_lwMipCur + 1, dwNumMips); strTitleMods += strMipInfo; } // Append view magnification CString strView; strView.Format("%d", (LONG)(100 * m_fZoom)); strTitleMods += strView + "%"; strTitleMods += ")"; return strTitleMods; } CString CDxtexView::FormatName(D3DFORMAT fmt) { CString str; switch (fmt) { case D3DFMT_A8R8G8B8: str = TEXT("A8R8G8B8"); break; case D3DFMT_A1R5G5B5: str = TEXT("A1R5G5B5"); break; case D3DFMT_A4R4G4B4: str = TEXT("A4R4G4B4"); break; case D3DFMT_R8G8B8: str = TEXT("R8G8B8"); break; case D3DFMT_R5G6B5: str = TEXT("R5G6B5"); break; case D3DFMT_X8R8G8B8: str = TEXT("X8R8G8B8"); break; case D3DFMT_X1R5G5B5: str = TEXT("X1R5G5B5"); break; case D3DFMT_R3G3B2: str = TEXT("R3G3B2"); break; case D3DFMT_A8R3G3B2: str = TEXT("A8R3G3B2"); break; case D3DFMT_X4R4G4B4: str = TEXT("X4R4G4B4"); break; case D3DFMT_DXT1: str = TEXT("DXT1"); break; case D3DFMT_DXT2: str = TEXT("DXT2"); break; case D3DFMT_DXT3: str = TEXT("DXT3"); break; case D3DFMT_DXT4: str = TEXT("DXT4"); break; case D3DFMT_DXT5: str = TEXT("DXT5"); break; default: str = TEXT("unknown fmt"); break; } return str; } void CDxtexView::OnViewChangeBackgroundColor() { CHOOSECOLOR cc; COLORREF crArray[16]; ZeroMemory(&cc, sizeof(cc)); cc.lStructSize = sizeof(cc); cc.hwndOwner = GetSafeHwnd(); cc.rgbResult = PDxtexApp()->GetProfileInt("Settings", "Background Color", RGB(0, 255, 255)); cc.lpCustColors = crArray; cc.Flags = CC_RGBINIT | CC_ANYCOLOR | CC_FULLOPEN; if (ChooseColor(&cc)) { PDxtexApp()->WriteProfileInt("Settings", "Background Color", cc.rgbResult); // Update all views of all documents of our one doc template POSITION posTemp = PDxtexApp()->GetFirstDocTemplatePosition(); CDocTemplate* pDocTemplate = PDxtexApp()->GetNextDocTemplate(posTemp); CDocument* pdoc; POSITION pos = pDocTemplate->GetFirstDocPosition(); while (pos != NULL) { pdoc = pDocTemplate->GetNextDoc(pos); pdoc->UpdateAllViews(NULL, 2); } } } void CDxtexView::OnFileOpenSubsurface() { GetDocument()->OpenSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur); } void CDxtexView::OnUpdateFileOpenSubsurface(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); } void CDxtexView::OnFileOpenAlphaSubsurface() { GetDocument()->OpenAlphaSubsurface(m_CubeFaceCur, m_lwMipCur, m_lwSliceCur); } void CDxtexView::OnUpdateFileOpenAlphaSubsurface(CCmdUI* pCmdUI) { pCmdUI->Enable(TRUE); } HRESULT CDxtexView::BuildViewSurface(BOOL bOrig, D3DCUBEMAP_FACES FaceType, LONG lwSlice, LONG lwMip, BOOL bViewAlpha) { HRESULT hr; LPDIRECT3DDEVICE8 pd3ddev = PDxtexApp()->Pd3ddev(); LPDIRECT3DBASETEXTURE8 ptex; BOOL bIsCubeMap = GetDocument()->IsCubeMap(); BOOL bIsVolumeMap = GetDocument()->IsVolumeMap(); D3DSURFACE_DESC sd; D3DVOLUME_DESC vd; ReleasePpo(&m_ptexCur); if (bIsVolumeMap && lwSlice == -1) lwSlice = 0; if (bIsCubeMap && FaceType == D3DCUBEMAP_FACE_FORCE_DWORD) FaceType = D3DCUBEMAP_FACE_POSITIVE_X; m_bViewOrig = bOrig; m_bViewAlpha = bViewAlpha; m_lwSliceCur = lwSlice; m_lwMipCur = lwMip; m_CubeFaceCur = FaceType; if (bOrig) ptex = GetDocument()->PtexOrig(); else ptex = GetDocument()->PtexNew(); if (bIsVolumeMap) { ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &vd); sd.Width = vd.Width; sd.Height = vd.Height; } else if (!bIsCubeMap) { ((LPDIRECT3DTEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &sd); } else { ((LPDIRECT3DCUBETEXTURE8)ptex)->GetLevelDesc(m_lwMipCur, &sd); } hr = pd3ddev->CreateTexture(sd.Width, sd.Height, 1, 0 /* Usage */, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_ptexCur); if (FAILED(hr)) return hr; m_rcSrc.SetRect(0, 0, sd.Width, sd.Height); m_rcDest.SetRect(0, 0, (INT)(sd.Width * m_fZoom), (INT)(sd.Height * m_fZoom)); LPDIRECT3DSURFACE8 psurfSrc = NULL; LPDIRECT3DSURFACE8 psurfDest = NULL; hr = m_ptexCur->GetSurfaceLevel(0, &psurfDest); if (bIsVolumeMap) { LPDIRECT3DVOLUME8 pvolSrc; hr = ((LPDIRECT3DVOLUMETEXTURE8)ptex)->GetVolumeLevel(m_lwMipCur, &pvolSrc); hr = LoadSurfaceFromVolumeSlice(pvolSrc, m_lwSliceCur, psurfDest); ReleasePpo(&pvolSrc); } else if (!bIsCubeMap) { hr = ((LPDIRECT3DTEXTURE8)ptex)->GetSurfaceLevel(m_lwMipCur, &psurfSrc); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0); } else { hr = ((LPDIRECT3DCUBETEXTURE8)ptex)->GetCubeMapSurface(FaceType, m_lwMipCur, &psurfSrc); hr = D3DXLoadSurfaceFromSurface(psurfDest, NULL, NULL, psurfSrc, NULL, NULL, D3DX_FILTER_TRIANGLE, 0); } if (bViewAlpha) { // Move alpha channels into RGB (and set alpha to 0xff) D3DLOCKED_RECT lr; hr = psurfDest->LockRect(&lr, NULL, 0); DWORD xp; DWORD yp; DWORD* pdwRow = (DWORD*)lr.pBits; DWORD* pdw; DWORD dwAlpha; LONG dataBytesPerRow = 4 * sd.Width; for (yp = 0; yp < sd.Height; yp++) { pdw = pdwRow; for (xp = 0; xp < sd.Width; xp++) { dwAlpha = *pdw >> 24; *pdw = 0xff000000 | (dwAlpha << 16) | (dwAlpha << 8) | (dwAlpha); pdw++; } pdwRow += lr.Pitch / 4; } psurfDest->UnlockRect(); } ReleasePpo(&psurfSrc); ReleasePpo(&psurfDest); return S_OK; } HRESULT CDxtexView::LoadSurfaceFromVolumeSlice(LPDIRECT3DVOLUME8 pVolume, UINT iSlice, LPDIRECT3DSURFACE8 psurf) { HRESULT hr; D3DVOLUME_DESC vd; D3DLOCKED_BOX lb; D3DBOX box; RECT rc; pVolume->GetDesc(&vd); box.Left = 0; box.Right = vd.Width; box.Top = 0; box.Bottom = vd.Height; box.Front = iSlice; box.Back = iSlice + 1; rc.left = 0; rc.right = vd.Width; rc.top = 0; rc.bottom = vd.Height; hr = pVolume->LockBox(&lb, &box, 0); if (FAILED(hr)) return hr; hr = D3DXLoadSurfaceFromMemory(psurf, NULL, NULL, lb.pBits, vd.Format, lb.RowPitch, NULL, &rc, D3DX_FILTER_TRIANGLE, 0); pVolume->UnlockBox(); return hr; } void CDxtexView::OnViewNegX() { BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); m_bTitleModsChanged = TRUE; // force title bar update RenderScene(); Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewNegX(CCmdUI* pCmdUI) { BOOL bEnable = GetDocument()->IsCubeMap(); pCmdUI->Enable(bEnable); pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_X); } void CDxtexView::OnViewPosX() { BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_X, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); m_bTitleModsChanged = TRUE; // force title bar update RenderScene(); Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewPosX(CCmdUI* pCmdUI) { BOOL bEnable = GetDocument()->IsCubeMap(); pCmdUI->Enable(bEnable); pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_X); } void CDxtexView::OnViewNegY() { BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); m_bTitleModsChanged = TRUE; // force title bar update RenderScene(); Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewNegY(CCmdUI* pCmdUI) { BOOL bEnable = GetDocument()->IsCubeMap(); pCmdUI->Enable(bEnable); pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Y); } void CDxtexView::OnViewPosY() { BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Y, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); m_bTitleModsChanged = TRUE; // force title bar update RenderScene(); Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewPosY(CCmdUI* pCmdUI) { BOOL bEnable = GetDocument()->IsCubeMap(); pCmdUI->Enable(bEnable); pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Y); } void CDxtexView::OnViewNegZ() { BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_NEGATIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); m_bTitleModsChanged = TRUE; // force title bar update RenderScene(); Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewNegZ(CCmdUI* pCmdUI) { BOOL bEnable = GetDocument()->IsCubeMap(); pCmdUI->Enable(bEnable); pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_NEGATIVE_Z); } void CDxtexView::OnViewPosZ() { BuildViewSurface(m_bViewOrig, D3DCUBEMAP_FACE_POSITIVE_Z, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); m_bTitleModsChanged = TRUE; // force title bar update RenderScene(); Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewPosZ(CCmdUI* pCmdUI) { BOOL bEnable = GetDocument()->IsCubeMap(); pCmdUI->Enable(bEnable); pCmdUI->SetCheck(m_CubeFaceCur == D3DCUBEMAP_FACE_POSITIVE_Z); } void CDxtexView::OnFileOpenFace() { GetDocument()->OpenCubeFace(m_CubeFaceCur); } void CDxtexView::OnUpdateFileOpenFace(CCmdUI* pCmdUI) { BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD); pCmdUI->Enable(bEnable); } void CDxtexView::OnFileOpenAlphaFace() { GetDocument()->OpenAlphaCubeFace(m_CubeFaceCur); } void CDxtexView::OnUpdateFileOpenAlphaFace(CCmdUI* pCmdUI) { BOOL bEnable = (m_CubeFaceCur != D3DCUBEMAP_FACE_FORCE_DWORD); pCmdUI->Enable(bEnable); } void CDxtexView::OnViewHigherVolumeSlice() { m_lwSliceCur++; BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); UpdateDevice(); RenderScene(); m_bTitleModsChanged = TRUE; // force title bar update Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewHigherVolumeSlice(CCmdUI* pCmdUI) { pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur < (LONG)GetDocument()->DwDepthAt(m_lwMipCur) - 1); } void CDxtexView::OnViewLowerVolumeSlice() { m_lwSliceCur--; BuildViewSurface(m_bViewOrig, m_CubeFaceCur, m_lwSliceCur, m_lwMipCur, m_bViewAlpha); UpdateDevice(); RenderScene(); m_bTitleModsChanged = TRUE; // force title bar update Invalidate(); // force redraw of this view } void CDxtexView::OnUpdateViewLowerVolumeSlice(CCmdUI* pCmdUI) { pCmdUI->Enable(GetDocument()->IsVolumeMap() && m_lwSliceCur > 0); }