You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
771 lines
23 KiB
771 lines
23 KiB
14 years ago
|
/*==LICENSE==*
|
||
|
|
||
|
CyanWorlds.com Engine - MMOG client, server and tools
|
||
|
Copyright (C) 2011 Cyan Worlds, 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/>.
|
||
|
|
||
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||
|
or by snail mail at:
|
||
|
Cyan Worlds, Inc.
|
||
|
14617 N Newport Hwy
|
||
|
Mead, WA 99021
|
||
|
|
||
|
*==LICENSE==*/
|
||
|
#include "HeadSpin.h"
|
||
|
#include "max.h"
|
||
|
#include "resource.h"
|
||
|
#include "hsTemplates.h"
|
||
|
|
||
|
#include "pfGUISkinComp.h"
|
||
|
#include "plGUICompClassIDs.h"
|
||
|
|
||
|
#include "../MaxMain/plMaxNodeBase.h"
|
||
|
|
||
|
|
||
|
pfGUISkinEditProc *pfGUISkinEditProc::fInstance = nil;
|
||
|
int pfGUISkinEditProc::fZoom = 3; // So re-opening the dialog will keep the same zoom level
|
||
|
|
||
|
extern HINSTANCE hInstance;
|
||
|
|
||
|
pfGUISkinEditProc::pfGUISkinEditProc( plGUISkinComp *comp )
|
||
|
{
|
||
|
fInstance = this;
|
||
|
fComp = comp;
|
||
|
|
||
|
fDblDC = nil;
|
||
|
fDblBitmap = nil;
|
||
|
|
||
|
fXOffset = fYOffset = 0;
|
||
|
|
||
|
fCurrPBRefSet = plGUISkinComp::kRefUpLeftCorner;
|
||
|
|
||
|
fDefPen = CreatePen( PS_SOLID, 3, RGB( 200, 0, 0 ) );
|
||
|
fOtherPen = CreatePen( PS_DOT, 1, RGB( 200, 0, 0 ) );
|
||
|
|
||
|
fDragging = false;
|
||
|
fDragTimer = 0;
|
||
|
|
||
|
// Back up the old settings
|
||
|
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
|
||
|
for( int i = 0; i < pfGUISkin::kNumElements; i++ )
|
||
|
{
|
||
|
int id = i * 4 + plGUISkinComp::kRefUpLeftCorner;
|
||
|
fBackups[ i ].fX = pb->GetInt( id + 0 );
|
||
|
fBackups[ i ].fY = pb->GetInt( id + 1 );
|
||
|
fBackups[ i ].fWidth = pb->GetInt( id + 2 );
|
||
|
fBackups[ i ].fHeight = pb->GetInt( id + 3 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pfGUISkinEditProc::~pfGUISkinEditProc()
|
||
|
{
|
||
|
fInstance = nil;
|
||
|
DeleteObject( fDefPen );
|
||
|
IKillDblBuffer();
|
||
|
}
|
||
|
|
||
|
void pfGUISkinEditProc::IJustDrawOneRect( int whichElement, IParamBlock2 *pb, HDC hDC, HPEN whichPen, int refToIgnore )
|
||
|
{
|
||
|
whichElement = ( whichElement * 4 ) + plGUISkinComp::kRefUpLeftCorner;
|
||
|
|
||
|
if( whichElement == refToIgnore )
|
||
|
return;
|
||
|
|
||
|
RECT r;
|
||
|
SetRect( &r, pb->GetInt( whichElement + 0 ),
|
||
|
pb->GetInt( whichElement + 1 ),
|
||
|
pb->GetInt( whichElement + 0 ) + pb->GetInt( whichElement + 2 ),
|
||
|
pb->GetInt( whichElement + 1 ) + pb->GetInt( whichElement + 3 ) );
|
||
|
|
||
|
r.left *= fZoom; r.right *= fZoom; r.top *= fZoom; r.bottom *= fZoom;
|
||
|
|
||
|
SelectObject( hDC, whichPen );
|
||
|
int rop2 = SetROP2( hDC, R2_NOTXORPEN );
|
||
|
|
||
|
MoveToEx( hDC, r.left, r.top, nil );
|
||
|
LineTo( hDC, r.right, r.top );
|
||
|
LineTo( hDC, r.right, r.bottom );
|
||
|
LineTo( hDC, r.left, r.bottom );
|
||
|
LineTo( hDC, r.left, r.top );
|
||
|
|
||
|
SetROP2( hDC, rop2 );
|
||
|
}
|
||
|
|
||
|
void pfGUISkinEditProc::IRefreshDblBuffer( void )
|
||
|
{
|
||
|
// Image buffer is where we keep our resized image. Dbl buffer is where we draw our bounds
|
||
|
if( fDblDC == nil )
|
||
|
IInitDblBuffer();
|
||
|
else
|
||
|
{
|
||
|
// Copy the zoomed image as our backdrop
|
||
|
BitBlt( fDblDC, 0, 0, fDblWidth, fDblHeight, fImageDC, 0, 0, SRCCOPY );
|
||
|
|
||
|
RECT r;
|
||
|
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
|
||
|
if( pb != nil )
|
||
|
{
|
||
|
// Draw all the other elements other than our current one
|
||
|
for( int i = 0; i < pfGUISkin::kNumElements; i++ )
|
||
|
IJustDrawOneRect( i, pb, fDblDC, fOtherPen, fCurrPBRefSet );
|
||
|
|
||
|
// Now draw the bounds of our current element
|
||
|
SetRect( &r, pb->GetInt( fCurrPBRefSet + 0 ),
|
||
|
pb->GetInt( fCurrPBRefSet + 1 ),
|
||
|
pb->GetInt( fCurrPBRefSet + 0 ) + pb->GetInt( fCurrPBRefSet + 2 ),
|
||
|
pb->GetInt( fCurrPBRefSet + 1 ) + pb->GetInt( fCurrPBRefSet + 3 ) );
|
||
|
|
||
|
// While we have it here, go ahead and update our status text for this element
|
||
|
char str[ 256 ];
|
||
|
sprintf( str, "Left: %d\nTop: %d\nWidth: %d\nHeight: %d\n", r.left, r.top, r.right - r.left, r.bottom - r.top );
|
||
|
SetDlgItemText( fHWnd, IDC_GUI_INFO, str );
|
||
|
|
||
|
r.left *= fZoom; r.right *= fZoom; r.top *= fZoom; r.bottom *= fZoom;
|
||
|
|
||
|
SelectObject( fDblDC, fDefPen );
|
||
|
int rop2 = SetROP2( fDblDC, R2_NOTXORPEN );
|
||
|
|
||
|
MoveToEx( fDblDC, r.left, r.top, nil );
|
||
|
LineTo( fDblDC, r.right, r.top );
|
||
|
LineTo( fDblDC, r.right, r.bottom );
|
||
|
LineTo( fDblDC, r.left, r.bottom );
|
||
|
LineTo( fDblDC, r.left, r.top );
|
||
|
|
||
|
SetROP2( fDblDC, rop2 );
|
||
|
|
||
|
fCurrElemRect = r;
|
||
|
MapWindowPoints( GetDlgItem( fHWnd, IDC_GUI_PREVIEW ), fHWnd, (POINT *)&fCurrElemRect, 2 );
|
||
|
OffsetRect( &fCurrElemRect, -fXOffset, -fYOffset );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void pfGUISkinEditProc::IRefreshImageBuffer( void )
|
||
|
{
|
||
|
IInitDblBuffer();
|
||
|
|
||
|
plLayerTex *layer = fComp->GetSkinBitmap();
|
||
|
PBBitmap *pbBMap = layer->GetPBBitmap();
|
||
|
|
||
|
if( pbBMap->bm == nil )
|
||
|
pbBMap->Load();
|
||
|
if( pbBMap->bm != nil )
|
||
|
{
|
||
|
// Copy into a new temp bitmap that is the right format for us to read
|
||
|
Bitmap *newBM;
|
||
|
BitmapInfo bi;
|
||
|
bi.SetName( _T("y879873b") );
|
||
|
bi.SetType( BMM_TRUE_32 );
|
||
|
bi.SetFlags( MAP_HAS_ALPHA );
|
||
|
bi.SetWidth( fDblWidth );
|
||
|
bi.SetHeight( fDblHeight );
|
||
|
newBM = TheManager->Create( &bi );
|
||
|
|
||
|
BMM_Color_64 foo = { 0, 0, 0, 0 };
|
||
|
newBM->CopyImage( pbBMap->bm, COPY_IMAGE_RESIZE_LO_QUALITY, foo, nil );
|
||
|
|
||
|
// Now copy from our newly created bitmap into our DC....way slow :(
|
||
|
BITMAPINFO *bitInfo = newBM->ToDib( 24, nil, false );
|
||
|
if( bitInfo != nil )
|
||
|
{
|
||
|
SetDIBitsToDevice( fImageDC, 0, 0, fDblWidth, fDblHeight,
|
||
|
0, 0, 0, fDblHeight,
|
||
|
( (UInt8 *)bitInfo ) + bitInfo->bmiHeader.biSize,
|
||
|
bitInfo,
|
||
|
DIB_RGB_COLORS );
|
||
|
}
|
||
|
|
||
|
newBM->DeleteThis();
|
||
|
}
|
||
|
|
||
|
IRefreshDblBuffer();
|
||
|
}
|
||
|
|
||
|
void pfGUISkinEditProc::IInitDblBuffer( void )
|
||
|
{
|
||
|
if( fDblDC == NULL )
|
||
|
{
|
||
|
int width, height;
|
||
|
HDC desk = GetDC( NULL );
|
||
|
|
||
|
plLayerTex *layer = fComp->GetSkinBitmap();
|
||
|
PBBitmap *pbBMap = layer->GetPBBitmap();
|
||
|
if( pbBMap == nil )
|
||
|
return;
|
||
|
width = pbBMap->bi.Width() * fZoom;
|
||
|
height = pbBMap->bi.Height() * fZoom;
|
||
|
// GetClientRect( fHWnd, &r );
|
||
|
// width = r.right - r.left;
|
||
|
// height = r.bottom - r.top;
|
||
|
|
||
|
// Note: For some strange reason, grabbing the HDC of the window doesn't do
|
||
|
// any good, 'cause it's black-and-white (right, THAT makes sense). Grabbing
|
||
|
// the desktop DC works, however.
|
||
|
|
||
|
fDblDC = CreateCompatibleDC( desk );
|
||
|
fDblBitmap = CreateCompatibleBitmap( desk/*fDblDC*/, width, height );
|
||
|
SelectObject( fDblDC, fDblBitmap );
|
||
|
|
||
|
fImageDC = CreateCompatibleDC( desk );
|
||
|
fImageBitmap = CreateCompatibleBitmap( desk/*fDblDC*/, width, height );
|
||
|
SelectObject( fImageDC, fImageBitmap );
|
||
|
|
||
|
ReleaseDC( NULL, desk );
|
||
|
|
||
|
fDblWidth = width;
|
||
|
fDblHeight = height;
|
||
|
|
||
|
ISetScrollRanges();
|
||
|
IRefreshImageBuffer();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void pfGUISkinEditProc::IKillDblBuffer( void )
|
||
|
{
|
||
|
if( fDblDC != NULL )
|
||
|
{
|
||
|
SelectObject( fDblDC, (HBITMAP)NULL );
|
||
|
DeleteObject( fDblBitmap );
|
||
|
DeleteDC( fDblDC );
|
||
|
}
|
||
|
|
||
|
if( fImageDC != NULL )
|
||
|
{
|
||
|
SelectObject( fImageDC, (HBITMAP)NULL );
|
||
|
DeleteObject( fImageBitmap );
|
||
|
DeleteDC( fImageDC );
|
||
|
}
|
||
|
|
||
|
fDblDC = fImageDC = nil;
|
||
|
fDblBitmap = fImageBitmap = nil;
|
||
|
}
|
||
|
|
||
|
void pfGUISkinEditProc::ISetScrollRanges( void )
|
||
|
{
|
||
|
SCROLLINFO info;
|
||
|
|
||
|
|
||
|
int visW = fPreviewRect.right - fPreviewRect.left;
|
||
|
int visH = fPreviewRect.bottom - fPreviewRect.top;
|
||
|
|
||
|
if( visW < fDblWidth )
|
||
|
{
|
||
|
if( fXOffset > fDblWidth - visW )
|
||
|
fXOffset = fDblWidth - visW;
|
||
|
else if( fXOffset < 0 )
|
||
|
fXOffset = 0;
|
||
|
|
||
|
info.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
|
||
|
info.nMin = 0;
|
||
|
info.nMax = fDblWidth;// - visW;
|
||
|
info.nPage = visW;
|
||
|
info.nPos = fXOffset;
|
||
|
info.cbSize = sizeof( info );
|
||
|
|
||
|
SetScrollInfo( GetDlgItem( fHWnd, IDC_GUI_HORZSCROLL ), SB_CTL, &info, true );
|
||
|
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_HORZSCROLL ), true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_HORZSCROLL ), false );
|
||
|
fXOffset = 0;
|
||
|
}
|
||
|
|
||
|
if( visH < fDblHeight )
|
||
|
{
|
||
|
if( fYOffset > fDblHeight - visH )
|
||
|
fYOffset = fDblHeight - visH;
|
||
|
else if( fYOffset < 0 )
|
||
|
fYOffset = 0;
|
||
|
|
||
|
info.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
|
||
|
info.nMin = 0;
|
||
|
info.nMax = fDblHeight;// - visH;
|
||
|
info.nPage = visH;
|
||
|
info.nPos = fYOffset;
|
||
|
info.cbSize = sizeof( info );
|
||
|
|
||
|
SetScrollInfo( GetDlgItem( fHWnd, IDC_GUI_VERTSCROLL ), SB_CTL, &info, true );
|
||
|
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_VERTSCROLL ), true );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShowWindow( GetDlgItem( fHWnd, IDC_GUI_VERTSCROLL ), false );
|
||
|
fYOffset = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool pfGUISkinEditProc::IPointWithinRange( int x, int y, int ptX, int ptY )
|
||
|
{
|
||
|
if( x > ptX - kRangeSlop && x < ptX + kRangeSlop &&
|
||
|
y > ptY - kRangeSlop && y < ptY + kRangeSlop )
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool pfGUISkinEditProc::IPointWithinVertRange( int x, int y, int ptX, int ptY1, int ptY2 )
|
||
|
{
|
||
|
if( x > ptX - kRangeSlop && x < ptX + kRangeSlop &&
|
||
|
y > ptY1 - kRangeSlop && y < ptY2 + kRangeSlop )
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool pfGUISkinEditProc::IPointWithinHorzRange( int x, int y, int ptX1, int ptX2, int ptY )
|
||
|
{
|
||
|
if( x > ptX1 - kRangeSlop && x < ptX2 + kRangeSlop &&
|
||
|
y > ptY - kRangeSlop && y < ptY + kRangeSlop )
|
||
|
return true;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
UInt8 pfGUISkinEditProc::IGetDragTypeFlags( int x, int y )
|
||
|
{
|
||
|
// Corners
|
||
|
if( IPointWithinRange( x, y, fCurrElemRect.left, fCurrElemRect.top ) )
|
||
|
return kLeft | kTop;
|
||
|
if( IPointWithinRange( x, y, fCurrElemRect.right, fCurrElemRect.top ) )
|
||
|
return kRight | kTop;
|
||
|
if( IPointWithinRange( x, y, fCurrElemRect.right, fCurrElemRect.bottom ) )
|
||
|
return kRight | kBottom;
|
||
|
if( IPointWithinRange( x, y, fCurrElemRect.left, fCurrElemRect.bottom ) )
|
||
|
return kLeft | kBottom;
|
||
|
|
||
|
// Edges
|
||
|
if( IPointWithinVertRange( x, y, fCurrElemRect.left, fCurrElemRect.top, fCurrElemRect.bottom ) )
|
||
|
return kLeft;
|
||
|
if( IPointWithinVertRange( x, y, fCurrElemRect.right, fCurrElemRect.top, fCurrElemRect.bottom ) )
|
||
|
return kRight;
|
||
|
|
||
|
if( IPointWithinHorzRange( x, y, fCurrElemRect.left, fCurrElemRect.right, fCurrElemRect.top ) )
|
||
|
return kTop;
|
||
|
if( IPointWithinHorzRange( x, y, fCurrElemRect.left, fCurrElemRect.right, fCurrElemRect.bottom ) )
|
||
|
return kBottom;
|
||
|
|
||
|
// The middle
|
||
|
if( x >= fCurrElemRect.left && x <= fCurrElemRect.right && y >= fCurrElemRect.top && y <= fCurrElemRect.bottom )
|
||
|
return kDragAll;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
INT_PTR CALLBACK pfGUISkinEditProc::DlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
return fInstance->DialogProc( hDlg, msg, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
INT_PTR CALLBACK pfGUISkinEditProc::DialogProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
PAINTSTRUCT pInfo;
|
||
|
RECT r;
|
||
|
HDC hDC;
|
||
|
int maxDim, i, j, x, y;
|
||
|
bool timerActive = false;
|
||
|
|
||
|
|
||
|
static struct plElemPair
|
||
|
{
|
||
|
pfGUISkin::Elements el;
|
||
|
const char *name;
|
||
|
} sElemPairs[] = { { pfGUISkin::kUpLeftCorner, "Upper-left Corner" },
|
||
|
{ pfGUISkin::kTopSpan, "Top Span" },
|
||
|
{ pfGUISkin::kUpRightCorner, "Upper-right Corner" },
|
||
|
{ pfGUISkin::kRightSpan, "Right Span" },
|
||
|
{ pfGUISkin::kLowerRightCorner, "Lower-right Corner" },
|
||
|
{ pfGUISkin::kBottomSpan, "Bottom Span" },
|
||
|
{ pfGUISkin::kLowerLeftCorner, "Lower-left Corner" },
|
||
|
{ pfGUISkin::kLeftSpan, "Left Span" },
|
||
|
{ pfGUISkin::kMiddleFill, "Middle Fill" },
|
||
|
{ pfGUISkin::kSelectedFill, "Selected Middle Fill" },
|
||
|
{ pfGUISkin::kSubMenuArrow, "Sub-Menu Arrow" },
|
||
|
{ pfGUISkin::kSelectedSubMenuArrow, "Selected Sub-Menu Arrow" },
|
||
|
{ pfGUISkin::kTreeButtonClosed, "Tree-view Button, Closed" },
|
||
|
{ pfGUISkin::kTreeButtonOpen, "Tree-view Button, Open" },
|
||
|
{ pfGUISkin::kNumElements, nil } };
|
||
|
|
||
|
|
||
|
fHWnd = hDlg;
|
||
|
|
||
|
switch( msg )
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
|
||
|
// Get preview rect
|
||
|
GetClientRect( GetDlgItem( hDlg, IDC_GUI_PREVIEW ), &fPreviewRect );
|
||
|
MapWindowPoints( GetDlgItem( hDlg, IDC_GUI_PREVIEW ), hDlg, (POINT *)&fPreviewRect, 2 );
|
||
|
|
||
|
SendDlgItemMessage( hDlg, IDC_GUI_ZIN, BM_SETIMAGE, (WPARAM)IMAGE_ICON,
|
||
|
(LPARAM)LoadImage( hInstance, MAKEINTRESOURCE( IDI_ZOOMIN ), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR ) );
|
||
|
SendDlgItemMessage( hDlg, IDC_GUI_ZOUT, BM_SETIMAGE, (WPARAM)IMAGE_ICON,
|
||
|
(LPARAM)LoadImage( hInstance, MAKEINTRESOURCE( IDI_ZOOMOUT ), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR ) );
|
||
|
|
||
|
// Fill element list
|
||
|
SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_RESETCONTENT, 0, 0 );
|
||
|
for( i = 0; sElemPairs[ i ].el != pfGUISkin::kNumElements; i++ )
|
||
|
{
|
||
|
int idx = SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_ADDSTRING, 0, (LPARAM)sElemPairs[ i ].name );
|
||
|
SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_SETITEMDATA, (WPARAM)idx, (LPARAM)sElemPairs[ i ].el );
|
||
|
if( sElemPairs[ i ].el == pfGUISkin::kUpLeftCorner )
|
||
|
j = idx;
|
||
|
}
|
||
|
SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_SETCURSEL, j, 0 );
|
||
|
|
||
|
fOrigCursor = LoadCursor( nil, IDC_ARROW );//GetCursor();
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
if( LOWORD( wParam ) == IDCANCEL )
|
||
|
{
|
||
|
// Since we've been editing the PB directly, we have to now restore them
|
||
|
// to their original values
|
||
|
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
|
||
|
for( int i = 0; i < pfGUISkin::kNumElements; i++ )
|
||
|
{
|
||
|
int id = i * 4 + plGUISkinComp::kRefUpLeftCorner;
|
||
|
pb->SetValue( id + 0, 0, (int)fBackups[ i ].fX );
|
||
|
pb->SetValue( id + 1, 0, (int)fBackups[ i ].fY );
|
||
|
pb->SetValue( id + 2, 0, (int)fBackups[ i ].fWidth );
|
||
|
pb->SetValue( id + 3, 0, (int)fBackups[ i ].fHeight );
|
||
|
}
|
||
|
EndDialog( hDlg, 1 );
|
||
|
}
|
||
|
else if( LOWORD( wParam ) == IDOK )
|
||
|
EndDialog( hDlg, 0 );
|
||
|
else if( LOWORD( wParam ) == IDC_GUI_ZIN )
|
||
|
{
|
||
|
fXOffset /= fZoom; fYOffset /= fZoom;
|
||
|
fZoom++;
|
||
|
fXOffset *= fZoom; fYOffset *= fZoom;
|
||
|
|
||
|
IKillDblBuffer();
|
||
|
IRefreshImageBuffer();
|
||
|
InvalidateRect( hDlg, &fPreviewRect, false );
|
||
|
}
|
||
|
else if( LOWORD( wParam ) == IDC_GUI_ZOUT )
|
||
|
{
|
||
|
if( fZoom > 1 )
|
||
|
{
|
||
|
fXOffset /= fZoom; fYOffset /= fZoom;
|
||
|
fZoom--;
|
||
|
fXOffset *= fZoom; fYOffset *= fZoom;
|
||
|
|
||
|
IKillDblBuffer();
|
||
|
IRefreshImageBuffer();
|
||
|
InvalidateRect( hDlg, &fPreviewRect, false );
|
||
|
}
|
||
|
}
|
||
|
else if( LOWORD( wParam ) == IDC_GUI_ELEMENTS )
|
||
|
{
|
||
|
int idx = SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_GETCURSEL, 0, 0 );
|
||
|
fCurrPBRefSet = SendDlgItemMessage( hDlg, IDC_GUI_ELEMENTS, LB_GETITEMDATA, (WPARAM)idx, 0 ) * 4 + plGUISkinComp::kRefUpLeftCorner;
|
||
|
|
||
|
IRefreshDblBuffer();
|
||
|
InvalidateRect( hDlg, &fPreviewRect, false );
|
||
|
}
|
||
|
return true;
|
||
|
|
||
|
case WM_CLOSE:
|
||
|
EndDialog( hDlg, 0 );
|
||
|
return true;
|
||
|
|
||
|
case WM_HSCROLL:
|
||
|
OffsetRect( &fCurrElemRect, fXOffset, fYOffset );
|
||
|
switch( LOWORD( wParam ) )
|
||
|
{
|
||
|
case SB_PAGEUP: fXOffset -= 300; break;
|
||
|
case SB_PAGEDOWN: fXOffset += 300; break;
|
||
|
case SB_LINEUP: fXOffset -= 16; break;
|
||
|
case SB_LINEDOWN: fXOffset += 16; break;
|
||
|
case SB_THUMBPOSITION:
|
||
|
case SB_THUMBTRACK:
|
||
|
fXOffset = HIWORD( wParam );
|
||
|
break;
|
||
|
}
|
||
|
maxDim = fDblWidth - ( fPreviewRect.right - fPreviewRect.left );
|
||
|
if( fXOffset < 0 )
|
||
|
fXOffset = 0;
|
||
|
else if( fXOffset > maxDim )
|
||
|
fXOffset = maxDim;
|
||
|
SetScrollPos( GetDlgItem( hDlg, IDC_GUI_HORZSCROLL ), SB_CTL, fXOffset, true );
|
||
|
|
||
|
OffsetRect( &fCurrElemRect, -fXOffset, -fYOffset );
|
||
|
InvalidateRect( hDlg, &fPreviewRect, false );
|
||
|
break;
|
||
|
|
||
|
case WM_VSCROLL:
|
||
|
OffsetRect( &fCurrElemRect, fXOffset, fYOffset );
|
||
|
switch( LOWORD( wParam ) )
|
||
|
{
|
||
|
case SB_PAGEUP: fYOffset -= 300; break;
|
||
|
case SB_PAGEDOWN: fYOffset += 300; break;
|
||
|
case SB_LINEUP: fYOffset -= 16; break;
|
||
|
case SB_LINEDOWN: fYOffset += 16; break;
|
||
|
case SB_THUMBPOSITION:
|
||
|
case SB_THUMBTRACK:
|
||
|
fYOffset = HIWORD( wParam );
|
||
|
break;
|
||
|
}
|
||
|
maxDim = fDblHeight - ( fPreviewRect.bottom - fPreviewRect.top );
|
||
|
if( fYOffset < 0 )
|
||
|
fYOffset = 0;
|
||
|
else if( fYOffset > maxDim )
|
||
|
fYOffset = maxDim;
|
||
|
SetScrollPos( GetDlgItem( hDlg, IDC_GUI_VERTSCROLL ), SB_CTL, fYOffset, true );
|
||
|
|
||
|
OffsetRect( &fCurrElemRect, -fXOffset, -fYOffset );
|
||
|
InvalidateRect( hDlg, &fPreviewRect, false );
|
||
|
break;
|
||
|
|
||
|
case WM_PAINT:
|
||
|
{
|
||
|
BeginPaint( hDlg, &pInfo );
|
||
|
hDC = (HDC)pInfo.hdc;
|
||
|
|
||
|
if( fDblDC == NULL )
|
||
|
IInitDblBuffer();
|
||
|
|
||
|
int width = fDblWidth;
|
||
|
int height = fDblHeight;
|
||
|
if( width > fPreviewRect.right - fPreviewRect.left )
|
||
|
width = fPreviewRect.right - fPreviewRect.left;
|
||
|
if( height > fPreviewRect.bottom - fPreviewRect.top )
|
||
|
height = fPreviewRect.bottom - fPreviewRect.top;
|
||
|
|
||
|
BitBlt( hDC, fPreviewRect.left, fPreviewRect.top, width, height, fDblDC, fXOffset, fYOffset, SRCCOPY );
|
||
|
|
||
|
r = fPreviewRect;
|
||
|
r.left += width;
|
||
|
FillRect( hDC, &r, ColorMan()->GetBrush( kBackground ) );
|
||
|
|
||
|
r = fPreviewRect;
|
||
|
r.top += height;
|
||
|
FillRect( hDC, &r, ColorMan()->GetBrush( kBackground ) );
|
||
|
|
||
|
EndPaint( hDlg, &pInfo );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONDOWN:
|
||
|
SetCapture( hDlg );
|
||
|
fDragging = true;
|
||
|
fDragType = IGetDragTypeFlags( GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) );
|
||
|
if( fDragType == kDragAll )
|
||
|
{
|
||
|
fDragOffsetX = fCurrElemRect.left - GET_X_LPARAM( lParam );
|
||
|
fDragOffsetY = fCurrElemRect.top - GET_Y_LPARAM( lParam );
|
||
|
}
|
||
|
else if( fDragType == 0 )
|
||
|
{
|
||
|
fDragOffsetX = GET_X_LPARAM( lParam ) + fXOffset;
|
||
|
fDragOffsetY = GET_Y_LPARAM( lParam ) + fYOffset;
|
||
|
}
|
||
|
else
|
||
|
fDragOffsetX = fDragOffsetY = 0;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONUP:
|
||
|
ReleaseCapture();
|
||
|
fDragging = false;
|
||
|
break;
|
||
|
|
||
|
case WM_TIMER:
|
||
|
// We do the same processing as MOUSEMOVE, but we need to make sure we have the right
|
||
|
// mouse position first
|
||
|
{
|
||
|
POINT pt;
|
||
|
GetCursorPos( &pt );
|
||
|
MapWindowPoints( nil, hDlg, &pt, 1 );
|
||
|
lParam = MAKELPARAM( pt.x, pt.y );
|
||
|
}
|
||
|
// Fall thru...
|
||
|
|
||
|
case WM_MOUSEMOVE:
|
||
|
x = GET_X_LPARAM( lParam );
|
||
|
y = GET_Y_LPARAM( lParam );
|
||
|
|
||
|
if( fDragging )
|
||
|
{
|
||
|
if( fDragType == 0 )
|
||
|
{
|
||
|
fXOffset = fDragOffsetX - x;
|
||
|
fYOffset = fDragOffsetY - y;
|
||
|
ISetScrollRanges(); // Will clamp offset \for us
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Translate x and y into bitmap space
|
||
|
POINT pt;
|
||
|
pt.x = x;
|
||
|
pt.y = y;
|
||
|
|
||
|
if( PtInRect( &fPreviewRect, pt ) )
|
||
|
{
|
||
|
MapWindowPoints( hDlg, GetDlgItem( hDlg, IDC_GUI_PREVIEW ), &pt, 1 );
|
||
|
|
||
|
pt.x += fDragOffsetX;
|
||
|
pt.y += fDragOffsetY;
|
||
|
|
||
|
// Note the + 1/2 zoom so it's the closest pixel by center, not by area
|
||
|
x = ( pt.x + fXOffset + ( fZoom >> 1 ) ) / fZoom;
|
||
|
y = ( pt.y + fYOffset + ( fZoom >> 1 ) ) / fZoom;
|
||
|
|
||
|
// Set depending on our current drag flags
|
||
|
// Note the logic here: if we drag left, we want width and left changing,
|
||
|
// if we drag both, just left, if we drag right, just width
|
||
|
IParamBlock2 *pb = fComp->GetParamBlockByID( plComponent::kBlkComp );
|
||
|
if( fDragType & kLeft )
|
||
|
{
|
||
|
if( fDragType & kRight )
|
||
|
pb->SetValue( fCurrPBRefSet + 0, 0, (int)x );
|
||
|
else
|
||
|
{
|
||
|
int old = pb->GetInt( fCurrPBRefSet + 0 ) + pb->GetInt( fCurrPBRefSet + 2 );
|
||
|
|
||
|
pb->SetValue( fCurrPBRefSet + 0, 0, (int)x );
|
||
|
pb->SetValue( fCurrPBRefSet + 2, 0, (int)old - x );
|
||
|
}
|
||
|
}
|
||
|
else if( fDragType & kRight )
|
||
|
pb->SetValue( fCurrPBRefSet + 2, 0, (int)x - pb->GetInt( fCurrPBRefSet + 0 ) );
|
||
|
|
||
|
if( fDragType & kTop )
|
||
|
{
|
||
|
if( fDragType & kBottom )
|
||
|
pb->SetValue( fCurrPBRefSet + 1, 0, (int)y );
|
||
|
else
|
||
|
{
|
||
|
int old = pb->GetInt( fCurrPBRefSet + 1 ) + pb->GetInt( fCurrPBRefSet + 3 );
|
||
|
|
||
|
pb->SetValue( fCurrPBRefSet + 1, 0, (int)y );
|
||
|
pb->SetValue( fCurrPBRefSet + 3, 0, (int)old - y );
|
||
|
}
|
||
|
}
|
||
|
else if( fDragType & kBottom )
|
||
|
pb->SetValue( fCurrPBRefSet + 3, 0, (int)y - pb->GetInt( fCurrPBRefSet + 1 ) );
|
||
|
|
||
|
// Clamp width and height
|
||
|
if( pb->GetInt( fCurrPBRefSet + 2 ) < 0 )
|
||
|
pb->SetValue( fCurrPBRefSet + 2, 0, (int)0 );
|
||
|
if( pb->GetInt( fCurrPBRefSet + 3 ) < 0 )
|
||
|
pb->SetValue( fCurrPBRefSet + 3, 0, (int)0 );
|
||
|
|
||
|
// Clamp X and Y
|
||
|
if( pb->GetInt( fCurrPBRefSet + 0 ) < 0 )
|
||
|
pb->SetValue( fCurrPBRefSet + 0, 0, (int)0 );
|
||
|
else if( pb->GetInt( fCurrPBRefSet + 0 ) + pb->GetInt( fCurrPBRefSet + 2 ) > fDblWidth / fZoom )
|
||
|
pb->SetValue( fCurrPBRefSet + 0, 0, (int)fDblWidth / fZoom - pb->GetInt( fCurrPBRefSet + 2 ) );
|
||
|
|
||
|
if( pb->GetInt( fCurrPBRefSet + 1 ) < 0 )
|
||
|
pb->SetValue( fCurrPBRefSet + 1, 0, (int)0 );
|
||
|
else if( pb->GetInt( fCurrPBRefSet + 1 ) + pb->GetInt( fCurrPBRefSet + 3 ) > fDblHeight / fZoom )
|
||
|
pb->SetValue( fCurrPBRefSet + 1, 0, (int)fDblHeight / fZoom - pb->GetInt( fCurrPBRefSet + 3 ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Mouse is outside our preview, so scroll if possible
|
||
|
int dX = ( x < fPreviewRect.left ) ? x - fPreviewRect.left : ( x > fPreviewRect.right ) ? x - fPreviewRect.right : 0;
|
||
|
int dY = ( y < fPreviewRect.top ) ? y - fPreviewRect.top : ( y > fPreviewRect.bottom ) ? y - fPreviewRect.bottom : 0;
|
||
|
|
||
|
fXOffset += dX;
|
||
|
fYOffset += dY;
|
||
|
OffsetRect( &fCurrElemRect, -dX, -dY );
|
||
|
|
||
|
ISetScrollRanges(); // Will clamp origin for us
|
||
|
|
||
|
// Don't actually drag our bounds, 'cause we're scrolling
|
||
|
|
||
|
// Note: since we only get MOUSEMOVE when, gee, the mouse moves, if we've scrolled over, it'll only
|
||
|
// do it once and then wait for the mouse to nudge again. We'd rather it keep going until the user
|
||
|
// moves the mouse again, so we create a timer that calls us back in n somethingths so we can check again
|
||
|
if( fDragTimer == 0 )
|
||
|
fDragTimer = SetTimer( hDlg, 0, 200, nil );
|
||
|
timerActive = true; // So we don't kill it at the end here...
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IRefreshDblBuffer();
|
||
|
InvalidateRect( hDlg, &fPreviewRect, false );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UInt8 dragType = IGetDragTypeFlags( x, y );
|
||
|
HCURSOR cursor;
|
||
|
switch( dragType )
|
||
|
{
|
||
|
case kLeft | kTop:
|
||
|
case kRight | kBottom:
|
||
|
cursor = LoadCursor( nil, IDC_SIZENWSE );
|
||
|
break;
|
||
|
case kLeft | kBottom:
|
||
|
case kRight | kTop:
|
||
|
cursor = LoadCursor( nil, IDC_SIZENESW );
|
||
|
break;
|
||
|
case kLeft:
|
||
|
case kRight:
|
||
|
cursor = LoadCursor( nil, IDC_SIZEWE );
|
||
|
break;
|
||
|
case kTop:
|
||
|
case kBottom:
|
||
|
cursor = LoadCursor( nil, IDC_SIZENS );
|
||
|
break;
|
||
|
case kLeft | kTop | kRight | kBottom:
|
||
|
cursor = LoadCursor( nil, IDC_SIZEALL );
|
||
|
break;
|
||
|
default:
|
||
|
{
|
||
|
POINT pt;
|
||
|
pt.x = x;
|
||
|
pt.y = y;
|
||
|
if( PtInRect( &fPreviewRect, pt ) )
|
||
|
cursor = LoadCursor( nil, IDC_HAND );
|
||
|
else
|
||
|
cursor = fOrigCursor;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SetCursor( cursor );
|
||
|
|
||
|
if( !timerActive )
|
||
|
{
|
||
|
// No longer need our trick timer, so kill it
|
||
|
KillTimer( hDlg, fDragTimer );
|
||
|
fDragTimer = 0;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
plGUISkinComp *plGUISkinComp::GetGUIComp( INode *node )
|
||
|
{
|
||
|
if( node == nil )
|
||
|
return nil;
|
||
|
|
||
|
plComponentBase *base = ( ( plMaxNodeBase *)node )->ConvertToComponent();
|
||
|
if( base == nil )
|
||
|
return nil;
|
||
|
|
||
|
if( base->ClassID() == GUI_SKIN_CLASSID )
|
||
|
return (plGUISkinComp *)base;
|
||
|
|
||
|
return nil;
|
||
|
}
|
||
|
|