| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- // VisWindowDialog.cpp : implementation file
- //
- #include "stdafx.h"
- #include "leveledit.h"
- #include "viswindowdialog.h"
- #include "visrasterizer.h"
- #include "visrendercontext.h"
- #include "pscene.h"
- #include "phys.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- /////////////////////////////////////////////////////////////////////////////
- //
- // VisWindowDialogClass
- //
- /////////////////////////////////////////////////////////////////////////////
- VisWindowDialogClass::VisWindowDialogClass(CWnd* pParent /*=NULL*/) :
- BitmapBits (NULL),
- Bitmap (NULL),
- Width (0),
- Height (0),
- MemDC (NULL),
- CurToolTipVisId(-1),
- CDialog(VisWindowDialogClass::IDD, pParent)
- {
- //{{AFX_DATA_INIT(VisWindowDialogClass)
- // NOTE: the ClassWizard will add member initialization here
- //}}AFX_DATA_INIT
- //
- // Create a screen compatible DC
- //
- MemDC = ::CreateCompatibleDC (NULL);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // ~VisWindowDialogClass
- //
- /////////////////////////////////////////////////////////////////////////////
- VisWindowDialogClass::~VisWindowDialogClass (void)
- {
- Free_DIB_Section ();
- ::DeleteDC (MemDC);
- MemDC = NULL;
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // DoDataExchange
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- VisWindowDialogClass::DoDataExchange (CDataExchange *pDX)
- {
- CDialog::DoDataExchange(pDX);
- //{{AFX_DATA_MAP(VisWindowDialogClass)
- // NOTE: the ClassWizard will add DDX and DDV calls here
- //}}AFX_DATA_MAP
- return ;
- }
- BEGIN_MESSAGE_MAP(VisWindowDialogClass, CDialog)
- //{{AFX_MSG_MAP(VisWindowDialogClass)
- ON_WM_PAINT()
- ON_WM_MOUSEMOVE()
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- //
- // Create
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- VisWindowDialogClass::Create (void)
- {
- CDialog::Create (VisWindowDialogClass::IDD, NULL);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnInitDialog
- //
- /////////////////////////////////////////////////////////////////////////////
- BOOL VisWindowDialogClass::OnInitDialog()
- {
- CDialog::OnInitDialog();
-
- // create the tool-tip
- if (ToolTip.Create(this, TTS_ALWAYSTIP) && ToolTip.AddTool(this))
- {
- ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, SHRT_MAX);
- ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_AUTOPOP, SHRT_MAX);
- ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, 200);
- ToolTip.SendMessage(TTM_SETDELAYTIME, TTDT_RESHOW, 200);
- }
- else
- {
- TRACE("Error in creating ToolTip");
- }
-
- return TRUE; // return TRUE unless you set the focus to a control
- // EXCEPTION: OCX Property Pages should return FALSE
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Update_Display
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- VisWindowDialogClass::Update_Display (VisRasterizerClass &rasterizer)
- {
- //
- // Don't do anything if the user has not enabled the vis window
- //
- if (m_hWnd == NULL || IsWindowVisible () == false) {
- return;
- }
- //
- // Get the resolution of rasterizer
- //
- int width = 0;
- int height = 0;
- rasterizer.Get_Resolution (&width, &height);
- //
- // Recreate DIB section
- //
- Create_DIB_Section (width, height);
- //
- // Loop over all the rows in the bitmap
- //
- int index = 0;
- int stride = (((Width * 3) + 3) & ~3);
- for (int row = 0; row < Height; row ++) {
- //
- // DIB sections are aligned on DWORD boundaries, so ensure
- // our starting index for this row is mapped appropriately.
- //
- index = row * stride;
-
- //
- // Get a pointer to the raw vis-render data for this row of the bitmap
- //
- const uint32 *pixel_ptr = rasterizer.Get_Pixel_Row (row, 0, Width - 1);
- //
- // Loop over all the columns of the bitmap
- //
- for (int col = 0; col < Width; col ++) {
- unsigned int id = pixel_ptr[col];// + 1;
- unsigned int pixel = Id_To_Pixel(id);
-
- //
- // Convert the pixel into red, green, and blue components
- //
- BYTE red = BYTE(pixel & 0x000000FF);
- BYTE green = BYTE((pixel & 0x0000FF00) >> 8);
- BYTE blue = BYTE((pixel & 0x00FF0000) >> 16);
-
- //
- // Store the pixel in the bitmap
- //
- BitmapBits[index ++] = blue;
- BitmapBits[index ++] = green;
- BitmapBits[index ++] = red;
- }
- }
- //
- // Update the window
- //
- Paint_Display ();
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Free_DIB_Section
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- VisWindowDialogClass::Free_DIB_Section (void)
- {
- Width = 0;
- Height = 0;
- //
- // Free the bitmap
- //
- if (Bitmap != NULL) {
- ::DeleteObject (Bitmap);
- Bitmap = NULL;
- }
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Create_DIB_Section
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- VisWindowDialogClass::Create_DIB_Section (int width, int height)
- {
- if (Width == width && Height == height) {
- return ;
- }
- //
- // Calculate what size to make the window
- //
- RECT rect = { 0, 0, width * 2, height * 2 };
- LONG style = ::GetWindowLong (m_hWnd, GWL_STYLE);
- ::AdjustWindowRect (&rect, style, FALSE);
- //
- // Resize the window
- //
- SetWindowPos (NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE);
- //
- // Release our old DIB section
- //
- Free_DIB_Section ();
- //
- // Cache the new width and height
- //
- Width = width;
- Height = height;
- //
- // Set-up the fields of the BITMAPINFOHEADER
- // Note: Top-down DIBs use negative height in Win32.
- //
- BITMAPINFOHEADER bitmap_info = { 0 };
- bitmap_info.biSize = sizeof (BITMAPINFOHEADER);
- bitmap_info.biWidth = Width;
- bitmap_info.biHeight = -Height;
- bitmap_info.biPlanes = 1;
- bitmap_info.biBitCount = 24;
- bitmap_info.biCompression = BI_RGB;
- bitmap_info.biSizeImage = ((Width * Height) * 3);
- bitmap_info.biXPelsPerMeter = 0;
- bitmap_info.biYPelsPerMeter = 0;
- bitmap_info.biClrUsed = 0;
- bitmap_info.biClrImportant = 0;
- //
- // Create a bitmap that we can access the bits directly of
- //
- HDC screen_dc = ::GetDC (NULL);
- Bitmap = ::CreateDIBSection ( screen_dc,
- (const BITMAPINFO *)&bitmap_info,
- DIB_RGB_COLORS,
- (void **)&BitmapBits,
- NULL,
- 0L);
- //
- // Release our temporary screen DC
- //
- ::ReleaseDC (NULL, screen_dc);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Paint_Display
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- VisWindowDialogClass::Paint_Display (void)
- {
- if (m_hWnd == NULL || Bitmap == NULL) {
- return ;
- }
- //
- // Setup the DCs for blitting
- //
- HDC wnd_dc = ::GetDC (m_hWnd);
- HBITMAP old_bmp = (HBITMAP)::SelectObject (MemDC, Bitmap);
- //
- // Copy the contents of the bitmap to the screen
- //
- ::StretchBlt (wnd_dc, 0, 0, Width * 2, Height * 2, MemDC, 0, 0, Width, Height, SRCCOPY);
- //
- // Restore the DCs
- //
- ::SelectObject (MemDC, old_bmp);
- ::ReleaseDC (m_hWnd, wnd_dc);
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnPaint
- //
- /////////////////////////////////////////////////////////////////////////////
- void
- VisWindowDialogClass::OnPaint (void)
- {
- CPaintDC dc (this);
- Paint_Display ();
- return ;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Hit_Test - determines the vis-id under the cursor
- //
- /////////////////////////////////////////////////////////////////////////////
- int
- VisWindowDialogClass::Hit_Test(CPoint point) const
- {
- //
- // If we don't have a bitmap, just return
- //
- if (BitmapBits == NULL) {
- return -1;
- }
- //
- // Look up the pixel, we are StretchBlt'ing the bitmap to 2x the normal size
- // so we divide the coordinates by two
- //
- int x = point.x / 2;
- int y = point.y / 2;
- if ((x <= 0) || (x >= Width) || (y <= 0) || (y >= Height)) {
- return -1;
- }
- int stride = (((Width * 3) + 3) & ~3);
- int pixel_address = x * 3 + stride * y;
- BYTE blue = BitmapBits[pixel_address ++];
- BYTE green = BitmapBits[pixel_address ++];
- BYTE red = BitmapBits[pixel_address ++];
- //
- // Map the color back to a vis ID
- //
- unsigned int color = red | (green<<8) | (blue<<16);
- unsigned int id = Pixel_To_Id(color);
- return id;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Id_To_Pixel
- //
- /////////////////////////////////////////////////////////////////////////////
- unsigned int
- VisWindowDialogClass::Id_To_Pixel(unsigned int id) const
- {
- uint32 pixel = 0;
- pixel |= ((id & 0x0000000F) >> 0) << 20; // LSN (Least Significant Nibble) goes into MSN of red
- pixel |= ((id & 0x000000F0) >> 4) << 12; // next LSN goes into MSN of green
- pixel |= ((id & 0x00000F00) >> 8) << 4; // next LSN goes into MSN of blue
- pixel |= ((id & 0x0000F000) >> 12) << 16; // put into LSN of red
- pixel |= ((id & 0x000F0000) >> 16) << 8; // put into LSN of green
- pixel |= ((id & 0x00F00000) >> 20) << 0; // put into LSN of blue
- return pixel;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // Pixel_To_Id
- //
- /////////////////////////////////////////////////////////////////////////////
- unsigned int
- VisWindowDialogClass::Pixel_To_Id(unsigned int pixel) const
- {
- uint32 id = 0;
- id |= ((pixel & 0x0000000F) >> 0) << 20;
- id |= ((pixel & 0x000000F0) >> 4) << 8;
- id |= ((pixel & 0x00000F00) >> 8) << 16;
- id |= ((pixel & 0x0000F000) >> 12) << 4;
- id |= ((pixel & 0x000F0000) >> 16) << 12;
- id |= ((pixel & 0x00F00000) >> 20) << 0;
- return id;
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // PreTranslateMessage
- //
- /////////////////////////////////////////////////////////////////////////////
- BOOL
- VisWindowDialogClass::PreTranslateMessage(MSG* pMsg)
- {
- if (::IsWindow(ToolTip.m_hWnd) && pMsg->hwnd == m_hWnd)
- {
- switch(pMsg->message)
- {
- case WM_LBUTTONDOWN:
- case WM_MOUSEMOVE:
- case WM_LBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_MBUTTONUP:
- ToolTip.RelayEvent(pMsg);
- break;
- }
- }
- return CDialog::PreTranslateMessage(pMsg);
- }
- /////////////////////////////////////////////////////////////////////////////
- //
- // OnMouseMove
- //
- /////////////////////////////////////////////////////////////////////////////
- void VisWindowDialogClass::OnMouseMove(UINT nFlags, CPoint point)
- {
- if (::IsWindow(ToolTip.m_hWnd))
- {
- unsigned int vis_id = Hit_Test(point);
- if ((vis_id == -1) || (vis_id != CurToolTipVisId)) {
- // Use Activate() to hide the tooltip.
- ToolTip.Activate(FALSE);
- }
- if (vis_id != -1) {
- ToolTip.Activate(TRUE);
- if (vis_id == BACKFACE_VIS_ID) {
- CString tooltip_string;
- tooltip_string.Format("Vis Id: %d, Backface!",vis_id);
- ToolTip.UpdateTipText(tooltip_string,this);
- } else {
- PhysClass * obj = NULL;
- RefPhysListIterator it = PhysicsSceneClass::Get_Instance()->Get_Static_Object_Iterator();
- while ((!it.Is_Done()) && (obj == NULL)) {
- if (it.Peek_Obj()->Get_Vis_Object_ID()==(int)vis_id) {
- obj = it.Peek_Obj();
- }
- it.Next();
- }
- if (obj != NULL) {
- CString tooltip_string;
- tooltip_string.Format("Vis Id: %d, Model Name: %s",vis_id,obj->Peek_Model()->Get_Name());
- ToolTip.UpdateTipText(tooltip_string,this);
- } else {
- CString tooltip_string;
- tooltip_string.Format("Vis Id: %d, Unknown Model",vis_id);
- ToolTip.UpdateTipText(tooltip_string,this);
- }
- }
- CurToolTipVisId = vis_id;
- }
- }
- CDialog::OnMouseMove(nFlags, point);
- }
|