mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 23:51:41 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
517
Code/Tools/LevelEdit/VisWindowDialog.cpp
Normal file
517
Code/Tools/LevelEdit/VisWindowDialog.cpp
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
** 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user