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.
1389 lines
42 KiB
1389 lines
42 KiB
/*==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/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
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 "hsStream.h" |
|
#include "hsTemplates.h" |
|
#include "hsWindows.h" |
|
|
|
#include <max.h> |
|
|
|
#include "resource.h" |
|
#pragma hdrstop |
|
|
|
#include "plAgeDescInterface.h" |
|
|
|
#include "plAgeDescription/plAgeDescription.h" |
|
#include "plMaxCFGFile.h" |
|
|
|
|
|
#ifdef MAXASS_AVAILABLE |
|
# include "../../AssetMan/PublicInterface/MaxAssInterface.h" |
|
#endif |
|
#include "plMaxAccelerators.h" |
|
|
|
extern HINSTANCE hInstance; |
|
|
|
//// Tree Data Wrapper Class ////////////////////////////////////////////////// |
|
|
|
class plAgeFile |
|
{ |
|
protected: |
|
void IGetAgeName(const plFileName& path) |
|
{ |
|
fAgeName = path.GetFileNameNoExt(); |
|
} |
|
|
|
public: |
|
#ifdef MAXASS_VAILABLE |
|
jvUniqueId fAssetID; |
|
#endif |
|
plFileName fPath; |
|
plString fAgeName; |
|
|
|
enum Types |
|
{ |
|
kAssetFile, |
|
kLocalFile |
|
}; |
|
Types fType; |
|
|
|
plAgeFile(Types type) : fType(type) { } |
|
plAgeFile(Types type, const plFileName &path) : fPath(path), fType(type) |
|
{ |
|
IGetAgeName(path); |
|
} |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
plAgeFile(Types type, const plFileName &path, jvUniqueId& id) |
|
: fPath(path), fType(type), fAssetID(id) |
|
{ |
|
IGetAgeName(path); |
|
} |
|
#endif |
|
}; |
|
|
|
//// Static Tree Helpers ////////////////////////////////////////////////////// |
|
|
|
static HTREEITEM SAddTreeItem( HWND hTree, HTREEITEM hParent, const char *label, int userData ); |
|
static int SGetTreeData( HWND tree, HTREEITEM item ); |
|
|
|
static void RemovePageItem( HWND listBox, int item ) |
|
{ |
|
plAgePage *page = (plAgePage *)ListBox_GetItemData( listBox, item ); |
|
delete page; |
|
ListBox_DeleteString( listBox, item ); |
|
} |
|
|
|
//// Dummy Dialog Proc //////////////////////////////////////////////////////// |
|
|
|
BOOL CALLBACK DumbDialogProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam ) |
|
{ |
|
switch( msg ) |
|
{ |
|
case WM_COMMAND: |
|
EndDialog( hDlg, LOWORD( wParam ) ); |
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
|
|
|
|
//// Constructor/Destructor /////////////////////////////////////////////////// |
|
|
|
plAgeDescInterface::plAgeDescInterface() : fhDlg(nil), fDirty(false), fSpin(nil), fCurAge(-1) |
|
{ |
|
fCurrAgeCheckedOut = false; |
|
fBoldFont = nil; |
|
fAssetManIface = nil; |
|
|
|
// Make sure the date/time picker controls we need are initialized |
|
INITCOMMONCONTROLSEX icc; |
|
icc.dwSize = sizeof(INITCOMMONCONTROLSEX); |
|
icc.dwICC = ICC_DATE_CLASSES; |
|
InitCommonControlsEx(&icc); |
|
} |
|
|
|
plAgeDescInterface::~plAgeDescInterface() |
|
{ |
|
IClearAgeFiles(fAgeFiles); |
|
|
|
DeleteObject( fBoldFont ); |
|
DeleteObject( fHiliteBrush ); |
|
fBoldFont = nil; |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
delete fAssetManIface; |
|
fAssetManIface = nil; |
|
#endif |
|
} |
|
|
|
plAgeDescInterface& plAgeDescInterface::Instance() |
|
{ |
|
static plAgeDescInterface theInstance; |
|
return theInstance; |
|
} |
|
|
|
void plAgeDescInterface::Open() |
|
{ |
|
if (!fhDlg) |
|
{ |
|
CreateDialog(hInstance, |
|
MAKEINTRESOURCE(IDD_AGE_DESC), |
|
GetCOREInterface()->GetMAXHWnd(), |
|
ForwardDlgProc); |
|
|
|
GetCOREInterface()->RegisterDlgWnd(fhDlg); |
|
ShowWindow(fhDlg, SW_SHOW); |
|
} |
|
} |
|
|
|
BOOL CALLBACK plAgeDescInterface::ForwardDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
return Instance().DlgProc(hDlg, msg, wParam, lParam); |
|
} |
|
|
|
BOOL plAgeDescInterface::DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
switch (msg) |
|
{ |
|
case WM_INITDIALOG: |
|
fhDlg = hDlg; |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
if( fAssetManIface == nil ) |
|
fAssetManIface = new MaxAssBranchAccess(); |
|
#endif |
|
|
|
// Make our bold font by getting the normal font and bolding |
|
if( fBoldFont == nil ) |
|
{ |
|
HFONT origFont = (HFONT)SendMessage( hDlg, WM_GETFONT, 0, 0 ); |
|
LOGFONT origInfo, newInfo; |
|
GetObject( origFont, sizeof( origInfo ), &origInfo ); |
|
memcpy( &newInfo, &origInfo, sizeof( newInfo ) ); |
|
newInfo.lfWeight = FW_BOLD; |
|
|
|
fBoldFont = CreateFontIndirect( &newInfo ); |
|
} |
|
|
|
if( fHiliteBrush == nil ) |
|
fHiliteBrush = CreateSolidBrush( RGB( 255, 0, 0 ) ); |
|
|
|
IInitControls(); |
|
IFillAgeTree(); |
|
return TRUE; |
|
|
|
case WM_DESTROY: |
|
#ifdef MAXASS_AVAILABLE |
|
delete fAssetManIface; |
|
fAssetManIface = nil; |
|
#endif |
|
return TRUE; |
|
|
|
// Day length spinner changed |
|
case CC_SPINNER_CHANGE: |
|
if (LOWORD(wParam) == IDC_DAYLEN_SPINNER || |
|
LOWORD(wParam) == IDC_CAP_SPINNER || |
|
LOWORD(wParam) == IDC_SEQPREFIX_SPIN ) |
|
{ |
|
fDirty = true; |
|
return TRUE; |
|
} |
|
break; |
|
|
|
case WM_CLOSE: |
|
::SendMessage( fhDlg, WM_COMMAND, IDOK, 0 ); |
|
return true; |
|
|
|
case WM_COMMAND: |
|
switch (LOWORD(wParam)) |
|
{ |
|
case IDOK: |
|
case IDCANCEL: |
|
if( IMakeSureCheckedIn() ) |
|
{ |
|
#ifdef MAXASS_AVAILABLE |
|
IUpdateCurAge(); |
|
#endif |
|
DestroyWindow(fhDlg); |
|
fhDlg = nil; |
|
fDirty = false; |
|
fCurAge = -1; |
|
fSpin = nil; |
|
} |
|
return TRUE; |
|
|
|
// case IDC_AGE_LIST: |
|
// if (HIWORD(wParam) == LBN_SELCHANGE) |
|
// { |
|
// IUpdateCurAge(); |
|
// return TRUE; |
|
// } |
|
// break; |
|
|
|
case IDC_AGE_CHECKOUT: |
|
ICheckOutCurrentAge(); |
|
return TRUE; |
|
|
|
case IDC_AGE_CHECKIN: |
|
ICheckInCurrentAge(); |
|
return TRUE; |
|
|
|
case IDC_AGE_UNDOCHECKOUT: |
|
IUndoCheckOutCurrentAge(); |
|
return TRUE; |
|
|
|
case IDC_AGE_NEW: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
INewAge(); |
|
return TRUE; |
|
} |
|
break; |
|
|
|
case IDC_PAGE_NEW: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
INewPage(); |
|
return TRUE; |
|
} |
|
break; |
|
|
|
case IDC_PAGE_DEL: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
HWND hPage = GetDlgItem(hDlg, IDC_PAGE_LIST); |
|
int sel = ListBox_GetCurSel(hPage); |
|
if (sel != LB_ERR) |
|
{ |
|
RemovePageItem( hPage, sel ); |
|
fDirty = true; |
|
} |
|
return TRUE; |
|
} |
|
break; |
|
|
|
case IDC_PAGE_LIST: |
|
if( HIWORD( wParam ) == LBN_SELCHANGE ) |
|
{ |
|
// Sel change |
|
HWND list = GetDlgItem( hDlg, IDC_PAGE_LIST ); |
|
int sel = ListBox_GetCurSel( list ); |
|
if( sel != LB_ERR ) |
|
{ |
|
IEnablePageControls(true); |
|
|
|
plAgePage *page = (plAgePage *)ListBox_GetItemData( list, sel ); |
|
CheckDlgButton( hDlg, IDC_ADM_DONTLOAD, ( page->GetFlags() & plAgePage::kPreventAutoLoad ) ? TRUE : FALSE ); |
|
CheckDlgButton( hDlg, IDC_ADM_LOADSDL, ( page->GetFlags() & plAgePage::kLoadIfSDLPresent ) ? TRUE : FALSE ); |
|
CheckDlgButton( hDlg, IDC_ADM_LOCAL_ONLY, ( page->GetFlags() & plAgePage::kIsLocalOnly ) ? TRUE : FALSE ); |
|
CheckDlgButton( hDlg, IDC_ADM_VOLATILE, ( page->GetFlags() & plAgePage::kIsVolatile ) ? TRUE : FALSE ); |
|
} |
|
else |
|
IEnablePageControls(false); |
|
} |
|
break; |
|
|
|
case IDC_ADM_DONTLOAD: |
|
case IDC_ADM_LOADSDL: |
|
case IDC_ADM_LOCAL_ONLY: |
|
case IDC_ADM_VOLATILE: |
|
ICheckedPageFlag(LOWORD(wParam)); |
|
break; |
|
|
|
case IDC_EDITREG: |
|
// Ask the user to make sure they really want to do this |
|
if( GetAsyncKeyState( VK_SHIFT ) & (~1) ) |
|
{ |
|
if( MessageBox( hDlg, "Are you sure you wish to reassign the sequence prefix for this age?", "WARNING", MB_YESNO | MB_ICONEXCLAMATION ) == IDYES ) |
|
{ |
|
int32_t prefix = (int32_t)IGetNextFreeSequencePrefix( IsDlgButtonChecked( hDlg, IDC_RSVDCHECK ) ); |
|
fSeqPrefixSpin->SetValue( ( prefix >= 0 ) ? prefix : -prefix, false ); |
|
fDirty = true; |
|
} |
|
} |
|
else |
|
{ |
|
if( MessageBox( hDlg, "Editing the registry data for an age can be extremely dangerous and " |
|
"can cause instabilities and crashes, particularly with multiplayer. " |
|
"Are you sure you want to do this?", "WARNING", MB_YESNO | MB_ICONEXCLAMATION ) == IDYES ) |
|
{ |
|
// Enable the controls |
|
EnableWindow( GetDlgItem( hDlg, IDC_RSVDCHECK ), TRUE ); |
|
EnableWindow( GetDlgItem( hDlg, IDC_SEQPREFIX_EDIT ), TRUE ); |
|
EnableWindow( GetDlgItem( hDlg, IDC_SEQPREFIX_SPIN ), TRUE ); |
|
} |
|
} |
|
return TRUE; |
|
|
|
case IDC_RSVDCHECK: |
|
fDirty = true; |
|
return FALSE; // Still process as normal |
|
|
|
case IDC_BRANCHCOMBO: |
|
if( HIWORD( wParam ) == CBN_SELCHANGE ) |
|
{ |
|
int idx = SendDlgItemMessage( hDlg, IDC_BRANCHCOMBO, CB_GETCURSEL, 0, 0 ); |
|
if( idx != CB_ERR ) |
|
{ |
|
int id = SendDlgItemMessage( hDlg, IDC_BRANCHCOMBO, CB_GETITEMDATA, idx, 0 ); |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
fAssetManIface->SetCurrBranch( id ); |
|
#endif |
|
IFillAgeTree(); |
|
} |
|
} |
|
return TRUE; |
|
} |
|
break; |
|
|
|
case WM_PAINT: |
|
PAINTSTRUCT paintInfo; |
|
|
|
BeginPaint( hDlg, &paintInfo ); |
|
|
|
if( fCurrAgeCheckedOut ) |
|
{ |
|
RECT r; |
|
HWND dummy = GetDlgItem( hDlg, IDC_AGEDESC ); |
|
GetClientRect( dummy, &r ); |
|
MapWindowPoints( dummy, hDlg, (POINT *)&r, 2 ); |
|
|
|
for( int i = 0; i < 3; i++ ) |
|
{ |
|
InflateRect( &r, -1, -1 ); |
|
FrameRect( paintInfo.hdc, &r, fHiliteBrush ); |
|
} |
|
} |
|
|
|
EndPaint( hDlg, &paintInfo ); |
|
return TRUE; |
|
|
|
case WM_NOTIFY: |
|
{ |
|
NMHDR *hdr = (NMHDR*)lParam; |
|
|
|
// Message from the start date/time controls |
|
if (hdr->idFrom == IDC_DATE || hdr->idFrom == IDC_TIME) |
|
{ |
|
if (hdr->code == NM_KILLFOCUS) |
|
{ |
|
plMaxAccelerators::Enable(); |
|
return TRUE; |
|
} |
|
else if (hdr->code == NM_SETFOCUS) |
|
{ |
|
plMaxAccelerators::Disable(); |
|
return TRUE; |
|
} |
|
// Time or date changed, set dirty |
|
else if (hdr->code == DTN_DATETIMECHANGE) |
|
{ |
|
fDirty = true; |
|
return TRUE; |
|
} |
|
} |
|
else if( hdr->idFrom == IDC_AGE_LIST ) |
|
{ |
|
if( hdr->code == NM_CUSTOMDRAW ) |
|
{ |
|
// Custom draw notifications for our treeView control |
|
LPNMTVCUSTOMDRAW treeNotify = (LPNMTVCUSTOMDRAW)lParam; |
|
|
|
if( treeNotify->nmcd.dwDrawStage == CDDS_PREPAINT ) |
|
{ |
|
// Sent at the start of redraw, lets us request more specific notifys |
|
SetWindowLong( hDlg, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW ); |
|
return TRUE; |
|
} |
|
else if( treeNotify->nmcd.dwDrawStage == CDDS_ITEMPREPAINT ) |
|
{ |
|
// Prepaint on an item. We get to change item font and color here |
|
int idx = SGetTreeData( hdr->hwndFrom, (HTREEITEM)treeNotify->nmcd.dwItemSpec ); |
|
/* if( item == nil || item->fType != plAgeFile::kBranch ) |
|
{ |
|
// Default drawing, with default font and such |
|
SetWindowLong( hDlg, DWL_MSGRESULT, CDRF_DODEFAULT ); |
|
return TRUE; |
|
} |
|
*/ |
|
// Color change (only if the item isn't selected) |
|
if( (HTREEITEM)treeNotify->nmcd.dwItemSpec != TreeView_GetSelection( hdr->hwndFrom ) ) |
|
{ |
|
treeNotify->clrText = GetColorManager()->GetColor( kText ); |
|
treeNotify->clrTextBk = GetColorManager()->GetColor( kWindow ); |
|
} |
|
|
|
if (idx == -1) |
|
{ |
|
// Set a bold font for the branch headers |
|
if( fBoldFont != nil ) |
|
SelectObject( treeNotify->nmcd.hdc, fBoldFont ); |
|
} |
|
|
|
// Let Windows know we changed the font |
|
SetWindowLong( hDlg, DWL_MSGRESULT, CDRF_NEWFONT ); |
|
return TRUE; |
|
} |
|
else |
|
// Let the default handle it |
|
return FALSE; |
|
} |
|
else if( hdr->code == TVN_SELCHANGING ) |
|
{ |
|
SetWindowLong( hDlg, DWL_MSGRESULT, !IMakeSureCheckedIn() ); |
|
return TRUE; |
|
} |
|
else if( hdr->code == TVN_SELCHANGED ) |
|
{ |
|
// Update the viewing age |
|
IUpdateCurAge(); |
|
return TRUE; |
|
} |
|
} |
|
} |
|
break; |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
void plAgeDescInterface::ICheckedPageFlag(int ctrlID) |
|
{ |
|
HWND hList = GetDlgItem(fhDlg, IDC_PAGE_LIST); |
|
int sel = ListBox_GetCurSel(hList); |
|
if (sel == LB_ERR) |
|
return; |
|
|
|
plAgePage* page = (plAgePage*)ListBox_GetItemData(hList, sel); |
|
bool isChecked = (IsDlgButtonChecked(fhDlg, ctrlID) == BST_CHECKED); |
|
|
|
if (ctrlID == IDC_ADM_DONTLOAD) |
|
{ |
|
if (isChecked) |
|
{ |
|
page->SetFlags(plAgePage::kPreventAutoLoad, true); |
|
|
|
// Doesn't make sense to have loadWithSDL checked too |
|
CheckDlgButton(fhDlg, IDC_ADM_LOADSDL, FALSE); |
|
page->SetFlags(plAgePage::kLoadIfSDLPresent, false); |
|
} |
|
else |
|
page->SetFlags(plAgePage::kPreventAutoLoad, false); |
|
} |
|
else if (ctrlID == IDC_ADM_LOADSDL) |
|
{ |
|
if (isChecked) |
|
{ |
|
page->SetFlags(plAgePage::kLoadIfSDLPresent, true); |
|
|
|
// Doesn't make sense to have dontLoad checked too |
|
CheckDlgButton(fhDlg, IDC_ADM_DONTLOAD, FALSE); |
|
page->SetFlags(plAgePage::kPreventAutoLoad, false); |
|
} |
|
else |
|
page->SetFlags(plAgePage::kLoadIfSDLPresent, false); |
|
} |
|
else if (ctrlID == IDC_ADM_LOCAL_ONLY) |
|
{ |
|
page->SetFlags(plAgePage::kIsLocalOnly, isChecked); |
|
} |
|
else if (ctrlID == IDC_ADM_VOLATILE) |
|
{ |
|
page->SetFlags(plAgePage::kIsVolatile, isChecked); |
|
} |
|
} |
|
|
|
void plAgeDescInterface::ICheckOutCurrentAge( void ) |
|
{ |
|
#ifdef MAXASS_AVAILABLE |
|
hsAssert( !fCurrAgeCheckedOut, "Trying to re-check out an age!" ); |
|
|
|
plAgeFile *currAge = IGetCurrentAge(); |
|
if( currAge == nil ) |
|
{ |
|
hsAssert( false, "How are you checking out an age if none is selected?" ); |
|
return; |
|
} |
|
|
|
if( currAge->fType != plAgeFile::kAssetFile ) |
|
return; |
|
|
|
// Check it out from AssetMan |
|
bool checkOutSuccess = (*fAssetManIface)->CheckOutAsset( currAge->fAssetID, fCheckedOutPath, sizeof( fCheckedOutPath ) ); |
|
if( !checkOutSuccess ) |
|
{ |
|
hsMessageBox( "Unable to check out age file from AssetMan. Most likely somebody already has it checked out.", "Error", hsMessageBoxNormal ); |
|
return; |
|
} |
|
#endif |
|
fCurrAgeCheckedOut = true; |
|
|
|
// Make sure we loaded the latest version |
|
ILoadAge( fCheckedOutPath, true ); |
|
|
|
IInvalidateCheckOutIndicator(); |
|
IEnableControls( true ); |
|
} |
|
|
|
void plAgeDescInterface::ICheckInCurrentAge( void ) |
|
{ |
|
#ifdef MAXASS_AVAILABLE |
|
hsAssert( fCurrAgeCheckedOut, "Trying to check in an age when none is checked out!" ); |
|
|
|
plAgeFile *currAge = IGetCurrentAge(); |
|
if( currAge == nil ) |
|
{ |
|
hsAssert( false, "How are you checking in an age if none is selected?" ); |
|
return; |
|
} |
|
|
|
// Save the sucker |
|
ISaveCurAge( fCheckedOutPath ); |
|
|
|
// Check the age file back in to AssetMan |
|
(*fAssetManIface)->CheckInAsset( currAge->fAssetID, fCheckedOutPath, "" ); |
|
fCurrAgeCheckedOut = false; |
|
#endif |
|
|
|
IInvalidateCheckOutIndicator(); |
|
IEnableControls( true ); |
|
} |
|
|
|
void plAgeDescInterface::IUndoCheckOutCurrentAge( void ) |
|
{ |
|
#ifdef MAXASS_AVAILABLE |
|
hsAssert( fCurrAgeCheckedOut, "Trying to undo check out an age when none is checked out!" ); |
|
|
|
plAgeFile *currAge = IGetCurrentAge(); |
|
if( currAge == nil ) |
|
{ |
|
hsAssert( false, "How are you undoing a checkout if no age is selected?" ); |
|
return; |
|
} |
|
|
|
// Check the age file back in to AssetMan |
|
(*fAssetManIface)->UndoCheckOutAsset(currAge->fAssetID); |
|
fCurrAgeCheckedOut = false; |
|
|
|
// Reload the non-saved version |
|
ILoadAge( fCheckedOutPath ); |
|
#endif |
|
|
|
IInvalidateCheckOutIndicator(); |
|
IEnableControls( true ); |
|
} |
|
|
|
void plAgeDescInterface::IInvalidateCheckOutIndicator( void ) |
|
{ |
|
RECT r; |
|
HWND dummy = GetDlgItem( fhDlg, IDC_AGEDESC ); |
|
GetClientRect( dummy, &r ); |
|
MapWindowPoints( dummy, fhDlg, (POINT *)&r, 2 ); |
|
|
|
RedrawWindow( fhDlg, &r, nil, RDW_INVALIDATE | RDW_ERASE ); |
|
} |
|
|
|
bool plAgeDescInterface::IMakeSureCheckedIn( void ) |
|
{ |
|
#ifdef MAXASS_AVAILABLE |
|
int result; |
|
plAgeFile* currAge = IGetCurrentAge(); |
|
if (!currAge) |
|
return true; |
|
|
|
if ( currAge->fType == plAgeFile::kAssetFile && fCurrAgeCheckedOut ) |
|
{ |
|
// We're switching away from an age we have checked out--ask what they want to do |
|
result = DialogBox( hInstance, MAKEINTRESOURCE( IDD_AGE_CHECKIN ), |
|
GetCOREInterface()->GetMAXHWnd(), DumbDialogProc ); |
|
if( result == IDCANCEL ) |
|
{ |
|
// Got cancelled |
|
return false; |
|
} |
|
else if( result == IDYES ) |
|
{ |
|
ICheckInCurrentAge(); |
|
} |
|
else |
|
{ |
|
IUndoCheckOutCurrentAge(); |
|
} |
|
} |
|
else if( currAge->fType == plAgeFile::kLocalFile && fDirty ) |
|
{ |
|
// Ask if we want to save changes |
|
result = DialogBox( hInstance, MAKEINTRESOURCE( IDD_AGE_SAVEYESNO ), |
|
GetCOREInterface()->GetMAXHWnd(), DumbDialogProc ); |
|
if( result == IDCANCEL ) |
|
{ |
|
// Got cancelled |
|
return false; |
|
} |
|
else if( result == IDYES ) |
|
{ |
|
ISaveCurAge( currAge->fPath.c_str() ); |
|
} |
|
else |
|
{ |
|
// Reload the non-saved version |
|
ILoadAge( currAge->fPath.c_str() ); |
|
} |
|
IEnableControls( true ); |
|
} |
|
#endif |
|
|
|
return true; |
|
} |
|
|
|
void plAgeDescInterface::IUpdateCurAge( void ) |
|
{ |
|
// Get the current age selection |
|
plAgeFile *currAge = IGetCurrentAge(); |
|
|
|
if (currAge == nil) |
|
{ |
|
ISetControlDefaults(); |
|
IEnableControls( false ); |
|
return; |
|
} |
|
|
|
IEnableControls( true ); |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
if( currAge->fType == plAgeFile::kAssetFile ) |
|
{ |
|
// Gotta get the latest version from assetMan before loading |
|
char localFilename[ MAX_PATH ]; |
|
if( !(*fAssetManIface)->GetLatestVersionFile( currAge->fAssetID, localFilename, sizeof( localFilename ) ) ) |
|
{ |
|
hsMessageBox( "Unable to get latest version of age asset from AssetMan. Things are about to get very funky...", "ERROR", hsMessageBoxNormal ); |
|
} |
|
else |
|
{ |
|
ILoadAge( localFilename ); |
|
} |
|
} |
|
else |
|
#endif |
|
// Load the local age, also check its sequence #s |
|
ILoadAge( currAge->fPath, true ); |
|
} |
|
|
|
static const int kDefaultCapacity = 10; |
|
|
|
void plAgeDescInterface::IInitControls() |
|
{ |
|
#ifdef MAXASS_AVAILABLE |
|
// Fill the branch combo box |
|
SendDlgItemMessage( fhDlg, IDC_BRANCHCOMBO, CB_RESETCONTENT, 0, 0 ); |
|
const jvTypeArray &branches = (*fAssetManIface)->GetBranches(); |
|
int i, curr = 0; |
|
for( i = 0; i < branches.Size(); i++ ) |
|
{ |
|
int idx = SendDlgItemMessage( fhDlg, IDC_BRANCHCOMBO, CB_ADDSTRING, 0, (LPARAM)(const char *)( branches[ i ].Name ) ); |
|
SendDlgItemMessage( fhDlg, IDC_BRANCHCOMBO, CB_SETITEMDATA, idx, (LPARAM)branches[ i ].Id ); |
|
|
|
if( branches[ i ].Id == fAssetManIface->GetCurrBranch() ) |
|
curr = i; |
|
} |
|
SendDlgItemMessage( fhDlg, IDC_BRANCHCOMBO, CB_SETCURSEL, curr, 0 ); |
|
|
|
|
|
fSpin = SetupFloatSpinner(fhDlg, IDC_DAYLEN_SPINNER, IDC_DAYLEN_EDIT, 1.f, 100.f, 24.f); |
|
fCapSpin = SetupIntSpinner(fhDlg, IDC_CAP_SPINNER, IDC_CAP_EDIT, 1, 250, kDefaultCapacity); |
|
fSeqPrefixSpin = SetupIntSpinner(fhDlg, IDC_SEQPREFIX_SPIN, IDC_SEQPREFIX_EDIT, 1, 102400, 1); |
|
|
|
SendDlgItemMessage( fhDlg, IDC_AGELIST_STATIC, WM_SETFONT, (WPARAM)fBoldFont, MAKELPARAM( TRUE, 0 ) ); |
|
SendDlgItemMessage( fhDlg, IDC_AGEDESC, WM_SETFONT, (WPARAM)fBoldFont, MAKELPARAM( TRUE, 0 ) ); |
|
#endif |
|
|
|
ISetControlDefaults(); |
|
IEnableControls(false); |
|
} |
|
|
|
void plAgeDescInterface::ISetControlDefaults() |
|
{ |
|
HWND hDate = GetDlgItem(fhDlg, IDC_DATE); |
|
HWND hTime = GetDlgItem(fhDlg, IDC_TIME); |
|
|
|
SYSTEMTIME st = {0}; |
|
st.wDay = 1; |
|
st.wMonth = 1; |
|
st.wYear = 2000; |
|
DateTime_SetSystemtime(hDate, GDT_VALID, &st); |
|
DateTime_SetSystemtime(hTime, GDT_VALID, &st); |
|
|
|
fSpin->SetValue(24.f, FALSE); |
|
fCapSpin->SetValue(kDefaultCapacity, FALSE); |
|
|
|
CheckDlgButton( fhDlg, IDC_ADM_DONTLOAD, FALSE ); |
|
|
|
int i; |
|
HWND ctrl = GetDlgItem( fhDlg, IDC_PAGE_LIST ); |
|
for( i = SendMessage( ctrl, LB_GETCOUNT, 0, 0 ) - 1; i >= 0; i-- ) |
|
RemovePageItem( ctrl, i ); |
|
|
|
SetDlgItemText( fhDlg, IDC_AGEDESC, "Age Description" ); |
|
} |
|
|
|
void plAgeDescInterface::IEnableControls(bool enable) |
|
{ |
|
bool checkedOut = true; |
|
|
|
plAgeFile *currAge = IGetCurrentAge(); |
|
if( currAge != nil && currAge->fType == plAgeFile::kAssetFile ) |
|
checkedOut = fCurrAgeCheckedOut && enable; |
|
else if( currAge != nil && currAge->fType == plAgeFile::kLocalFile ) |
|
checkedOut = enable; |
|
else |
|
checkedOut = false; |
|
|
|
EnableWindow(GetDlgItem(fhDlg, IDC_DATE), checkedOut ); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_TIME), checkedOut ); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_PAGE_LIST), checkedOut ); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_PAGE_NEW), checkedOut ); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_PAGE_DEL), checkedOut ); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_EDITREG), checkedOut ); |
|
|
|
if (!enable || !checkedOut) |
|
IEnablePageControls(false); |
|
|
|
fSpin->Enable(checkedOut ); |
|
fCapSpin->Enable(checkedOut ); |
|
|
|
if( currAge != nil && currAge->fType == plAgeFile::kAssetFile ) |
|
{ |
|
EnableWindow( GetDlgItem( fhDlg, IDC_AGE_CHECKIN ), checkedOut ); |
|
EnableWindow( GetDlgItem( fhDlg, IDC_AGE_UNDOCHECKOUT ), checkedOut ); |
|
EnableWindow( GetDlgItem( fhDlg, IDC_AGE_CHECKOUT ), !checkedOut ); |
|
} |
|
else |
|
{ |
|
EnableWindow( GetDlgItem( fhDlg, IDC_AGE_CHECKIN ), false ); |
|
EnableWindow( GetDlgItem( fhDlg, IDC_AGE_UNDOCHECKOUT ), false ); |
|
EnableWindow( GetDlgItem( fhDlg, IDC_AGE_CHECKOUT ), false ); |
|
} |
|
} |
|
|
|
void plAgeDescInterface::IEnablePageControls(bool enable) |
|
{ |
|
EnableWindow(GetDlgItem(fhDlg, IDC_ADM_DONTLOAD), enable); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_ADM_LOADSDL), enable); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_ADM_LOCAL_ONLY), enable); |
|
EnableWindow(GetDlgItem(fhDlg, IDC_ADM_VOLATILE), enable); |
|
} |
|
|
|
plFileName plAgeDescInterface::IGetLocalAgePath() |
|
{ |
|
// Get the path to the description folder |
|
plFileName plasmaPath = plMaxConfig::GetClientPath(); |
|
if (!plasmaPath.IsValid()) |
|
return ""; |
|
|
|
plFileName path = plFileName::Join(plasmaPath, plAgeDescription::kAgeDescPath); |
|
|
|
// Make sure the desc folder exists |
|
plFileSystem::CreateDir(path); |
|
|
|
return path; |
|
} |
|
|
|
int plAgeDescInterface::IFindAge(const char* ageName, std::vector<plAgeFile*>& ageFiles) |
|
{ |
|
for (int i = 0; i < ageFiles.size(); i++) |
|
if (ageFiles[i]->fAgeName == ageName) |
|
return i; |
|
|
|
return -1; |
|
} |
|
|
|
void plAgeDescInterface::IGetAgeFiles(std::vector<plAgeFile*>& ageFiles) |
|
{ |
|
IClearAgeFiles(ageFiles); |
|
|
|
// Make list of "local" ages. This might contain copies of those in AssetMan, so we make the |
|
// list first and take out the ones that are in AssetMan |
|
plFileName localPath = IGetLocalAgePath(); |
|
if (localPath.IsValid()) |
|
{ |
|
std::vector<plFileName> files = plFileSystem::ListDir(localPath, "*.age"); |
|
for (auto iter = files.begin(); iter != files.end(); ++iter) |
|
{ |
|
plAgeFile* age = new plAgeFile(plAgeFile::kLocalFile, *iter); |
|
ageFiles.push_back(age); |
|
} |
|
} |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
// Add AssetMan ages, if available (since we're static, go thru the main MaxAss interface) |
|
// Hoikas (many years later) does not believe the above comment... |
|
MaxAssInterface *assetMan = GetMaxAssInterface(); |
|
if( assetMan!= nil ) |
|
{ |
|
hsTArray<jvUniqueId> doneAssets; |
|
|
|
jvArray<jvUniqueId>* assets = assetMan->GetAssetsByType(MaxAssInterface::kTypeAge); |
|
for (int i = 0; i < assets->Size(); i++) |
|
{ |
|
if( doneAssets.Find( (*assets)[ i ] ) == doneAssets.kMissingIndex ) |
|
{ |
|
char agePath[MAX_PATH]; |
|
if (assetMan->GetLatestVersionFile((*assets)[i], agePath, sizeof(agePath))) |
|
{ |
|
plAgeFile* age = new plAgeFile(plAgeFile::kAssetFile, agePath, (*assets)[i]); |
|
|
|
int existing = IFindAge(age->fAgeName.c_str(), ageFiles); |
|
// Remove it from our "local" list if there, since it's a duplicate |
|
if (existing != -1) |
|
{ |
|
delete ageFiles[existing]; |
|
ageFiles[existing] = age; |
|
} |
|
else |
|
ageFiles.push_back(age); |
|
|
|
doneAssets.Append( (*assets)[ i ] ); |
|
} |
|
} |
|
} |
|
assets->DeleteSelf(); |
|
} |
|
#endif |
|
} |
|
|
|
void plAgeDescInterface::IClearAgeFiles(std::vector<plAgeFile*>& ageFiles) |
|
{ |
|
for (int i = 0; i < ageFiles.size(); i++) |
|
delete ageFiles[i]; |
|
ageFiles.clear(); |
|
} |
|
|
|
hsTArray<plFileName> plAgeDescInterface::BuildAgeFileList() |
|
{ |
|
std::vector<plAgeFile*> tempAgeFiles; |
|
IGetAgeFiles(tempAgeFiles); |
|
|
|
hsTArray<plFileName> ageList; |
|
for (int i = 0; i < tempAgeFiles.size(); i++) |
|
{ |
|
ageList.Push(tempAgeFiles[i]->fPath); |
|
delete tempAgeFiles[ i ]; |
|
} |
|
|
|
return ageList; |
|
} |
|
|
|
//// IFillAgeTree ///////////////////////////////////////////////////////////// |
|
// Refreshes/inits the tree view of all ages we have to work with. If |
|
// specified, will also get the latest version of the .age files from assetMan. |
|
void plAgeDescInterface::IFillAgeTree( void ) |
|
{ |
|
HWND ageTree = GetDlgItem( fhDlg, IDC_AGE_LIST ); |
|
|
|
// Clear the tree first and add our two root headers |
|
TreeView_DeleteAllItems(ageTree); |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
if( fAssetManIface != nil ) |
|
fAssetManBranch = SAddTreeItem(ageTree, nil, "AssetMan Ages", -1); |
|
else |
|
fAssetManBranch = nil; |
|
#endif |
|
|
|
fLocalBranch = SAddTreeItem(ageTree, nil, "Local Ages", -1); |
|
|
|
IGetAgeFiles(fAgeFiles); |
|
|
|
// Add the ages to the tree |
|
for (int i = 0; i < fAgeFiles.size(); i++) |
|
{ |
|
SAddTreeItem(ageTree, |
|
(fAgeFiles[i]->fType == plAgeFile::kAssetFile) ? fAssetManBranch : fLocalBranch, |
|
fAgeFiles[i]->fAgeName.c_str(), |
|
i); |
|
} |
|
|
|
// Select the first age to view |
|
IUpdateCurAge(); |
|
} |
|
|
|
BOOL CALLBACK NewAgeDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
static plString *name = nil; |
|
|
|
switch (msg) |
|
{ |
|
case WM_INITDIALOG: |
|
name = reinterpret_cast<plString *>(lParam); |
|
SetWindowText(hDlg, name->c_str()); |
|
return TRUE; |
|
|
|
case WM_COMMAND: |
|
if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK) |
|
{ |
|
char buffer[_MAX_FNAME]; |
|
if (GetDlgItemText(hDlg, IDC_AGE_NAME, buffer, _MAX_FNAME) > 0) { |
|
EndDialog(hDlg, 1); |
|
*name = buffer; |
|
} else { |
|
EndDialog(hDlg, 0); |
|
} |
|
return TRUE; |
|
} |
|
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) |
|
{ |
|
EndDialog(hDlg, 0); |
|
return TRUE; |
|
} |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
BOOL CALLBACK NewSeqNumberProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
static char msg1[] = "This age currently does not have a sequence number assigned to it. All ages " |
|
"must have a unique sequence number for multiplayer to work. Unassigned ages " |
|
"will get a temporary random number at export time, but will result in undefined " |
|
"(but probably bad) behavior during multiplayer games. In general, you should " |
|
"always assign a sequence number to an age unless you have a very specific and " |
|
"good reason not to."; |
|
static char msg2[] = "The ADManager can find and assign a new, unique sequence number to this age for " |
|
"you. You can choose to assign a normal or a global/reserved number. Normal ages " |
|
"are ones for gameplay (that you can link to, walk around in, etc.), while " |
|
"global/reserved ages are typically for storing data (such as avatars, GUI dialogs, etc.)"; |
|
char msg3[ 512 ]; |
|
|
|
|
|
switch (msg) |
|
{ |
|
case WM_INITDIALOG: |
|
SetDlgItemText( hDlg, IDC_INFOMSG, msg1 ); |
|
SetDlgItemText( hDlg, IDC_ADMMSG, msg2 ); |
|
sprintf( msg3, "Age: %s", (const char *)lParam ); |
|
SetDlgItemText( hDlg, IDC_AGEMSG, msg3 ); |
|
return TRUE; |
|
|
|
case WM_COMMAND: |
|
if (HIWORD(wParam) == BN_CLICKED ) |
|
{ |
|
EndDialog( hDlg, LOWORD( wParam ) ); |
|
return TRUE; |
|
} |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
void plAgeDescInterface::INewAge() |
|
{ |
|
VARIANT assetId; |
|
VariantInit(&assetId); |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
bool makeAsset = true; |
|
if( hsMessageBox( "Do you wish to store your new age in AssetMan?", "Make source-controlled?", hsMessageBoxYesNo ) == hsMBoxNo ) |
|
makeAsset = false; |
|
#endif |
|
|
|
plFileName newAssetFilename; |
|
#ifdef MAXASS_AVAILABLE |
|
if (!fAssetManIface) |
|
makeAsset = false; |
|
#endif |
|
|
|
newAssetFilename = IGetLocalAgePath(); |
|
if (!newAssetFilename.IsValid()) |
|
return; |
|
|
|
plString name = "New Age Name"; |
|
|
|
// Get the name of the new age from the user |
|
int ret = DialogBoxParam(hInstance, |
|
MAKEINTRESOURCE(IDD_AGE_NAME), |
|
GetCOREInterface()->GetMAXHWnd(), |
|
NewAgeDlgProc, |
|
(LPARAM)&name); |
|
if (ret != 1) |
|
return; |
|
|
|
newAssetFilename = plFileName::Join(newAssetFilename, name + ".age"); |
|
|
|
#ifdef MAXASS_AVAILABLE |
|
if( !makeAsset ) |
|
fForceSeqNumLocal = true; |
|
ISetControlDefaults(); |
|
ISaveCurAge(newAssetFilename, true); // Check sequence # while we're at it |
|
fForceSeqNumLocal = false; |
|
|
|
if( makeAsset ) |
|
(*fAssetManIface)->AddNewAsset(newAssetFilename.AsString().c_str()); |
|
#endif |
|
|
|
// Refresh the tree now |
|
IFillAgeTree(); |
|
} |
|
|
|
void plAgeDescInterface::INewPage() |
|
{ |
|
plString name = "New Page Name"; |
|
|
|
// Get the name of the new age from the user |
|
int ret = DialogBoxParam(hInstance, |
|
MAKEINTRESOURCE(IDD_AGE_NAME), |
|
GetCOREInterface()->GetMAXHWnd(), |
|
NewAgeDlgProc, |
|
(LPARAM)&name); |
|
if (ret != 1) |
|
return; |
|
|
|
HWND hPages = GetDlgItem(fhDlg, IDC_PAGE_LIST); |
|
|
|
// Make sure this page doesn't already exist |
|
int count = ListBox_GetCount(hPages); |
|
for (int i = 0; i < count; i++) |
|
{ |
|
char pageName[256]; |
|
ListBox_GetText(hPages, i, pageName); |
|
if (!name.CompareI(pageName)) |
|
return; |
|
} |
|
|
|
// Add the new page and select it |
|
int idx = ListBox_AddString(hPages, name.c_str()); |
|
|
|
// Choose a new sequence suffix for it |
|
plAgePage *newPage = new plAgePage( name, IGetFreePageSeqSuffix( hPages ), 0 ); |
|
ListBox_SetItemData( hPages, idx, (LPARAM)newPage ); |
|
|
|
fDirty = true; |
|
} |
|
|
|
uint32_t plAgeDescInterface::IGetFreePageSeqSuffix( HWND pageCombo ) |
|
{ |
|
int i, count = ListBox_GetCount( pageCombo ); |
|
uint32_t searchSeq = 1; |
|
|
|
do |
|
{ |
|
for( i = 0; i < count; i++ ) |
|
{ |
|
plAgePage *page = (plAgePage *)ListBox_GetItemData( pageCombo, i ); |
|
if( page != nil && page->GetSeqSuffix() == searchSeq ) |
|
{ |
|
searchSeq++; |
|
break; |
|
} |
|
} |
|
|
|
} while( i < count ); |
|
|
|
return searchSeq; |
|
} |
|
|
|
void plAgeDescInterface::ISaveCurAge( const plFileName &path, bool checkSeqNum ) |
|
{ |
|
hsUNIXStream s; |
|
if( !s.Open( path, "wt" ) ) |
|
{ |
|
hsMessageBox("Unable to open the Age Description file for writing. Updates not saved.", "Error", hsMessageBoxNormal); |
|
return; |
|
} |
|
|
|
plAgeDescription aged; |
|
aged.SetAgeNameFromPath( path ); |
|
|
|
// set the date and time |
|
HWND hDate = GetDlgItem(fhDlg, IDC_DATE); |
|
SYSTEMTIME dst = {0}; |
|
DateTime_GetSystemtime(hDate, &dst); |
|
HWND hTime = GetDlgItem(fhDlg, IDC_TIME); |
|
SYSTEMTIME tst = {0}; |
|
DateTime_GetSystemtime(hTime, &tst); |
|
aged.SetStart(dst.wYear,dst.wMonth,dst.wDay,tst.wHour,tst.wMinute,tst.wSecond); |
|
aged.SetDayLength(fSpin->GetFVal()); |
|
aged.SetMaxCapacity(fCapSpin->GetIVal()); |
|
if( checkSeqNum ) |
|
{ |
|
ICheckSequenceNumber( aged ); |
|
} |
|
else if( IsDlgButtonChecked( fhDlg, IDC_RSVDCHECK ) ) |
|
{ |
|
// Store reserved sequence prefix |
|
aged.SetSequencePrefix( -fSeqPrefixSpin->GetIVal() ); |
|
} |
|
else |
|
{ |
|
aged.SetSequencePrefix( fSeqPrefixSpin->GetIVal() ); |
|
} |
|
|
|
// gather pages |
|
HWND hPages = GetDlgItem(fhDlg, IDC_PAGE_LIST); |
|
int count = ListBox_GetCount(hPages); |
|
if (count != LB_ERR) |
|
{ |
|
for (int i = 0; i < count; i++) |
|
{ |
|
char pageName[256]; |
|
ListBox_GetText(hPages, i, pageName); |
|
plAgePage *page = (plAgePage *)ListBox_GetItemData( hPages, i ); |
|
aged.AppendPage( pageName, page->GetSeqSuffix(), page->GetFlags() ); |
|
} |
|
} |
|
|
|
// write it all out |
|
aged.Write(&s); |
|
s.Close(); |
|
} |
|
|
|
//// ICheckSequenceNumber ///////////////////////////////////////////////////// |
|
// Checks to make sure the sequence prefix is valid. If not, asks to assign |
|
// a good one. |
|
|
|
void plAgeDescInterface::ICheckSequenceNumber( plAgeDescription &aged ) |
|
{ |
|
if( aged.GetSequencePrefix() == 0 ) // Default of uninitialized |
|
{ |
|
// Ask about the sequence # |
|
int ret = DialogBoxParam( hInstance, MAKEINTRESOURCE( IDD_AGE_SEQNUM ), |
|
GetCOREInterface()->GetMAXHWnd(), |
|
NewSeqNumberProc, (LPARAM)aged.GetAgeName().c_str() ); |
|
if( ret == IDYES ) |
|
{ |
|
aged.SetSequencePrefix( IGetNextFreeSequencePrefix( false ) ); |
|
fDirty = true; |
|
} |
|
else if( ret == IDNO ) |
|
{ |
|
aged.SetSequencePrefix( IGetNextFreeSequencePrefix( true ) ); |
|
fDirty = true; |
|
} |
|
} |
|
} |
|
|
|
void plAgeDescInterface::ILoadAge( const plFileName &path, bool checkSeqNum ) |
|
{ |
|
ISetControlDefaults(); |
|
|
|
fDirty = false; |
|
|
|
// create and read the age desc |
|
plAgeDescription aged( path ); |
|
|
|
// Get the name of the age |
|
plString ageName = path.GetFileNameNoExt(); |
|
|
|
// Check the sequence prefix # |
|
if( checkSeqNum ) |
|
ICheckSequenceNumber( aged ); |
|
|
|
char str[ _MAX_FNAME + 30 ]; |
|
sprintf( str, "Description for %s", ageName.c_str() ); |
|
SetDlgItemText( fhDlg, IDC_AGEDESC, str ); |
|
|
|
// Set up the Dlgs |
|
SYSTEMTIME st; |
|
|
|
HWND hTime = GetDlgItem(fhDlg, IDC_TIME); |
|
memset(&st,0, sizeof(st)); |
|
st.wYear = 2000; |
|
st.wMonth = 1; |
|
st.wDay = 1; |
|
st.wHour = aged.GetStartHour(); |
|
st.wMinute = aged.GetStartMinute(); |
|
st.wSecond = aged.GetStartSecond(); |
|
DateTime_SetSystemtime(hTime, GDT_VALID, &st); |
|
|
|
|
|
HWND hDate = GetDlgItem(fhDlg, IDC_DATE); |
|
memset(&st,0, sizeof(st)); |
|
st.wMonth = aged.GetStartMonth(); |
|
st.wDay = aged.GetStartDay(); |
|
st.wYear = aged.GetStartYear(); |
|
DateTime_SetSystemtime(hDate, GDT_VALID, &st); |
|
|
|
|
|
fSpin->SetValue(aged.GetDayLength(), FALSE); |
|
|
|
int maxCap = aged.GetMaxCapacity(); |
|
if (maxCap == -1) |
|
{ |
|
maxCap = kDefaultCapacity; |
|
fDirty = true; |
|
} |
|
fCapSpin->SetValue(maxCap, FALSE); |
|
|
|
int32_t seqPrefix = aged.GetSequencePrefix(); |
|
if( seqPrefix < 0 ) |
|
{ |
|
// Reserved prefix |
|
fSeqPrefixSpin->SetValue( (int)( -seqPrefix ), FALSE ); |
|
CheckDlgButton( fhDlg, IDC_RSVDCHECK, BST_CHECKED ); |
|
} |
|
else |
|
{ |
|
fSeqPrefixSpin->SetValue( (int)seqPrefix, FALSE ); |
|
CheckDlgButton( fhDlg, IDC_RSVDCHECK, BST_UNCHECKED ); |
|
} |
|
|
|
// Disable the registry controls for now |
|
EnableWindow( GetDlgItem( fhDlg, IDC_RSVDCHECK ), false ); |
|
EnableWindow( GetDlgItem( fhDlg, IDC_SEQPREFIX_EDIT ), false ); |
|
EnableWindow( GetDlgItem( fhDlg, IDC_SEQPREFIX_SPIN ), false ); |
|
|
|
aged.SeekFirstPage(); |
|
plAgePage *page; |
|
|
|
HWND hPage = GetDlgItem(fhDlg, IDC_PAGE_LIST); |
|
while( ( page = aged.GetNextPage() ) != nil ) |
|
{ |
|
int idx = ListBox_AddString( hPage, page->GetName().c_str() ); |
|
ListBox_SetItemData( hPage, idx, (LPARAM)new plAgePage( *page ) ); |
|
} |
|
} |
|
|
|
uint32_t plAgeDescInterface::IGetNextFreeSequencePrefix( bool getReservedPrefix ) |
|
{ |
|
int32_t searchSeq = getReservedPrefix ? -1 : 1; |
|
hsTArray<char *> ageList; |
|
int i; |
|
|
|
hsTArray<plAgeDescription> ages; |
|
|
|
|
|
if( fForceSeqNumLocal ) |
|
searchSeq = getReservedPrefix ? -1024 : 1024; |
|
|
|
IGetAgeFiles(fAgeFiles); |
|
|
|
ages.SetCount( fAgeFiles.size() ); |
|
for( i = 0; i < fAgeFiles.size(); i++ ) |
|
{ |
|
hsUNIXStream stream; |
|
if( stream.Open( fAgeFiles[ i ]->fPath, "rt" ) ) |
|
{ |
|
ages[ i ].Read( &stream ); |
|
stream.Close(); |
|
} |
|
} |
|
|
|
do |
|
{ |
|
if( getReservedPrefix ) |
|
{ |
|
for( i = 0; i < ages.GetCount(); i++ ) |
|
{ |
|
if( ages[ i ].GetSequencePrefix() == searchSeq ) |
|
{ |
|
searchSeq--; |
|
break; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
for( i = 0; i < ages.GetCount(); i++ ) |
|
{ |
|
if( ages[ i ].GetSequencePrefix() == searchSeq ) |
|
{ |
|
searchSeq++; |
|
break; |
|
} |
|
} |
|
} |
|
} while( i < ages.GetCount() ); |
|
|
|
return searchSeq; |
|
} |
|
|
|
plAgeFile* plAgeDescInterface::IGetCurrentAge( void ) |
|
{ |
|
HWND ageTree = GetDlgItem( fhDlg, IDC_AGE_LIST ); |
|
fCurrAgeItem = TreeView_GetSelection( ageTree ); |
|
if( fCurrAgeItem == nil ) |
|
return nil; |
|
|
|
int idx = SGetTreeData( ageTree, fCurrAgeItem ); |
|
if (idx == -1) |
|
return nil; |
|
|
|
return fAgeFiles[idx]; |
|
} |
|
|
|
//// SAddTreeItem ///////////////////////////////////////////////////////////// |
|
// Static helper function for adding an item to a treeView |
|
|
|
static HTREEITEM SAddTreeItem( HWND hTree, HTREEITEM hParent, const char *label, int userData ) |
|
{ |
|
TVITEM tvi = {0}; |
|
tvi.mask = TVIF_TEXT | TVIF_PARAM; |
|
tvi.pszText = (char *)label; |
|
tvi.cchTextMax = strlen( label ); |
|
tvi.lParam = (LPARAM)userData; |
|
if( userData == -1 ) |
|
{ |
|
tvi.mask |= TVIF_STATE; |
|
tvi.state = tvi.stateMask = TVIS_BOLD | TVIS_EXPANDED; |
|
} |
|
|
|
TVINSERTSTRUCT tvins = {0}; |
|
tvins.item = tvi; |
|
tvins.hParent = hParent; |
|
tvins.hInsertAfter = TVI_LAST; |
|
|
|
return TreeView_InsertItem( hTree, &tvins ); |
|
} |
|
|
|
//// SGetTreeData ///////////////////////////////////////////////////////////// |
|
// Gets the tree data for the given item |
|
|
|
int SGetTreeData( HWND tree, HTREEITEM item ) |
|
{ |
|
TVITEM itemInfo; |
|
itemInfo.mask = TVIF_PARAM | TVIF_HANDLE; |
|
itemInfo.hItem = item; |
|
TreeView_GetItem( tree, &itemInfo ); |
|
return itemInfo.lParam; |
|
}
|
|
|