diff --git a/Tools/LevelEditor/LevelEditor.exe b/Tools/LevelEditor/LevelEditor.exe new file mode 100644 index 0000000..634767c Binary files /dev/null and b/Tools/LevelEditor/LevelEditor.exe differ diff --git a/Tools/LevelEditor/Source/BGColorDialog.cpp b/Tools/LevelEditor/Source/BGColorDialog.cpp new file mode 100644 index 0000000..ce40811 --- /dev/null +++ b/Tools/LevelEditor/Source/BGColorDialog.cpp @@ -0,0 +1,153 @@ +// BGColorDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "BGColorDialog.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +int CBGColorDialog::initRed = 0; +int CBGColorDialog::initGreen = 0; +int CBGColorDialog::initBlue = 0; + +///////////////////////////////////////////////////////////////////////////// +// CBGColorDialog dialog + + +CBGColorDialog::CBGColorDialog(CWnd* pParent /*=NULL*/) + : CDialog(CBGColorDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CBGColorDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CBGColorDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CBGColorDialog) + DDX_Control(pDX, IDC_COLOR, m_colorFrame); + DDX_Control(pDX, IDC_RED, m_red); + DDX_Control(pDX, IDC_GREEN, m_green); + DDX_Control(pDX, IDC_BLUE, m_blue); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CBGColorDialog, CDialog) + //{{AFX_MSG_MAP(CBGColorDialog) + ON_EN_KILLFOCUS(IDC_RED, OnKillfocusRed) + ON_EN_KILLFOCUS(IDC_GREEN, OnKillfocusGreen) + ON_EN_KILLFOCUS(IDC_BLUE, OnKillfocusBlue) + ON_WM_PAINT() + ON_EN_CHANGE(IDC_RED, OnChangeRed) + ON_EN_CHANGE(IDC_GREEN, OnChangeGreen) + ON_EN_CHANGE(IDC_BLUE, OnChangeBlue) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CBGColorDialog message handlers + +BOOL CBGColorDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + + SetValue(m_red, initRed); + SetValue(m_green, initGreen); + SetValue(m_blue, initBlue); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CBGColorDialog::SetValue(CEdit &edit, int val) +{ + char st[80]; + ostrstream stout(st,80); + stout << val << ends; + edit.SetWindowText(st); +} + +int CBGColorDialog::GetValue(CEdit &edit) +{ + char st[80]; + edit.GetWindowText(st,80); + istrstream stin(st,80); + + int n; + stin >> n; + return n; +} + +void CBGColorDialog::LimitValue(CEdit &edit, int min, int max) +{ + int n = GetValue(edit); + if(n < min || n > max){ + if(nInvalidateRect(0); +} + +void CBGColorDialog::OnKillfocusGreen() +{ + LimitValue(m_green, 0, 255); + initGreen = GetValue(m_green); + this->InvalidateRect(0); +} + +void CBGColorDialog::OnKillfocusBlue() +{ + LimitValue(m_blue, 0, 255); + initBlue = GetValue(m_blue); + this->InvalidateRect(0); +} + +void CBGColorDialog::OnOK() +{ + CDialog::OnOK(); +} + +void CBGColorDialog::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + CRect rect; + m_colorFrame.GetWindowRect(&rect); + this->ScreenToClient(&rect); + + int color = (initBlue<<16) | (initGreen<<8) | initRed; + dc.FillSolidRect(&rect,color); + + // Do not call CDialog::OnPaint() for painting messages +} + +void CBGColorDialog::OnChangeRed() +{ + this->OnKillfocusRed(); +} + +void CBGColorDialog::OnChangeGreen() +{ + this->OnKillfocusGreen(); +} + +void CBGColorDialog::OnChangeBlue() +{ + this->OnKillfocusBlue(); +} diff --git a/Tools/LevelEditor/Source/BGColorDialog.h b/Tools/LevelEditor/Source/BGColorDialog.h new file mode 100644 index 0000000..43e0e30 --- /dev/null +++ b/Tools/LevelEditor/Source/BGColorDialog.h @@ -0,0 +1,61 @@ +#if !defined(AFX_BGCOLORDIALOG_H__7540E1C1_F5D2_11D3_B6CE_525400E2D57B__INCLUDED_) +#define AFX_BGCOLORDIALOG_H__7540E1C1_F5D2_11D3_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// BGColorDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CBGColorDialog dialog + +class CBGColorDialog : public CDialog +{ +// Construction +public: + void LimitValue(CEdit &edit, int min, int max); + int GetValue(CEdit &edit); + void SetValue(CEdit &edit, int val); + static int initRed, initGreen, initBlue; + CBGColorDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CBGColorDialog) + enum { IDD = IDD_COLORPICKER }; + CStatic m_colorFrame; + CEdit m_red; + CEdit m_green; + CEdit m_blue; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBGColorDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CBGColorDialog) + virtual BOOL OnInitDialog(); + afx_msg void OnKillfocusRed(); + afx_msg void OnKillfocusGreen(); + afx_msg void OnKillfocusBlue(); + virtual void OnOK(); + afx_msg void OnPaint(); + afx_msg void OnChangeRed(); + afx_msg void OnChangeGreen(); + afx_msg void OnChangeBlue(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BGCOLORDIALOG_H__7540E1C1_F5D2_11D3_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/LevelEditor/Source/ChildView.cpp b/Tools/LevelEditor/Source/ChildView.cpp new file mode 100644 index 0000000..65c701f --- /dev/null +++ b/Tools/LevelEditor/Source/ChildView.cpp @@ -0,0 +1,159 @@ +// ChildView.cpp : implementation of the CChildView class +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "ChildView.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CChildView + +CChildView::CChildView() +{ + + //load in bitmap + tyPic.LoadBMP("ty.bmp"); + +} + +CChildView::~CChildView() +{ +} + + +BEGIN_MESSAGE_MAP(CChildView,CWnd ) + //{{AFX_MSG_MAP(CChildView) + ON_WM_PAINT() + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_ERASEBKGND() + ON_WM_CREATE() + ON_WM_SIZE() + ON_WM_KEYDOWN() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CChildView message handlers + +BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) +{ + if (!CWnd::PreCreateWindow(cs)) + return FALSE; + + cs.dwExStyle |= WS_EX_CLIENTEDGE; + cs.style &= ~WS_BORDER; + cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, + ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); + + return TRUE; +} + +void CChildView::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + if(1) + return; +} + + +void CChildView::OnMouseMove(UINT nFlags, CPoint point) +{ + + // TODO: Add your message handler code here and/or call default + this->InvalidateRect(0, TRUE); + CWnd ::OnMouseMove(nFlags, point); + +} + +void CChildView::OnLButtonDown(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + + CWnd ::OnLButtonDown(nFlags, point); + + +} + +BOOL CChildView::OnEraseBkgnd(CDC* pDC) +{ + // TODO: Add your message handler code here and/or call default + + // we'll handle clearing + return true; + + //return CWnd ::OnEraseBkgnd(pDC); +} + + + +int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CWnd ::OnCreate(lpCreateStruct) == -1) + return -1; + + + // TODO: Add your specialized creation code here + controls.Create(IDD_CONTROLS, this); + mapWin.Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL, + CRect(0,0,0,0), this, 0, 0); + + controls.ShowWindow(SW_SHOW); + + return 0; +} + +void CChildView::ReSizeWindows() +{ + + CRect rect; + + this->GetClientRect(&rect); + + controls.SetWindowPos(&wndTop, 0, 0, 300, rect.Height(), SWP_SHOWWINDOW); + mapWin.SetWindowPos(&wndTop, 300, 0, rect.Width()-300, rect.Height(), SWP_SHOWWINDOW); + + +} + +void CChildView::OnSize(UINT nType, int cx, int cy) +{ + CWnd ::OnSize(nType, cx, cy); + + // TODO: Add your message handler code here + this->ReSizeWindows(); + +} + +// display grids on the mapview +void CChildView::SetGrids(bool on){ + mapWin.SetGrids(on); +} + +// naughty function to grab a reference to WinMap +CMapWin* CChildView::GrabWinMap(){ + return &mapWin; +} + +// naughty function to grab a reference to control +CControls* CChildView::GrabControls(){ + return &controls; +} + + + + +void CChildView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ +ASSERT(0); + CWnd ::OnKeyDown(nChar, nRepCnt, nFlags); +} diff --git a/Tools/LevelEditor/Source/ChildView.h b/Tools/LevelEditor/Source/ChildView.h new file mode 100644 index 0000000..fc6bd44 --- /dev/null +++ b/Tools/LevelEditor/Source/ChildView.h @@ -0,0 +1,78 @@ +// ChildView.h : interface of the CChildView class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CHILDVIEW_H__CA2832CA_B4C7_11D3_958B_00A0CC533895__INCLUDED_) +#define AFX_CHILDVIEW_H__CA2832CA_B4C7_11D3_958B_00A0CC533895__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "wingk.h" +#include "mapwin.h" +#include "Controls.h" + +///////////////////////////////////////////////////////////////////////////// +// CChildView window + +class CChildView : public CWnd +{ +// Construction +public: + CChildView(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChildView) + protected: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + void ReSizeWindows(); + void SetGrids(bool); + virtual ~CChildView(); + + // naughty function to grab references to Children + CMapWin* GrabWinMap(); + CControls* GrabControls(); + + + + // Generated message map functions +protected: + + gkWinShape tyPic; + //background + gkWinShape bckgrndBffr; + + CControls controls; + CMapWin mapWin; + + + //{{AFX_MSG(CChildView) + afx_msg void OnPaint(); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHILDVIEW_H__CA2832CA_B4C7_11D3_958B_00A0CC533895__INCLUDED_) diff --git a/Tools/LevelEditor/Source/ClassList.cpp b/Tools/LevelEditor/Source/ClassList.cpp new file mode 100644 index 0000000..2c2f0ce --- /dev/null +++ b/Tools/LevelEditor/Source/ClassList.cpp @@ -0,0 +1,120 @@ +// ClassList.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "ClassList.h" +#include "EditDefines.h" +#include "wingk.h" +#include "strstrea.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CClassList dialog + + +CClassList::CClassList(CWnd* pParent /*=NULL*/) + : CDialog(CClassList::IDD, pParent) +{ + //{{AFX_DATA_INIT(CClassList) + //}}AFX_DATA_INIT +} + + +void CClassList::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CClassList) + DDX_Control(pDX, IDC_CLASS_LIST, m_classList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CClassList, CDialog) + //{{AFX_MSG_MAP(CClassList) + ON_WM_CREATE() + ON_WM_CTLCOLOR() + ON_LBN_SELCHANGE(IDC_CLASS_LIST, OnSelchangeClassList) + ON_BN_CLICKED(IDC_CLASSLIST_CLEARALL, OnClasslistClearall) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CClassList message handlers + +int CClassList::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CDialog::OnCreate(lpCreateStruct) == -1) + return -1; + + + return 0; +} + +HBRUSH CClassList::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) +{ + HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); + + + // TODO: Return a different brush if the default is not desired + return hbr; +} + +BOOL CClassList::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_classList.tileList = tileList; + int i; + for(i=2; i<=E_LAST_TILE; i++){ + char st[80]; + ostrstream stout(st,80); + stout << "Tile " << i << ends; + int index = m_classList.AddString(st); + int data = 0; + if(listOfAllTiles[i]) data |= (1<<16); + data |= (i & 0xffff); + m_classList.SetItemData(index, data); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CClassList::OnSelchangeClassList() +{ + int index = m_classList.GetCurSel(); + + //toggle selected bit + int data = m_classList.GetItemData(index); + data ^= (1<<16); + m_classList.SetItemData(index, data); + + if(data & (1<<16)){ + //check was set + listOfAllTiles[index+2] = 1; + }else{ + //check was cleared + listOfAllTiles[index+2] = 0; + } + + m_classList.InvalidateRect(0); +} + +void CClassList::OnClasslistClearall() +{ + int last = m_classList.GetCount(); + int i; + for(i=0; i 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "wingk.h" +#include "ClassListList.h" + +// ClassList.h : header file +// + +#include "wingk.h" + +///////////////////////////////////////////////////////////////////////////// +// CClassList dialog + +class CClassList : public CDialog +{ +// Construction +public: + short int *listOfTilesUsed, *listOfAllTiles, totalTilesUsed; + gkWinShape *tileList; + CClassList(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CClassList) + enum { IDD = IDD_CLASS_LIST_DIALOG }; + CClassListList m_classList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CClassList) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CClassList) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeClassList(); + afx_msg void OnClasslistClearall(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CLASSLIST_H__D14BA4E8_C76B_11D3_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/LevelEditor/Source/ClassListList.cpp b/Tools/LevelEditor/Source/ClassListList.cpp new file mode 100644 index 0000000..3f1b6fe --- /dev/null +++ b/Tools/LevelEditor/Source/ClassListList.cpp @@ -0,0 +1,96 @@ +// ClassListList.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "ClassListList.h" +#include "ClassList.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CClassListList + +CClassListList::CClassListList() +{ +} + +CClassListList::~CClassListList() +{ +} + + +BEGIN_MESSAGE_MAP(CClassListList, CListBox) + //{{AFX_MSG_MAP(CClassListList) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CClassListList message handlers + +void CClassListList::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) +{ + CRect rect; + this->GetClientRect(&rect); + + //tell windows the dimensions of each member of our selection box + //lpMeasureItemStruct->itemWidth = rect.Width(); + //lpMeasureItemStruct->itemHeight = 16; + +} + +void CClassListList::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + HDC hdc = lpDrawItemStruct->hDC; + CDC dc; + dc.Attach(hdc); + + CBrush brush; + brush.Attach(::GetStockObject(BLACK_BRUSH)); + + CRect rect = lpDrawItemStruct->rcItem; + int x = rect.left; + int y = rect.top; + + + int data = lpDrawItemStruct->itemData; + int tile = data & 0xffff; + int isUsed = (data>>16) & 1; + + //checkbox + CRect checkBox(x+4,y+2,x+14,y+12); + dc.FillSolidRect(&checkBox,0xffffff); + dc.FrameRect(&checkBox,&brush); + + if(isUsed){ + checkBox.DeflateRect(2,2); + dc.FillSolidRect(&checkBox,0); + //dc.MoveTo(checkBox.left, checkBox.top); + //dc.LineTo(checkBox.right-1, checkBox.bottom-1); + //dc.MoveTo(checkBox.left, checkBox.bottom-1); + //dc.LineTo(checkBox.right-1, checkBox.top); + } + + //picture + if(tile){ + tileList[tile].BlitToDC(&dc, x+20, y); + } + + //text + dc.SetBkColor(::GetSysColor(COLOR_WINDOW)); + char st[80]; + GetText(lpDrawItemStruct->itemID,st); + dc.TextOut(x+38,y,st); + + if(lpDrawItemStruct->itemState & ODS_SELECTED){ + dc.FrameRect(rect,&brush); + } + + brush.Detach(); + dc.Detach(); +} diff --git a/Tools/LevelEditor/Source/ClassListList.h b/Tools/LevelEditor/Source/ClassListList.h new file mode 100644 index 0000000..31ebc45 --- /dev/null +++ b/Tools/LevelEditor/Source/ClassListList.h @@ -0,0 +1,55 @@ +#if !defined(AFX_CLASSLISTLIST_H__D14BA4E9_C76B_11D3_B6CE_525400E2D57B__INCLUDED_) +#define AFX_CLASSLISTLIST_H__D14BA4E9_C76B_11D3_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "wingk.h" + +// ClassListList.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CClassListList window + +class CClassListList : public CListBox +{ +// Construction +public: + CClassListList(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CClassListList) + public: + virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + //}}AFX_VIRTUAL + +// Implementation +public: + gkWinShape* tileList; + virtual ~CClassListList(); + + // Generated message map functions +protected: + //{{AFX_MSG(CClassListList) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CLASSLISTLIST_H__D14BA4E9_C76B_11D3_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/LevelEditor/Source/Controls.cpp b/Tools/LevelEditor/Source/Controls.cpp new file mode 100644 index 0000000..7937596 --- /dev/null +++ b/Tools/LevelEditor/Source/Controls.cpp @@ -0,0 +1,985 @@ +// Controls.cpp : implementation file +// + +#include +#include +#include "stdafx.h" +#include "EditDefines.h" +#include "LevelEditor.h" +#include "Controls.h" +#include "ChildView.h" +#include "MapWin.h" +#include "ZoneList.h" +#include "WayPointList.h" +#include "ClassList.h" +#include "BGColorDialog.h" +#include "LinkExitsDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define E_TILETITLE "background0001-1535.bmp" +#define E_PEOPLETITLE "objects2048-2303.bmp" + +///////////////////////////////////////////////////////////////////////////// +// CControls dialog + + +CControls::CControls(CWnd* pParent /*=NULL*/) + : CDialog(CControls::IDD, pParent) +{ + + gkWinShape temp1, temp2; + + //Load tiles into buffer + temp1.LoadBMP(E_TILETITLE); + + //CHANGE + //go ahead an set the cur tile as first tile in tileBuff + curTile = 1; + int i; + + //load all the tiles of a 512 wide file into tileList + //assuming all tiles are 16 pixel squares + int tmpIndex = 1; + for(int j=0;j<(E_TILEBMPSIZEY >> 4);j++) + for(i=0;i<(E_TILEBMPSIZEX >> 4);i++) + tileList[tmpIndex++].GetShape(&temp1,i<<4,j<<4,16,16); + + //Load people tiles into buffer + tmpIndex--; //start people at 1024, not 1025 + temp2.LoadBMP(E_PEOPLETITLE); + for(j=0;j<(E_PEOPLEBMPSIZEY >> 4);j++) + for(i=0;i<(E_PEOPLEBMPSIZEX >> 4);i++) + tileList[tmpIndex++].GetShape(&temp2,i<<4,j<<4,16,16); + + tileBuff.Create(E_TOTALBUFFERSIZEW,E_TOTALBUFFERSIZEH); + tileBuff.Cls(gkRGB(0,0,0)); + temp1.Blit(&tileBuff,0,0); + temp2.Blit(&tileBuff,0,E_TILEBMPSIZEY); + + mapWidth = E_LEVELSIZEX; + mapHeight = E_LEVELSIZEY; + + //discover map pitch + mapPitch = 0; + int temp = mapWidth-1; + while(temp){ + temp = (temp>>1) & 0x7f; + mapPitch = (mapPitch<<1) | 1; + } + mapPitch++; + + g_wayPointList.SetPitch(mapPitch); + + drawingZones = -1; + drawingExits = -1; + + metaWidth = metaHeight = 1; + areaSpecial = 0; + + links[0] = 0x4040; //+0, +0 + links[1] = 0x4081; //+0,-1 + links[2] = 0x4140; //+1,+0 + links[3] = 0x4041; //+0,+1 + links[4] = 0x8140; //-1,+0 + links[5] = links[6] = links[7] = 0x4040; //+0, +0 + + isWall = 0; + + //{{AFX_DATA_INIT(CControls) + //}}AFX_DATA_INIT +} + + +void CControls::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CControls) + DDX_Control(pDX, IDC_SORTCLASSESBY, m_sortClassesBy); + DDX_Control(pDX, IDC_WALLCHECK, m_wallCheck); + DDX_Control(pDX, IDC_COPYDOWN, m_copyDown); + DDX_Control(pDX, IDC_COPYLEFT, m_copyLeft); + DDX_Control(pDX, IDC_COPYRIGHT, m_copyRight); + DDX_Control(pDX, IDC_COPYUP, m_copyUp); + DDX_Control(pDX, IDC_SHIFTUP, m_shiftUp); + DDX_Control(pDX, IDC_SHIFTRIGHT, m_shiftRight); + DDX_Control(pDX, IDC_SHIFTLEFT, m_shiftLeft); + DDX_Control(pDX, IDC_SHIFTDOWN, m_shiftDown); + DDX_Control(pDX, IDC_META_HEIGHT, m_metaHeight); + DDX_Control(pDX, IDC_META_WIDTH, m_metaWidth); + DDX_Control(pDX, IDC_RADIO_TILES, m_radioTiles); + DDX_Control(pDX, IDC_LOAD_FILENAME, m_loadLevel); + DDX_Control(pDX, IDC_ZONELIST, m_zoneList); + DDX_Control(pDX, IDC_EDIT_HEIGHT, m_editHeight); + DDX_Control(pDX, IDC_EDIT_WIDTH, m_editWidth); + DDX_Control(pDX, IDC_CURTILE, m_loadlevelname); + DDX_Control(pDX, IDC_SAVELEVEL, m_levelname); + DDX_Control(pDX, IDC_SHOWGRIDS, m_showGrids); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CControls, CDialog) + //{{AFX_MSG_MAP(CControls) + ON_BN_CLICKED(IDC_SHOWGRIDS, OnShowgrids) + ON_WM_PAINT() + ON_WM_CREATE() + ON_WM_SIZE() + ON_BN_CLICKED(IDC_WRITEFILE, OnWritefile) + ON_BN_CLICKED(IDC_LOAD, OnLoad) + ON_BN_CLICKED(IDC_CLEAR, OnClear) + ON_EN_KILLFOCUS(IDC_EDIT_HEIGHT, OnKillfocusEditHeight) + ON_EN_KILLFOCUS(IDC_EDIT_WIDTH, OnKillfocusEditWidth) + ON_WM_MEASUREITEM() + ON_WM_DRAWITEM() + ON_LBN_SELCHANGE(IDC_ZONELIST, OnSelchangeZonelist) + ON_BN_CLICKED(IDC_BUTTON_CLASSLIST, OnButtonClasslist) + ON_WM_DESTROY() + ON_WM_KEYDOWN() + ON_BN_CLICKED(IDC_RADIO_TILES, OnRadioTiles) + ON_BN_CLICKED(IDC_RADIO_ZONES, OnRadioZones) + ON_BN_CLICKED(IDC_RADIO_EXITS, OnRadioExits) + ON_BN_CLICKED(IDC_BGCOLOR, OnBgcolor) + ON_BN_CLICKED(IDC_SETMETA_1X1, OnSetmeta1x1) + ON_BN_CLICKED(IDC_SETMETA_2X2, OnSetmeta2x2) + ON_EN_CHANGE(IDC_META_WIDTH, OnChangeMetaWidth) + ON_EN_CHANGE(IDC_META_HEIGHT, OnChangeMetaHeight) + ON_BN_CLICKED(IDC_SHIFTUP, OnShiftup) + ON_BN_CLICKED(IDC_SHIFTRIGHT, OnShiftright) + ON_BN_CLICKED(IDC_SHIFTDOWN, OnShiftdown) + ON_BN_CLICKED(IDC_SHIFTLEFT, OnShiftleft) + ON_BN_CLICKED(IDC_COPYUP, OnCopyup) + ON_BN_CLICKED(IDC_COPYRIGHT, OnCopyright) + ON_BN_CLICKED(IDC_COPYDOWN, OnCopydown) + ON_BN_CLICKED(IDC_COPYLEFT, OnCopyleft) + ON_BN_CLICKED(IDC_BUTTON_LINKEXITS, OnButtonLinkexits) + ON_BN_CLICKED(IDC_WALLCHECK, OnWallcheck) + ON_BN_CLICKED(IDC_SETMETA_3x3, OnSETMETA3x3) + ON_BN_CLICKED(IDC_SETMETA_4x4, OnSETMETA4x4) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CControls message handlers + +void CControls::OnShowgrids() +{ + CChildView* papa; + + if(!::IsWindow(this->m_hWnd)) + return; + + + //grab a pointer to the view + papa = (CChildView*)this->GetParent(); + //if(!papa) + // return; + + // TODO: Add your control notification handler code here + if(m_showGrids.GetCheck()) + { + papa->SetGrids(true); + }else + papa->SetGrids(false); + +} + +void CControls::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + // TODO: Add your message handler code here + + /////////////////Draw Current Tile///////////////// + + // draw Box + dc.MoveTo(15,50); + dc.LineTo(15,74); + dc.MoveTo(15,50); + dc.LineTo(39,50); + dc.MoveTo(39,50); + dc.LineTo(39,74); + dc.MoveTo(39,74); + dc.LineTo(15,74); + //draw current tile + tileList[curTile].BlitToDC(&dc,19,54); + + + // Do not call CDialog::OnPaint() for painting messages +} + + +// grab pointer to the current tile +gkWinShape *CControls::GrabCurTilePointer() +{ + return &tileList[curTile]; +} + +int CControls::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CDialog::OnCreate(lpCreateStruct) == -1) + return -1; + + // TODO: Add your specialized creation code here + + // TODO: Add your specialized creation code here + terrainTiles.Create(NULL, NULL, WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL + , CRect(0,0,0,0), this, 0, 0); + terrainTiles.ShowWindow(SW_SHOW); + + return 0; +} + +void CControls::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + + CRect rect; + this->GetClientRect(&rect); + terrainTiles.SetWindowPos(&wndTop,5,100,rect.Width()-10,189,SWP_SHOWWINDOW ); + + /* + SCROLLINFO info; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_ALL; + info.nPage = 32; + info.nMin = 0; + info.nMax = TERRAINSCROLLMAXV; + info.nPos = 0; + terrainTiles.SetScrollInfo(SB_HORZ, &info); + terrainTiles.SetScrollInfo(SB_VERT, &info); + */ + +} + +gkWinShape* CControls::GrabTileBuffer(){ + return &tileBuff; +} + +void CControls::SetCurTilePointer(int index) +{ + curTile = index; + this->InvalidateRect(0); +} + +// when this button is pressed we want to take the current file +// and write it to a .lvl gb binary +void CControls::OnWritefile() +{ + ofstream output; + CMapWin* mapWin; + int i;//declare on top for compatibility + + char str[80]; + + m_levelname.GetWindowText(str,80); + //m_levelname + if(!strcmp(str,"")) + { + output.open(E_DEFAULTFILENAME, ios::out | ios::binary); + if(output.fail()) + { + this->MessageBox("Couldn't open file bitch ass"); + return; + } + }else{ + output.open(str, ios::out | ios::binary); + if(output.fail()) + { + this->MessageBox("Couldn't open file bitch ass"); + return; + } + } + + //add to drop-down filename list? + if(m_loadLevel.FindStringExact(0,str)==CB_ERR){ + //m_loadLevel.InsertString(0,str); + m_loadLevel.AddString(str); + } + + mapWin = (CMapWin*)(((CChildView*)this->GetParent())->GrabWinMap()); + + output.put((char) 3); //file format version 3 + //2: Added exit arrays + //3: Added exit links + //---------------------write number of classes used------------------- + unsigned char totalTilesUsed = mapWin->getTotalTilesUsed()-1; + output.write(&totalTilesUsed, sizeof(unsigned char)); + + //remap tiles + mapWin->remapMonsters(); + + //---------------------write index of first monster--------------- + short int firstCharacterID; + short int* listOfAllTiles; + + unsigned char firstCharacterIndex; + listOfAllTiles = mapWin->getListOfTilesUsed(); + + firstCharacterID = (E_TILEBMPSIZEX >> 4) * (E_TILEBMPSIZEY >> 4); + + firstCharacterIndex=0; + while((firstCharacterIndex>8) & 0xff)); + + //---------------------write full id for each tile-------------------- + + for(i=1;i<=totalTilesUsed;i++) + output.write((char*)&listOfAllTiles[i],sizeof(short int)); + + //---------------------write level width------------------------------ + unsigned char width = mapWidth; + output.write(&width, sizeof(unsigned char)); + + //----------------------write level pitch----------------------------- + unsigned char pitch; + + pitch = 1; + while(pitch < width) pitch *= 2; + + output.write(&pitch,sizeof(unsigned char)); + + //--------------------write level height------------------------------ + unsigned char height = mapHeight; + output.write(&height, sizeof(unsigned char)); + + //--------------------write level indeces----------------------------- + PicStruct envArray[256][256]; + mapWin->getEnvArray(envArray); + + + int numBGTiles = 0; + int numObjects = 0; + for(i=0;i=firstCharacterIndex){ + numObjects++; + }else{ + numBGTiles++; + } + //output.write(&(envArray[j][i].index), sizeof(unsigned char)); + } + } + + //--------------------write background color--------------------------- + int backgroundColor = mapWin->getBackgroundColor(); + short int modifiedColor = 0; + int mask1 = 0x00FF0000; + int mask2 = 0x0000FF00; + int mask3 = 0x000000FF; + + unsigned char blue = ((backgroundColor & mask1) >> 16); + unsigned char green = ((backgroundColor & mask2) >> 8); + unsigned char red = (backgroundColor & mask3); + + modifiedColor |= (blue >> 3)<< 10; + modifiedColor |= (green >> 3)<< 5; + modifiedColor |= (red >> 3); + + output.write((char *)&modifiedColor,sizeof(short int)); + + //--------------------let the WayPointList write itself---------------- + g_wayPointList.Write(output); + + //------------tell the map to write the zones & exit info-------------- + mapWin->WriteZones(output); + mapWin->WriteExits(output); + + //------------Write the exit links------------------------------------- + output << (char) 0 << (char) 0; + for(i=1; i<8; i++){ + output << (char) (links[i] & 0xff) << (char) ((links[i]>>8) & 0xff); + } + + output.close(); + + //Display results + char st[80]; + ostrstream stout(st,80); + stout << "Number of Classes: " << (mapWin->getTotalTilesUsed()-1) << endl; + stout << "Number of Objects: " << numObjects << ends; + MessageBox(st,"Statistics"); +} + + +int CControls::GrabCurTileIndex() +{ + return curTile; +} + + +void CControls::OnCancel() +{ + // TODO: Add extra cleanup here + +// CDialog::OnCancel(); +} + +void CControls::OnOK() +{ + // TODO: Add extra validation here + +// CDialog::OnOK(); +} + +void CControls::OnLoad() +{ + // TODO: Add your control notification handler code here + char str[80]; + m_loadLevel.GetWindowText(str,80); + m_levelname.SetWindowText(str); + + CMapWin* mapWin; + mapWin = (CMapWin*)(((CChildView*)this->GetParent())->GrabWinMap()); + + + if(!strcmp(str,"")) + { + this->MessageBox("You need to specify a level name bitch ass"); + return; + } + + //add to drop-down filename list? + if(m_loadLevel.FindStringExact(0,str)==CB_ERR){ + m_loadLevel.InsertString(0,str); + } + + mapWin->loadLevel(str); + offset_x = 0; + offset_y = 0; +} + +void CControls::OnClear() +{ + // TODO: Add your control notification handler code here + CMapWin* mapWin; + mapWin = (CMapWin*)(((CChildView*)this->GetParent())->GrabWinMap()); + mapWin->clearLevel(); + mapWin->InvalidateRect(0); + + links[0] = 0x4040; //+0, +0 + links[1] = 0x4081; //+0,-1 + links[2] = 0x4140; //+1,+0 + links[3] = 0x4041; //+0,+1 + links[4] = 0x8140; //-1,+0 + links[5] = links[6] = links[7] = 0x4040; + + m_levelname.SetWindowText("unnamed.lvl"); +} + +//return a pointer to a picture at a given index +gkWinShape* CControls::GrabPicAt(int index) +{ + return &tileList[index]; +} + +int CControls::GetMapWidth() +{ + return mapWidth; +} + +int CControls::GetMapHeight() +{ + return mapHeight; +} + +void CControls::SetMapWidth(int n) +{ + mapWidth = n; + char st[80]; + ostrstream stout(st,80); + stout << n << ends; + m_editWidth.SetWindowText(st); + +} + +void CControls::SetMapHeight(int n) +{ + mapHeight = n; + char st[80]; + ostrstream stout(st,80); + stout << n << ends; + m_editHeight.SetWindowText(st); +} + +void CControls::SetOffsetX(int n) +{ + offset_x = n; +} + +void CControls::SetOffsetY(int n) +{ + offset_y = n; +} + +int CControls::GetOffsetX() +{ + return offset_x; +} + +int CControls::GetOffsetY() +{ + return offset_y; +} + +void CControls::OnKillfocusEditHeight() +{ + char st[80]; + m_editHeight.GetWindowText(st,80); + istrstream stin(st,80); + stin >> mapHeight; + offset_y = 0; + + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *mapWin = view->GrabWinMap(); + mapWin->SetScrollBarPositions(); + mapWin->InvalidateRect(0); +} + +void CControls::OnKillfocusEditWidth() +{ + char st[80]; + m_editWidth.GetWindowText(st,80); + istrstream stin(st,80); + stin >> mapWidth; + offset_x = 0; + + //discover map pitch + mapPitch = 0; + int temp = mapWidth-1; + while(temp){ + temp = (temp>>1) & 0x7f; + mapPitch = (mapPitch<<1) | 1; + } + mapPitch++; + g_wayPointList.SetPitch(mapPitch); + + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *mapWin = view->GrabWinMap(); + mapWin->SetScrollBarPositions(); + mapWin->InvalidateRect(0); +} + +void CControls::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) +{ + lpMeasureItemStruct->itemWidth = 16; + lpMeasureItemStruct->itemHeight = 16; + + CDialog::OnMeasureItem(nIDCtl, lpMeasureItemStruct); +} + + +void CControls::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + + CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); +} + +BOOL CControls::OnInitDialog() +{ + CDialog::OnInitDialog(); + + HANDLE findFileHandle; + WIN32_FIND_DATA findFileData; + + findFileHandle = FindFirstFile("L*.lvl",&findFileData); + do{ + m_loadLevel.AddString(findFileData.cFileName); + }while(FindNextFile(findFileHandle,&findFileData)); + /* + ifstream recentFiles("recentFiles.txt",ios::in|ios::nocreate); + if(!(!recentFiles)){ + char st[80]; + recentFiles.getline(st,80); + while(!recentFiles.eof()){ + m_loadLevel.AddString(st); + recentFiles.getline(st,80); + } + + recentFiles.close(); + } + */ + + int i; + for(i=0; i<16; i++) m_zoneList.AddString((char*) i); + + m_zoneList.SetCurSel(0); + + m_editWidth.SetWindowText("32"); + m_editHeight.SetWindowText("32"); + + m_radioTiles.SetCheck(1); + + m_metaWidth.SetWindowText("1"); + m_metaHeight.SetWindowText("1"); + + m_wallCheck.SetCheck(0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CControls::OnCheckShowzones() +{ + /* + if(m_checkShowZones.GetCheck()){ + drawingZones = m_zoneList.GetCurSel(); + }else{ + drawingZones = -1; + } + + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *map = view->GrabWinMap(); + + map->InvalidateRect(0); + */ +} + +int CControls::GetDrawingZones() +{ + return drawingZones; +} + +void CControls::OnSelchangeZonelist() +{ + if(drawingZones>=0) drawingZones = m_zoneList.GetCurSel(); + else if(drawingExits>=0) drawingExits = MapIndexToExit(m_zoneList.GetCurSel()); +} + +int CControls::GetMapPitch() +{ + return mapPitch; +} + +void CControls::OnButtonClasslist() +{ + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *map = view->GrabWinMap(); + + CClassList classList; + classList.listOfTilesUsed = map->getListOfTilesUsed(); + classList.listOfAllTiles = map->getListOfAllTiles(); + classList.totalTilesUsed = map->getTotalTilesUsed(); + classList.tileList = this->tileList; + classList.DoModal(); + + map->RemakeListOfTilesUsed(); +} + +void CControls::OnDestroy() +{ + //write out recent files list + /* + ofstream outfile("recentFiles.txt",ios::out); + char st[80]; + int n = m_loadLevel.GetCount(); + int i; + for(i=0; i20) break; + m_loadLevel.GetLBText(i,st); + outfile << st << endl; + } + outfile.close(); + */ + + CDialog::OnDestroy(); +} + +void CControls::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + switch(nChar){ + case VK_LEFT: + curTile--; + this->InvalidateRect(0); + break; + case VK_RIGHT: + curTile++; + this->InvalidateRect(0); + break; + case VK_UP: + curTile-=32; + this->InvalidateRect(0); + break; + case VK_DOWN: + curTile+=32; + this->InvalidateRect(0); + break; + } + if(curTile<0) curTile=0; + else if(curTile>E_LASTTILE) curTile=E_LASTTILE; + CDialog::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CControls::SendToKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + OnKeyDown(nChar,nRepCnt,nFlags); +} + +void CControls::OnRadioTiles() +{ + drawingZones = -1; + drawingExits = -1; + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *map = view->GrabWinMap(); + + map->InvalidateRect(0); + m_zoneList.InvalidateRect(0); +} + +void CControls::OnRadioZones() +{ + drawingZones = m_zoneList.GetCurSel(); + drawingExits = -1; + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *map = view->GrabWinMap(); + + map->InvalidateRect(0); + m_zoneList.InvalidateRect(0); +} + +void CControls::OnRadioExits() +{ + drawingZones = -1; + drawingExits = MapIndexToExit(m_zoneList.GetCurSel()); + + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *map = view->GrabWinMap(); + + map->InvalidateRect(0); + m_zoneList.InvalidateRect(0); +} + +int CControls::MapIndexToExit(int n) +{ + static int map[17] = {7,4,4,7, 1,5,6,3, 1,5,6,3, 7,2,2,7}; + return map[n]; +} + +int CControls::GetDrawingExits() +{ + return drawingExits; +} + +void CControls::OnBgcolor() +{ + CChildView *view = (CChildView*) this->GetParent(); + CMapWin *map = view->GrabWinMap(); + + CBGColorDialog dialog; + + int color = map->getBackgroundColor(); + dialog.initRed = (color & 0xff); + dialog.initGreen = ((color >> 8) & 0xff); + dialog.initBlue = ((color >> 16) & 0xff); + + if(dialog.DoModal()==IDOK){ + int r = dialog.initRed; + int g = dialog.initGreen; + int b = dialog.initBlue; + color = (b<<16) | (g<<8) | r; + map->setBackgroundColor(color); + map->InvalidateRect(0); + } +} + +void CControls::OnSetmeta1x1() +{ + isWall = 0; + m_wallCheck.SetCheck(0); + + metaWidth = metaHeight = 1; + m_metaWidth.SetWindowText("1"); + m_metaHeight.SetWindowText("1"); +} + +void CControls::OnSetmeta2x2() +{ + isWall = 0; + m_wallCheck.SetCheck(0); + + metaWidth = metaHeight = 2; + m_metaWidth.SetWindowText("2"); + m_metaHeight.SetWindowText("2"); +} + +void CControls::OnChangeMetaWidth() +{ + metaWidth = LimitEditValue(m_metaWidth, 1, 10); +} + +int CControls::LimitEditValue(CEdit &edit, int min, int max) +{ + char st[80]; + edit.GetWindowText(st,80); + + istrstream stin(st,80); + int n; + stin >> n; + + if(n < min || n > max){ + if(n 1000 +#pragma once +#endif // _MSC_VER > 1000 +// Controls.h : header file +// + +#include "wingk.h" +#include "TerrainTiles.h" +#include "ZoneList.h" + +///////////////////////////////////////////////////////////////////////////// +// CControls dialog + +class CControls : public CDialog +{ +// Construction +public: + int GetSortClassesBy(); + int links[8]; + int areaSpecial; + gkWinShape* GrabTilePointer(int n); + int LimitEditValue(CEdit &edit, int min, int max); + int metaWidth, metaHeight, isWall; + int GetDrawingExits(); + int MapIndexToExit(int n); + void SendToKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + int GetMapPitch(); + int GetDrawingZones(); + void SetOffsetX(int n); //at what point in the map is the TL corner of view? + void SetOffsetY(int n); + int GetOffsetX(); + int GetOffsetY(); + + int GetMapWidth(); + int GetMapHeight(); + void SetMapWidth(int n); + void SetMapHeight(int n); + CControls(CWnd* pParent = NULL); // standard constructor + + //return the current tile pointer + gkWinShape *GrabCurTilePointer(); + //return the full tile buffer + gkWinShape* GrabTileBuffer(); + //return a pointer to a picture at a given index + gkWinShape* GrabPicAt(int); + void SetCurTilePointer(int index); + int GrabCurTileIndex(); + +// Dialog Data + //{{AFX_DATA(CControls) + enum { IDD = IDD_CONTROLS }; + CButton m_sortClassesBy; + CButton m_wallCheck; + CButton m_copyDown; + CButton m_copyLeft; + CButton m_copyRight; + CButton m_copyUp; + CButton m_shiftUp; + CButton m_shiftRight; + CButton m_shiftLeft; + CButton m_shiftDown; + CEdit m_metaHeight; + CEdit m_metaWidth; + CButton m_radioTiles; + CComboBox m_loadLevel; + CZoneList m_zoneList; + CEdit m_editHeight; + CEdit m_editWidth; + CStatic m_loadlevelname; + CEdit m_levelname; + CButton m_showGrids; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CControls) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + +// Implementation +protected: + int drawingZones, drawingExits; + CTerrainTiles terrainTiles; + int offset_x, offset_y; + int mapPitch; + + // Application Specific Code // + + //buffer for all tiles + gkWinShape tileBuff; + + //current tile index + //REMOVE gkWinShape curTile; + int curTile; + + //list of all tiles + gkWinShape tileList[E_MAXTILES]; + + //current map width and height + int mapWidth, mapHeight; + + + // // // // + + + // Generated message map functions + //{{AFX_MSG(CControls) + afx_msg void OnShowgrids(); + afx_msg void OnPaint(); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnWritefile(); + virtual void OnCancel(); + virtual void OnOK(); + afx_msg void OnLoad(); + afx_msg void OnClear(); + afx_msg void OnKillfocusEditHeight(); + afx_msg void OnKillfocusEditWidth(); + afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct); + afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); + virtual BOOL OnInitDialog(); + afx_msg void OnCheckShowzones(); + afx_msg void OnSelchangeZonelist(); + afx_msg void OnButtonClasslist(); + afx_msg void OnDestroy(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnRadioTiles(); + afx_msg void OnRadioZones(); + afx_msg void OnRadioExits(); + afx_msg void OnBgcolor(); + afx_msg void OnSetmeta1x1(); + afx_msg void OnSetmeta2x2(); + afx_msg void OnChangeMetaWidth(); + afx_msg void OnChangeMetaHeight(); + afx_msg void OnShiftup(); + afx_msg void OnShiftright(); + afx_msg void OnShiftdown(); + afx_msg void OnShiftleft(); + afx_msg void OnCopyup(); + afx_msg void OnCopyright(); + afx_msg void OnCopydown(); + afx_msg void OnCopyleft(); + afx_msg void OnButtonLinkexits(); + afx_msg void OnWallcheck(); + afx_msg void OnSETMETA3x3(); + afx_msg void OnSETMETA4x4(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONTROLS_H__CA2832D1_B4C7_11D3_958B_00A0CC533895__INCLUDED_) diff --git a/Tools/LevelEditor/Source/Current Tile b/Tools/LevelEditor/Source/Current Tile new file mode 100644 index 0000000..e69de29 diff --git a/Tools/LevelEditor/Source/EditDefines.h b/Tools/LevelEditor/Source/EditDefines.h new file mode 100644 index 0000000..a500515 --- /dev/null +++ b/Tools/LevelEditor/Source/EditDefines.h @@ -0,0 +1,67 @@ +/***************************************** +* EditDefines.h +* 12/17/99 +* +* Martin Casado +* +* List of definitions and Macros for +* FGB level editer +********************************************/ + +#ifndef _OBEY_EDITER_LAW_OR_PERISH_IN_ETERNAL_PUDDING_ +#define _OBEY_EDITER_LAW_OR_PERISH_IN_ETERNAL_PUDDING_ + +#include "wingk.h" + + +//width and height of tiles +#define E_TILESIZE 16 + +// name of file which holds tiles +//#define E_TILETITLE "background1-228.bmp" +//#define E_PEOPLETITLE "objects241-308.bmp" + +//size of pic for terrain +#define E_TILEBMPSIZEX 512 +#define E_TILEBMPSIZEY 1024 + +//size of pic for peoples +#define E_PEOPLEBMPSIZEX 512 +#define E_PEOPLEBMPSIZEY 256 + +//TOTAL BUFFER SIZE FOR TILES +#define E_TOTALBUFFERSIZEW 512 +#define E_TOTALBUFFERSIZEH (E_TILEBMPSIZEY + E_PEOPLEBMPSIZEY) + +#define E_LAST_TILE ((((E_PEOPLEBMPSIZEY + E_TILEBMPSIZEY))/16) * 32) + +//struct to define pointer to a shape and the tile number +typedef struct picstruct{ + short int index; + gkWinShape *pic; +}PicStruct; + +//struct used for remapping of tile lists +typedef struct swapstruct{ + unsigned char index; + short int classID; +}SwapStruct; + +//maximum number of tiles for game +#define E_MAXTILES 4096 + +//Verticle and Horizontal scroll maximums for terraintile window +#define TERRAINSCROLLMAXH 512 +#define TERRAINSCROLLMAXV (E_TILEBMPSIZEY + E_PEOPLEBMPSIZEY) + +#define E_LASTTILE ((TERRAINSCROLLMAXV*32)/16) +#define E_FIRSTOBJ (E_TILEBMPSIZEY * 2) + +//default level size in grids +#define E_LEVELSIZEX 32 +#define E_LEVELSIZEY 32 + +//default level name +#define E_DEFAULTFILENAME "test.lvl" + +#endif diff --git a/Tools/LevelEditor/Source/LevelEditor.cpp b/Tools/LevelEditor/Source/LevelEditor.cpp new file mode 100644 index 0000000..d01cc56 --- /dev/null +++ b/Tools/LevelEditor/Source/LevelEditor.cpp @@ -0,0 +1,146 @@ +// LevelEditor.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "LevelEditor.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLevelEditorApp + +BEGIN_MESSAGE_MAP(CLevelEditorApp, CWinApp) + //{{AFX_MSG_MAP(CLevelEditorApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLevelEditorApp construction + +CLevelEditorApp::CLevelEditorApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CLevelEditorApp object + +CLevelEditorApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CLevelEditorApp initialization + +BOOL CLevelEditorApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + // Change the registry key under which our settings are stored. + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization. + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + + + // To create the main window, this code creates a new frame window + // object and then sets it as the application's main window object. + + CMainFrame* pFrame = new CMainFrame; + m_pMainWnd = pFrame; + + // create and load the frame with its resources + + pFrame->LoadFrame(IDR_MAINFRAME, + WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, + NULL); + + + + + // The one and only window has been initialized, so show and update it. + pFrame->ShowWindow(SW_SHOW); + pFrame->UpdateWindow(); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CLevelEditorApp message handlers + + + + + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CLevelEditorApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CLevelEditorApp message handlers + diff --git a/Tools/LevelEditor/Source/LevelEditor.dsp b/Tools/LevelEditor/Source/LevelEditor.dsp new file mode 100644 index 0000000..568c99f --- /dev/null +++ b/Tools/LevelEditor/Source/LevelEditor.dsp @@ -0,0 +1,268 @@ +# Microsoft Developer Studio Project File - Name="LevelEditor" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=LevelEditor - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LevelEditor.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LevelEditor.mak" CFG="LevelEditor - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LevelEditor - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "LevelEditor - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LevelEditor - Win32 Release" + +# PROP BASE Use_MFC 6 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 5 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 +# ADD LINK32 /nologo /subsystem:windows /machine:I386 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy EXE to parent directory +PostBuild_Cmds=copy /y Release\*.exe . +# End Special Build Tool + +!ELSEIF "$(CFG)" == "LevelEditor - Win32 Debug" + +# PROP BASE Use_MFC 6 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 5 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Copy EXE to parent directory +PostBuild_Cmds=copy /y Release\*.exe . +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "LevelEditor - Win32 Release" +# Name "LevelEditor - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\BGColorDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\ChildView.cpp +# End Source File +# Begin Source File + +SOURCE=.\ClassList.cpp +# End Source File +# Begin Source File + +SOURCE=.\ClassListList.cpp +# End Source File +# Begin Source File + +SOURCE=.\Controls.cpp +# End Source File +# Begin Source File + +SOURCE=.\LevelEditor.cpp +# End Source File +# Begin Source File + +SOURCE=.\LevelEditor.rc +# End Source File +# Begin Source File + +SOURCE=.\LinkExitsDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\MainFrm.cpp +# End Source File +# Begin Source File + +SOURCE=.\MapWin.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\TerrainTiles.cpp +# End Source File +# Begin Source File + +SOURCE=.\TileLimitDialog.cpp +# End Source File +# Begin Source File + +SOURCE=.\WayPointList.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZoneList.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\BGColorDialog.h +# End Source File +# Begin Source File + +SOURCE=.\ChildView.h +# End Source File +# Begin Source File + +SOURCE=.\ClassList.h +# End Source File +# Begin Source File + +SOURCE=.\ClassListList.h +# End Source File +# Begin Source File + +SOURCE=.\Controls.h +# End Source File +# Begin Source File + +SOURCE=.\EditDefines.h +# End Source File +# Begin Source File + +SOURCE=.\LevelEditor.h +# End Source File +# Begin Source File + +SOURCE=.\LinkExitsDialog.h +# End Source File +# Begin Source File + +SOURCE=.\MainFrm.h +# End Source File +# Begin Source File + +SOURCE=.\MapWin.h +# End Source File +# Begin Source File + +SOURCE=.\Resource.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\TerrainTiles.h +# End Source File +# Begin Source File + +SOURCE=.\TileLimitDialog.h +# End Source File +# Begin Source File + +SOURCE=.\WayPointList.h +# End Source File +# Begin Source File + +SOURCE=.\ZoneList.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\res\LevelEditor.ico +# End Source File +# Begin Source File + +SOURCE=.\res\LevelEditor.rc2 +# End Source File +# Begin Source File + +SOURCE=.\res\Toolbar.bmp +# End Source File +# End Group +# Begin Group "GraphixUtils" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\wingk.cpp +# End Source File +# Begin Source File + +SOURCE=.\wingk.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/Tools/LevelEditor/Source/LevelEditor.dsw b/Tools/LevelEditor/Source/LevelEditor.dsw new file mode 100644 index 0000000..53ba1b2 --- /dev/null +++ b/Tools/LevelEditor/Source/LevelEditor.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LevelEditor"=.\LevelEditor.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Tools/LevelEditor/Source/LevelEditor.h b/Tools/LevelEditor/Source/LevelEditor.h new file mode 100644 index 0000000..23f1eb6 --- /dev/null +++ b/Tools/LevelEditor/Source/LevelEditor.h @@ -0,0 +1,51 @@ +// LevelEditor.h : main header file for the LEVELEDITOR application +// + +#if !defined(AFX_LEVELEDITOR_H__CA2832C4_B4C7_11D3_958B_00A0CC533895__INCLUDED_) +#define AFX_LEVELEDITOR_H__CA2832C4_B4C7_11D3_958B_00A0CC533895__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CLevelEditorApp: +// See LevelEditor.cpp for the implementation of this class +// + +class CLevelEditorApp : public CWinApp +{ +public: + CLevelEditorApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLevelEditorApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + +public: + //{{AFX_MSG(CLevelEditorApp) + afx_msg void OnAppAbout(); + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LEVELEDITOR_H__CA2832C4_B4C7_11D3_958B_00A0CC533895__INCLUDED_) diff --git a/Tools/LevelEditor/Source/LevelEditor.plg b/Tools/LevelEditor/Source/LevelEditor.plg new file mode 100644 index 0000000..adbf588 --- /dev/null +++ b/Tools/LevelEditor/Source/LevelEditor.plg @@ -0,0 +1,57 @@ + + +
+

Build Log

+

+--------------------Configuration: LevelEditor - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\WINDOWS\TEMP\RSP60B1.TMP" with contents +[ +/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fo"Release/" /Fd"Release/" /FD /c +"D:\Aprogs\FGBEditor\Controls.cpp" +] +Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP60B1.TMP" +Creating temporary file "C:\WINDOWS\TEMP\RSP60B2.TMP" with contents +[ +/nologo /subsystem:windows /incremental:no /pdb:"Release/LevelEditor.pdb" /machine:I386 /out:"Release/LevelEditor.exe" +.\Release\BGColorDialog.obj +.\Release\ChildView.obj +.\Release\ClassList.obj +.\Release\ClassListList.obj +.\Release\Controls.obj +.\Release\LevelEditor.obj +.\Release\LinkExitsDialog.obj +.\Release\MainFrm.obj +.\Release\MapWin.obj +.\Release\StdAfx.obj +.\Release\TerrainTiles.obj +.\Release\TileLimitDialog.obj +.\Release\WayPointList.obj +.\Release\ZoneList.obj +.\Release\wingk.obj +.\Release\LevelEditor.res +] +Creating command line "link.exe @C:\WINDOWS\TEMP\RSP60B2.TMP" +

Output Window

+Compiling... +Controls.cpp +Linking... +LINK : warning LNK4089: all references to "comdlg32.dll" discarded by /OPT:REF +Creating temporary file "C:\WINDOWS\TEMP\RSP6130.BAT" with contents +[ +@echo off +copy /y Release\*.exe . +] +Creating command line "C:\WINDOWS\TEMP\RSP6130.BAT" +Copy EXE to parent directory +Release\LevelEditor.exe + 1 file(s) copied + + + +

Results

+LevelEditor.exe - 0 error(s), 1 warning(s) +
+ + diff --git a/Tools/LevelEditor/Source/LevelEditor.rc b/Tools/LevelEditor/Source/LevelEditor.rc new file mode 100644 index 0000000..000af75 --- /dev/null +++ b/Tools/LevelEditor/Source/LevelEditor.rc @@ -0,0 +1,521 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\LevelEditor.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON DISCARDABLE "res\\LevelEditor.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP MOVEABLE PURE "res\\Toolbar.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_MAINFRAME TOOLBAR DISCARDABLE 16, 15 +BEGIN + BUTTON ID_EDIT_CUT + BUTTON ID_EDIT_COPY + BUTTON ID_EDIT_PASTE + SEPARATOR + BUTTON ID_FILE_PRINT + SEPARATOR + BUTTON ID_APP_ABOUT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO + MENUITEM SEPARATOR + MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT + MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY + MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE + END + POPUP "&View" + BEGIN + MENUITEM "&Toolbar", ID_VIEW_TOOLBAR + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About LevelEditor...", ID_APP_ABOUT + END + POPUP "Background" + BEGIN + MENUITEM "Red", MENU_RED + MENUITEM "Black", MENU_BLACK + MENUITEM "Blue", MENU_BLUE + MENUITEM "Yellow", MENU_YELLOW + MENUITEM "White", MENU_WHITE + MENUITEM "Gray", MENU_GRAY + MENUITEM "Green", MENU_GREEN + END + POPUP "Grid" + BEGIN + MENUITEM "Red", GRID_RED + MENUITEM "Black", GRID_BLACK + MENUITEM "White", GRID_WHITE + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE +BEGIN + "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT + VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT + VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT + VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT + VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT + VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT + "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 235, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About LevelEditor" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "LevelEditor Version 1.0",IDC_STATIC,40,10,119,8, + SS_NOPREFIX + LTEXT "Copyright (C) 1999",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP +END + +IDD_CONTROLS DIALOG DISCARDABLE 0, 0, 200, 349 +STYLE WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Show Grids",IDC_SHOWGRIDS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,6,4,54,15 + EDITTEXT IDC_SAVELEVEL,38,190,83,12,ES_AUTOHSCROLL + PUSHBUTTON "Save",IDC_WRITEFILE,6,190,28,13 + COMBOBOX IDC_LOAD_FILENAME,38,210,83,132,CBS_DROPDOWN | + CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Load",IDC_LOAD,6,210,28,13 + PUSHBUTTON "Clear",IDC_CLEAR,6,230,28,13 + EDITTEXT IDC_EDIT_WIDTH,40,252,40,12,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_HEIGHT,40,272,40,12,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Tiles",IDC_RADIO_TILES,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,61,299,47,12 + CONTROL "Zones",IDC_RADIO_ZONES,"Button",BS_AUTORADIOBUTTON,61, + 311,46,12 + CONTROL "Exits",IDC_RADIO_EXITS,"Button",BS_AUTORADIOBUTTON,61, + 323,46,12 + PUSHBUTTON "Class List",IDC_BUTTON_CLASSLIST,101,296,59,14 + LTEXT "Current Tile",IDC_CURTILE,31,33,37,8 + LTEXT "Terrain Tiles",IDC_STATIC,13,50,40,8 + LTEXT "Width",IDC_STATIC,9,252,25,12 + LTEXT "Height",IDC_STATIC,9,272,27,12 + LISTBOX IDC_ZONELIST,11,299,46,42,LBS_OWNERDRAWFIXED | + LBS_NOINTEGRALHEIGHT | LBS_MULTICOLUMN | WS_TABSTOP + LTEXT "Zone List",IDC_STATIC,19,288,56,10 + PUSHBUTTON "BG Color",IDC_BGCOLOR,61,4,45,14 + LTEXT "Metatile",IDC_STATIC,132,5,26,8 + EDITTEXT IDC_META_WIDTH,136,16,24,12,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_META_HEIGHT,136,31,24,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Tiles Wide",IDC_STATIC,100,18,34,8 + LTEXT "Tiles High",IDC_STATIC,100,33,32,8 + PUSHBUTTON "1 x 1",IDC_SETMETA_1X1,165,5,29,12 + PUSHBUTTON "2 x 2",IDC_SETMETA_2X2,165,19,29,12 + GROUPBOX "Area Draw Special",IDC_STATIC,126,186,68,98 + CONTROL "Shift Up",IDC_SHIFTUP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,196,41,10 + CONTROL "Shift Right",IDC_SHIFTRIGHT,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,206,49,10 + CONTROL "Shift Down",IDC_SHIFTDOWN,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,216,51,10 + CONTROL "Shift Left",IDC_SHIFTLEFT,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,226,44,10 + CONTROL "Cut",IDC_COPYUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 132,239,27,10 + CONTROL "Copy",IDC_COPYRIGHT,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,249,32,10 + CONTROL "Paste",IDC_COPYDOWN,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,132,259,34,10 + CONTROL "Copy Left",IDC_COPYLEFT,"Button",BS_AUTOCHECKBOX | NOT + WS_VISIBLE | WS_DISABLED | WS_TABSTOP,132,269,46,10 + PUSHBUTTON "Link Exits",IDC_BUTTON_LINKEXITS,101,314,59,14 + CONTROL "4x4 Wall",IDC_WALLCHECK,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,100,48,44,8 + PUSHBUTTON "3 x 3",IDC_SETMETA_3x3,165,33,29,12 + PUSHBUTTON "4 x 4",IDC_SETMETA_4x4,165,47,29,12 + CONTROL "Sort Classes BG/FG",IDC_SORTCLASSESBY,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,115,332,79,10 +END + +IDD_CLASS_LIST_DIALOG DIALOG DISCARDABLE 0, 0, 149, 215 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Included Classes" +FONT 8, "MS Sans Serif" +BEGIN + LISTBOX IDC_CLASS_LIST,7,7,135,182,LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "Clear All",IDC_CLASSLIST_CLEARALL,48,194,50,14 +END + +IDD_COLORPICKER DIALOG DISCARDABLE 0, 0, 136, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select Background Color" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,79,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,79,24,50,14 + CONTROL "",IDC_COLOR,"Static",SS_BLACKFRAME,7,7,50,24 + EDITTEXT IDC_RED,25,41,32,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "R",IDC_STATIC,11,43,11,9 + EDITTEXT IDC_GREEN,25,56,32,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "G",IDC_STATIC,11,58,11,9 + EDITTEXT IDC_BLUE,25,71,32,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "B",IDC_STATIC,11,73,11,9 +END + +IDD_LINKEXITS DIALOG DISCARDABLE 0, 0, 239, 130 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Link Exits" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,182,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,182,24,50,14 + LTEXT "Links may be expressed in:\n1) Absolute Coordinates\n \t2,5 = map (2,5)", + IDC_STATIC,7,80,97,27 + LTEXT "North",IDC_STATIC,10,10,18,8 + EDITTEXT IDC_NORTHEXIT,37,8,40,14,ES_AUTOHSCROLL + LTEXT "East",IDC_STATIC,11,28,15,8 + EDITTEXT IDC_EASTEXIT,37,26,40,14,ES_AUTOHSCROLL + LTEXT "South",IDC_STATIC,11,45,20,8 + EDITTEXT IDC_SOUTHEXIT,37,43,40,14,ES_AUTOHSCROLL + LTEXT "West",IDC_STATIC,11,63,18,8 + EDITTEXT IDC_WESTEXIT,37,61,40,14,ES_AUTOHSCROLL + LTEXT "Up",IDC_STATIC,95,10,10,8 + EDITTEXT IDC_UPEXIT,121,8,40,14,ES_AUTOHSCROLL + LTEXT "Down",IDC_STATIC,95,27,20,8 + EDITTEXT IDC_DOWNEXIT,121,25,40,14,ES_AUTOHSCROLL + LTEXT "Exit (X)",IDC_STATIC,95,45,23,8 + EDITTEXT IDC_EXITEXIT,121,43,40,14,ES_AUTOHSCROLL + LTEXT "Coords may range from 0-15. +0,+0 indicates no link.", + IDC_STATIC,36,110,170,13 + LTEXT "2) Relative Coordinates (recommended)\n\t+2,+5 = map(this_i+2, this_j+5)", + IDC_STATIC,108,80,124,24 +END + +IDD_TILELIMIT DIALOG DISCARDABLE 0, 0, 143, 66 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select Bank 0 Tile Limit" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,45,46,50,14 + CONTROL "0-135 (preserves Text Box and font)",IDC_LIMIT_TEXTBOX, + "Button",BS_AUTORADIOBUTTON | WS_GROUP,7,7,129,10 + CONTROL "0-199 (preserves font only) ",IDC_LIMIT_FONT,"Button", + BS_AUTORADIOBUTTON,7,19,101,10 + CONTROL "0-255",IDC_LIMIT_NONE,"Button",BS_AUTORADIOBUTTON,7,31, + 34,10 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "LevelEditor MFC Application\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "LevelEditor\0" + VALUE "LegalCopyright", "Copyright (C) 1999\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "LevelEditor.EXE\0" + VALUE "ProductName", "LevelEditor Application\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END + + IDD_CONTROLS, DIALOG + BEGIN + LEFTMARGIN, 6 + RIGHTMARGIN, 194 + TOPMARGIN, 4 + BOTTOMMARGIN, 342 + END + + IDD_CLASS_LIST_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 142 + TOPMARGIN, 7 + BOTTOMMARGIN, 208 + END + + IDD_COLORPICKER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 129 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END + + IDD_LINKEXITS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 232 + TOPMARGIN, 7 + BOTTOMMARGIN, 123 + END + + IDD_TILELIMIT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 136 + TOPMARGIN, 7 + BOTTOMMARGIN, 59 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + IDR_MAINFRAME "LevelEditor" +END + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + AFX_IDS_APP_TITLE "LevelEditor" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright\nAbout" + ID_APP_EXIT "Quit the application; prompts to save documents\nExit" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane\nNext Pane" + ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_WINDOW_SPLIT "Split the active window into panes\nSplit" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection\nErase" + ID_EDIT_CLEAR_ALL "Erase everything\nErase All" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" + ID_EDIT_FIND "Find the specified text\nFind" + ID_EDIT_PASTE "Insert Clipboard contents\nPaste" + ID_EDIT_REPEAT "Repeat the last action\nRepeat" + ID_EDIT_REPLACE "Replace specific text with different text\nReplace" + ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" + ID_EDIT_UNDO "Undo the last action\nUndo" + ID_EDIT_REDO "Redo the previously undone action\nRedo" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" + ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\LevelEditor.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Tools/LevelEditor/Source/LinkExitsDialog.cpp b/Tools/LevelEditor/Source/LinkExitsDialog.cpp new file mode 100644 index 0000000..d99f37f --- /dev/null +++ b/Tools/LevelEditor/Source/LinkExitsDialog.cpp @@ -0,0 +1,188 @@ +// LinkExitsDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "LinkExitsDialog.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//static variables +int CLinkExitsDialog::initNorthExit = 0; +int CLinkExitsDialog::initEastExit = 0; +int CLinkExitsDialog::initSouthExit = 0; +int CLinkExitsDialog::initWestExit = 0; +int CLinkExitsDialog::initUpExit = 0; +int CLinkExitsDialog::initDownExit = 0; +int CLinkExitsDialog::initExitExit = 0; + +///////////////////////////////////////////////////////////////////////////// +// CLinkExitsDialog dialog + + +CLinkExitsDialog::CLinkExitsDialog(CWnd* pParent /*=NULL*/) + : CDialog(CLinkExitsDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLinkExitsDialog) + //}}AFX_DATA_INIT +} + + +void CLinkExitsDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLinkExitsDialog) + DDX_Control(pDX, IDC_WESTEXIT, m_westExit); + DDX_Control(pDX, IDC_UPEXIT, m_upExit); + DDX_Control(pDX, IDC_SOUTHEXIT, m_southExit); + DDX_Control(pDX, IDC_NORTHEXIT, m_northExit); + DDX_Control(pDX, IDC_EXITEXIT, m_exitExit); + DDX_Control(pDX, IDC_EASTEXIT, m_eastExit); + DDX_Control(pDX, IDC_DOWNEXIT, m_downExit); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLinkExitsDialog, CDialog) + //{{AFX_MSG_MAP(CLinkExitsDialog) + ON_EN_KILLFOCUS(IDC_NORTHEXIT, OnKillfocusNorthexit) + ON_EN_KILLFOCUS(IDC_EASTEXIT, OnKillfocusEastexit) + ON_EN_KILLFOCUS(IDC_SOUTHEXIT, OnKillfocusSouthexit) + ON_EN_KILLFOCUS(IDC_WESTEXIT, OnKillfocusWestexit) + ON_EN_KILLFOCUS(IDC_UPEXIT, OnKillfocusUpexit) + ON_EN_KILLFOCUS(IDC_DOWNEXIT, OnKillfocusDownexit) + ON_EN_KILLFOCUS(IDC_EXITEXIT, OnKillfocusExitexit) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLinkExitsDialog message handlers + +void CLinkExitsDialog::DisplayLink(CEdit &edit, int link) +{ + char st[80]; + ostrstream stout(st,80); + int x = (link >> 8) & 0xff; + int y = link & 0xff; + + //x and y are in BCD form; convert to normal (1st digit will be 0 or 1) + //preserve upper 3 bits of each byte unchanged + x = (((x>>4) & 1) * 10 + (x & 0x0f)) | (x & 0xe0); + y = (((y>>4) & 1) * 10 + (y & 0x0f)) | (y & 0xe0); + + if(x < 16) stout << x << ", "; + else if(x & 64) stout << "+" << (x & 15) << ", "; + else stout << "-" << (x & 15) << ", "; + + if(y < 16) stout << y << ends; + else if(y & 64) stout << "+" << (y & 15) << ends; + else stout << "-" << (y & 15) << ends; + + edit.SetWindowText(st); +} + +int CLinkExitsDialog::RetrieveLink(CEdit &edit) +{ + char st[80]; + edit.GetWindowText(st,80); + + int i,x,y; + + //eliminate white space + for(i=0; st[i]; i++){ + if(st[i]!=' ') break; + } + + //get x value + x = 0; + for(; st[i]; i++){ + if(st[i]=='+') x |= 64; + else if(st[i]=='-') x |= 128; + else if(st[i]>='0' && st[i]<='9') x = (x & 0xe0) | ((x & 1) * 10 + (st[i]-'0')); + else break; + } + + //skip comma and whitespace + y = 0; + for(; st[i]; i++){ + if(st[i]!=',' && st[i]!=' ') break; + } + + //get y value + y = 0; + for(; st[i]; i++){ + if(st[i]=='+') y |= 64; + else if(st[i]=='-') y |= 128; + else if(st[i]>='0' && st[i]<='9') y = (y & 0xe0) | ((y & 1) * 10 + (st[i]-'0')); + else break; + } + + //convert values to BCD, preserving upper 3 bits + x = (x & 0xe0) | ((((x & 31)/10)<<4) + ((x&31)%10)); + y = (y & 0xe0) | ((((y & 31)/10)<<4) + ((y&31)%10)); + + i = (x << 8) | y; + + //redisplay our interpretation of the input + DisplayLink(edit,i); + + return i; +} + + +void CLinkExitsDialog::OnKillfocusNorthexit() +{ + initNorthExit = RetrieveLink(m_northExit); +} + + +void CLinkExitsDialog::OnKillfocusEastexit() +{ + initEastExit = RetrieveLink(m_eastExit); +} + +void CLinkExitsDialog::OnKillfocusSouthexit() +{ + initSouthExit = RetrieveLink(m_southExit); +} + +void CLinkExitsDialog::OnKillfocusWestexit() +{ + initWestExit = RetrieveLink(m_westExit); +} + +void CLinkExitsDialog::OnKillfocusUpexit() +{ + initUpExit = RetrieveLink(m_upExit); +} + +void CLinkExitsDialog::OnKillfocusDownexit() +{ + initDownExit = RetrieveLink(m_downExit); +} + +void CLinkExitsDialog::OnKillfocusExitexit() +{ + initExitExit = RetrieveLink(m_exitExit); +} + +BOOL CLinkExitsDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + + DisplayLink(m_northExit, initNorthExit); + DisplayLink(m_eastExit, initEastExit); + DisplayLink(m_southExit, initSouthExit); + DisplayLink(m_westExit, initWestExit); + DisplayLink(m_upExit, initUpExit); + DisplayLink(m_downExit, initDownExit); + DisplayLink(m_exitExit, initExitExit); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/Tools/LevelEditor/Source/LinkExitsDialog.h b/Tools/LevelEditor/Source/LinkExitsDialog.h new file mode 100644 index 0000000..179630c --- /dev/null +++ b/Tools/LevelEditor/Source/LinkExitsDialog.h @@ -0,0 +1,64 @@ +#if !defined(AFX_LINKEXITSDIALOG_H__02AEC5A1_F6B8_11D3_B6CE_525400E2D57B__INCLUDED_) +#define AFX_LINKEXITSDIALOG_H__02AEC5A1_F6B8_11D3_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LinkExitsDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLinkExitsDialog dialog + +class CLinkExitsDialog : public CDialog +{ +// Construction +public: + int RetrieveLink(CEdit &edit); + void DisplayLink(CEdit &edit, int link); + static int initNorthExit, initEastExit, initSouthExit, initWestExit; + static int initUpExit, initDownExit, initExitExit; + + CLinkExitsDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLinkExitsDialog) + enum { IDD = IDD_LINKEXITS }; + CEdit m_westExit; + CEdit m_upExit; + CEdit m_southExit; + CEdit m_northExit; + CEdit m_exitExit; + CEdit m_eastExit; + CEdit m_downExit; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLinkExitsDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLinkExitsDialog) + afx_msg void OnKillfocusNorthexit(); + afx_msg void OnKillfocusEastexit(); + afx_msg void OnKillfocusSouthexit(); + afx_msg void OnKillfocusWestexit(); + afx_msg void OnKillfocusUpexit(); + afx_msg void OnKillfocusDownexit(); + afx_msg void OnKillfocusExitexit(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LINKEXITSDIALOG_H__02AEC5A1_F6B8_11D3_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/LevelEditor/Source/MainFrm.cpp b/Tools/LevelEditor/Source/MainFrm.cpp new file mode 100644 index 0000000..12f5b45 --- /dev/null +++ b/Tools/LevelEditor/Source/MainFrm.cpp @@ -0,0 +1,237 @@ +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "LevelEditor.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + ON_WM_SETFOCUS() + ON_COMMAND(MENU_RED, OnRed) + ON_COMMAND(MENU_BLACK, OnBlack) + ON_COMMAND(MENU_BLUE, OnBlue) + ON_COMMAND(MENU_WHITE, OnWhite) + ON_COMMAND(MENU_YELLOW, OnYellow) + ON_COMMAND(MENU_GRAY, OnGray) + ON_COMMAND(GRID_BLACK, OnGridBlack) + ON_COMMAND(GRID_RED, OnGridRed) + ON_COMMAND(GRID_WHITE, OnGridWhite) + ON_COMMAND(MENU_GREEN, OnGreen) + ON_WM_KEYDOWN() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +static UINT indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here + +} + +CMainFrame::~CMainFrame() +{ +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + // create a view to occupy the client area of the frame + if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, + CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) + { + TRACE0("Failed to create view window\n"); + return -1; + } + + if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP + | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + + // TODO: Delete these three lines if you don't want the toolbar to + // be dockable + m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + DockControlBar(&m_wndToolBar); + + this->ShowWindow(SW_SHOWMAXIMIZED); + + return 0; +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CFrameWnd::PreCreateWindow(cs) ) + return FALSE; + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + cs.dwExStyle &= ~WS_EX_CLIENTEDGE; + cs.lpszClass = AfxRegisterWndClass(0); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers +void CMainFrame::OnSetFocus(CWnd* pOldWnd) +{ + // forward focus to the view window + m_wndView.SetFocus(); +} + +BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) +{ + // let the view have first crack at the command + if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) + return TRUE; + + // otherwise, do default handling + return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + + CChildView m_wndView; + + +void CMainFrame::OnRed() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setBackgroundColor(0x000022); + (m_wndView.GrabWinMap())->InvalidateRect(0); + +} + +void CMainFrame::OnBlack() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setBackgroundColor(0x000000); + (m_wndView.GrabWinMap())->InvalidateRect(0); +} + +void CMainFrame::OnBlue() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setBackgroundColor(0x220000); + (m_wndView.GrabWinMap())->InvalidateRect(0); + +} + +void CMainFrame::OnWhite() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setBackgroundColor(0xffffff); + (m_wndView.GrabWinMap())->InvalidateRect(0); + +} + +void CMainFrame::OnYellow() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setBackgroundColor(0x002222); + (m_wndView.GrabWinMap())->InvalidateRect(0); + +} + +void CMainFrame::OnGray() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setBackgroundColor(0x222222); + (m_wndView.GrabWinMap())->InvalidateRect(0); + + +} + +void CMainFrame::OnGridBlack() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setGridColor(0x010101); + (m_wndView.GrabWinMap())->InvalidateRect(0); + + +} + +void CMainFrame::OnGridRed() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setGridColor(0x0000ff); + (m_wndView.GrabWinMap())->InvalidateRect(0); + +} + +void CMainFrame::OnGridWhite() +{ + // TODO: Add your command handler code here + (m_wndView.GrabWinMap())->setGridColor(0xffffff); + (m_wndView.GrabWinMap())->InvalidateRect(0); + +} + +void CMainFrame::OnGreen() //background green +{ + (m_wndView.GrabWinMap())->setBackgroundColor(0x002200); + (m_wndView.GrabWinMap())->InvalidateRect(0); + + +} + +void CMainFrame::ShowStatus(char *st) +{ + m_wndStatusBar.SetWindowText(st); +} + +void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ +ASSERT(0); + CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags); +} diff --git a/Tools/LevelEditor/Source/MainFrm.h b/Tools/LevelEditor/Source/MainFrm.h new file mode 100644 index 0000000..173a5b6 --- /dev/null +++ b/Tools/LevelEditor/Source/MainFrm.h @@ -0,0 +1,74 @@ +// MainFrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAINFRM_H__CA2832C8_B4C7_11D3_958B_00A0CC533895__INCLUDED_) +#define AFX_MAINFRM_H__CA2832C8_B4C7_11D3_958B_00A0CC533895__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ChildView.h" + +class CMainFrame : public CFrameWnd +{ + +public: + CMainFrame(); +protected: + DECLARE_DYNAMIC(CMainFrame) + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + void ShowStatus(char *st); + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + CChildView m_wndView; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSetFocus(CWnd *pOldWnd); + afx_msg void OnRed(); + afx_msg void OnBlack(); + afx_msg void OnBlue(); + afx_msg void OnWhite(); + afx_msg void OnYellow(); + afx_msg void OnGray(); + afx_msg void OnGridBlack(); + afx_msg void OnGridRed(); + afx_msg void OnGridWhite(); + afx_msg void OnGreen(); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__CA2832C8_B4C7_11D3_958B_00A0CC533895__INCLUDED_) diff --git a/Tools/LevelEditor/Source/MapWin.cpp b/Tools/LevelEditor/Source/MapWin.cpp new file mode 100644 index 0000000..1a5f751 --- /dev/null +++ b/Tools/LevelEditor/Source/MapWin.cpp @@ -0,0 +1,1658 @@ +// MapWin.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "MapWin.h" +#include "Controls.h" +#include "ChildView.h" +#include +#include +#include "MainFrm.h" +#include + + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#include "ChildView.h" +#include "Controls.h" +#include "WayPointList.h" + + +///////////////////////////////////////////////////////////////////////////// +// CMapWin + +CMapWin::CMapWin() +{ + + // Member initializations + showGrids = false; + backgroundColor = 0x808080; + gridColor = 0x0000ff; + curTile = 0; + for(int i=0;i<256;i++) + for(int j=0;j<256;j++) + envArray[i][j].index = 0; + + totalTilesUsed = 1; + for(i=0;i<=256;i++) + listOfTilesUsed[i] = -1; + for(i=0;i<65536;i++) + listOfAllTiles[i] = 0; + + lmb_isDown = rmb_isDown = 0; + drawingPath = 0; + selectedZone = 1; + pathStartX = pathStartY = 0; + + clearLevel(); + + gkWinShape buffer; + buffer.LoadBMP("exitTiles.bmp"); + for(i=0; i<7; i++){ + exitTiles[i+1].GetShape(&buffer,i*16,0,16,16); + exitTiles[i+1].SetAlpha(192); + } + copyWidth = copyHeight = 0; +} + +CMapWin::~CMapWin() +{ +} + + +BEGIN_MESSAGE_MAP(CMapWin, CWnd) + //{{AFX_MSG_MAP(CMapWin) + ON_WM_PAINT() + ON_WM_LBUTTONDOWN() + ON_WM_ERASEBKGND() + ON_WM_RBUTTONDOWN() + ON_WM_SIZE() + ON_WM_HSCROLL() + ON_WM_VSCROLL() + ON_WM_LBUTTONUP() + ON_WM_MOUSEMOVE() + ON_WM_RBUTTONUP() + ON_WM_KEYDOWN() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CMapWin message handlers + +void CMapWin::OnPaint() +{ + //MODIFIED 12.30.1999 ABE + CPaintDC realdc(this); // device context for painting + + //get client window size MOVED 12.30.1999 ABE + CRect rect; + ::GetClientRect(this->m_hWnd,&rect); + + //NEW 12.30.1999 ABE + //variables for double-buffering + //static CBitmap backbuffer; + static int backbufferWidth=0, backbufferHeight=0, needSetup=1; + static gkWinShape tileBuffer; + static gkWinShape wayPoint; + + if(needSetup){ + //Create orange dot waypoint + needSetup = 0; + wayPoint.Create(16,16); + wayPoint.Cls(); + wayPoint.RectFill(5,5,6,6,gkRGB(255,128,0)); + wayPoint.SetColorAlpha(gkRGB(0,0,0), 0); + } + + //check to see if we need to (re)create bitmap + if(backbufferWidth < rect.Width() || backbufferHeight < rect.Height()){ + backbufferWidth = rect.Width(); + backbufferHeight = rect.Height(); + //if(backbuffer.GetSafeHandle() != 0){ + // backbuffer.DeleteObject(); + //} + //backbuffer.CreateCompatibleBitmap(&realdc, backbufferWidth, backbufferHeight); + tileBuffer.Create(backbufferWidth, backbufferHeight); + } + + //create a temporary device context & select the bitmap into it for drawing + //CDC dc; + //dc.CreateCompatibleDC(0); + //CBitmap *oldBitmap = (CBitmap*) dc.SelectObject(&backbuffer); + //END NEW + + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + // how many tiles by X? + int numX; + //how many tiles by Y? + int numY; + + numX = (rect.Width()>>4) + 1; + numY = (rect.Height()>>4) + 1; + + //see how far the screen is scrolled over + int tileOff_x = controls->GetOffsetX() >> 4; + int tileOff_y = controls->GetOffsetY() >> 4; + + //dc.FillSolidRect(0,0, rect.Width(), rect.Height(), backgroundColor); + tileBuffer.Cls(gkRGB(backgroundColor&0xff,(backgroundColor>>8)&0xff, + (backgroundColor>>16)&0xff)); + + //figure out how far to scoot each tile to the left because of scrolling + int pixOff_x = controls->GetOffsetX() & 15; + int pixOff_y = controls->GetOffsetY() & 15; + + + + //go ahead and draw the environment tiles + + //blit all the tiles to the tile backbuffer (to allow for transparency etc) + //then blit the tile backbuffer to the regular backbuffer + for(int i=0;i=controls->GetMapWidth() || tj>=controls->GetMapHeight()){ + continue; + } + + int dx = (i<<4)-pixOff_x; + int dy = (j<<4)-pixOff_y; + + if(controls->GetDrawingZones()==-1){ + if(envArray[i+tileOff_x][j+tileOff_y].index){ + //envArray[i+tileOff_x][j+tileOff_y].pic-> + //BlitToDC(&dc,(i<<4)-pixOff_x,(j<<4)-pixOff_y); + envArray[ti][tj].pic->Blit(&tileBuffer, dx, dy, 0); + } + + if(controls->GetDrawingExits()>0){ //overlay exit if necessary + if(exitArray[ti][tj]) + exitTiles[exitArray[ti][tj]].Blit(&tileBuffer,dx,dy); + }else{ + //flag too much open space + if(tooMuchOpenSpace[i+tileOff_x][j+tileOff_y]==1){ + tileBuffer.RectFillAlpha(dx, dy, 16, 16, gkRGB(128,0,0), 128); + } + } + }else{ + if(envArray[i+tileOff_x][j+tileOff_y].index){ + //envArray[i+tileOff_x][j+tileOff_y].pic-> + //BlitToDC(&dc,(i<<4)-pixOff_x,(j<<4)-pixOff_y); + envArray[ti][tj].pic->BlitHalfBrite(&tileBuffer, dx, dy, 0); + } + + //blit the zone if necessary + if(controls->GetDrawingZones()>-1){ + int color = CZoneList::GetZoneColor(zoneArray[ti][tj]); + //tileBuffer.RectFillAlpha(dx, dy, 16, 16, gkRGB(0,0,0), 128); + int r= color & 0xff; + int g = (color>>8) & 0xff; + int b = (color>>16) & 0xff; + tileBuffer.RectFillAlpha(dx, dy, 16, 16, gkRGB(r,g,b), 128); + } + + } + + + } + } + + //draw WayPoints + if(controls->GetDrawingZones()>-1){ + int nPoints = g_wayPointList.GetNumWayPoints(); + + int n; + for(n=1; n<=nPoints; n++){ + int p = g_wayPointList.GetWayPoint(n); + + int i = p & 0xff; + int j = (p>>8) & 0xff; + int dx = (i<<4) - controls->GetOffsetX(); + int dy = (j<<4) - controls->GetOffsetY(); + wayPoint.Blit(&tileBuffer, dx, dy); + } + } + + // show grids if showGrids is true + if(showGrids){ + + //CPen gridPen; + //if(!gridPen.CreatePen(PS_SOLID,1,gridColor)) + //{ + // //doh! + // ::AfxMessageBox("Pen Creation Failed drawing grids", MB_OK); + // ::AfxAbort(); + //} + + gkRGB lineColor; + lineColor.SetR(gridColor & 0xff); + lineColor.SetG((gridColor>>8) & 0xff); + lineColor.SetB((gridColor>>16) & 0xff); + + //save the old pen + //CPen* oldPen = dc.SelectObject(&gridPen); + + int off_x = controls->GetOffsetX(); + int off_y = controls->GetOffsetY(); + + //draw vertical lines + for(int i=0;i<(controls->GetMapWidth() + 1);i++) + { + tileBuffer.Line((i<<4)-off_x,0,(i<<4)-off_x,rect.Height(),lineColor); + //dc.MoveTo((i<<4)-off_x,0); + //dc.LineTo((i<<4)-off_x,rect.Height()); + } + //draw Horizontal lines + for(i=0;i<(controls->GetMapHeight() + 1);i++) + { + tileBuffer.Line(0,(i<<4)-off_y,rect.Width(),(i<<4)-off_y,lineColor); + //dc.MoveTo(0, (i<<4)-off_y); + //dc.LineTo(rect.Width(), (i<<4)-off_y); + } + + + //reset old pen + //dc.SelectObject(oldPen); + + }// end if(showGrids) + + + + //if we're currently drawing a path then draw just the path so far + if(drawingPath){ + this->DrawPath(selectedZone, drawingPath, tileBuffer); + }else{ + //draw all the paths that originate at the selected zone + if(selectedZone && controls->GetDrawingZones()>-1){ + int otherZone; + for(otherZone=1; otherZone<16; otherZone++){ + int path = g_wayPointList.GetPath(selectedZone, otherZone); + if(path){ + this->DrawPath(otherZone, path, tileBuffer); + } + } + } + } + + //if we're doing a selection rectangle then draw that + if(drawingRect){ + if(controls->GetDrawingZones()!=0){ + int sx = min(rectStartX,rectEndX)<<4; + int sy = min(rectStartY,rectEndY)<<4; + int dx = (max(rectStartX,rectEndX)<<4)+15; + int dy = (max(rectStartY,rectEndY)<<4)+15; + sx -= controls->GetOffsetX(); + dx -= controls->GetOffsetX(); + sy -= controls->GetOffsetY(); + dy -= controls->GetOffsetY(); + gkRGB color = gkRGB(255,255,255); + int curZone = controls->GetDrawingZones(); + if(curZone>0){ + int c = CZoneList::GetZoneColor(curZone); + color.SetR(c&0xff); + color.SetG((c>>8)&0xff); + color.SetB((c>>16)&0xff); + } + tileBuffer.RectFillAlpha(sx,sy,(dx-sx)+1, (dy-sy)+1, color, 128); + }else{ + //moving a waypoint + int sx = rectStartX<<4; + int sy = rectStartY<<4; + int dx = rectEndX<<4; + int dy = rectEndY<<4; + sx -= controls->GetOffsetX(); + dx -= controls->GetOffsetX(); + sy -= controls->GetOffsetY(); + dy -= controls->GetOffsetY(); + gkRGB color = gkRGB(255,255,255); + tileBuffer.Line(sx+7,sy+7,dx+7,dy+7,color); + wayPoint.Blit(&tileBuffer, dx, dy); + } + } + + tileBuffer.BlitToDC(&realdc, 0, 0); + + + //NEW 12.30.1999 ABE + //Blit the backbuffer to the screen + //realdc.BitBlt(0,0,rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY); + + //take bitmap out of temporary DC before the tempDC is destroyed + //dc.SelectObject(oldBitmap); + //END NEW + + // Do not call CWnd::OnPaint() for painting messages +} + +void CMapWin::SetGrids(bool on){ + showGrids = on; + this->InvalidateRect(0); +} + + +BOOL CMapWin::OnEraseBkgnd(CDC* pDC) +{ + // TODO: Add your message handler code here and/or call default + return true; + + //return CWnd::OnEraseBkgnd(pDC); +} + + +int CMapWin::getBackgroundColor(){ + return backgroundColor; +} + + +void CMapWin::setBackgroundColor(int color) +{ + backgroundColor = color; +} + +void CMapWin::setGridColor(int color) +{ + gridColor = color; +} + +void CMapWin::getEnvArray(PicStruct arg[256][256]) +{ + for(int i=0;i<256;i++) + for(int j=0;j<256;j++) + arg[i][j] = envArray[i][j]; +} +unsigned char CMapWin::getTotalTilesUsed() +{ + return totalTilesUsed; +} + +short int* CMapWin::getListOfTilesUsed() +{ + return listOfTilesUsed; +} + +//load a level from the file + +void CMapWin::loadLevel(char *str){ + + ifstream input(str, ios::in | ios::binary | ios::nocreate); + //unsigned char trash;//used to through away unnecessary info on reads + int i; + CControls *controls; + + controls = (CControls*)(((CChildView*)this->GetParent())->GrabControls()); + + if(input.fail()){ + this->MessageBox("Could not open file"); + return; + } + + //clear the current level + clearLevel(); + + // Member initializations + showGrids = false; + curTile = 0; + + int firstCharacterID = (E_TILEBMPSIZEX >> 4) * (E_TILEBMPSIZEY >> 4); + + int version = input.get() & 0xff; + //------------load in total classes used----------------------- + input.read(&totalTilesUsed, sizeof(unsigned char)); + totalTilesUsed++;//must add 1 to compensate for 0 index + //--------------throw away 1rst character index---------------- + int firstCharacterIndex = input.get() & 0xff; + int oldFirstID = (input.get() & 0xff); + oldFirstID |= (input.get() & 0xff) << 8; + + //----------------read monster list into listOfTilesUsed------- + for(i=1;i=firstCharacterIndex){ + listOfTilesUsed[i] += (firstCharacterID - oldFirstID); + } + } + //-------------------set up listOfAllTiles---------------------- + for(i=0;i<256;i++) + if(listOfTilesUsed[i] != -1) + listOfAllTiles[listOfTilesUsed[i]] = 1; + //----------------read level width----------------------------- + unsigned char width; + input.read(&width,sizeof(unsigned char)); + controls->SetMapWidth(width); + //----------------get pitch----------------------------- + int pitch = input.get() & 0xff; + g_wayPointList.SetPitch(pitch); + //-----------------read level height--------------------------- + unsigned char height; + input.read(&height,sizeof(unsigned char)); + controls->SetMapHeight(height); + //-----------------read in level-------------------------------- + for(i=0;iGrabPicAt(listOfTilesUsed[envArray[j][i].index]); + } + //-------------------get the backgruond color------------------- + int bgByte0 = input.get() & 0xff; + int bgByte1 = input.get() & 0xff; + int bgColor = (bgByte1<<8) | bgByte0; + int bg_r = (bgColor & 0x1f) << 3; + int bg_g = ((bgColor>>5) & 0x1f) << 3; + int bg_b = ((bgColor>>10) & 0x1f) << 3; + backgroundColor = (bg_b << 16) | (bg_g << 8) | (bg_r); + + g_wayPointList.Read(input); + + ReadZones(input); + + if(version>=2){ + ReadExits(input); + } + + if(version>=3){ + //read links + input.get(); //1st link always null + input.get(); + for(i=1; i<8; i++){ + int n = (input.get() & 0xff); + n |= (input.get() & 0xff) << 8; + controls->links[i] = n; + } + } + + //be a good poopy + input.close(); + this->SetScrollBarPositions(); + this->InvalidateRect(0); + FlagTooMuchOpenSpace(); + +} + +//we need to remap all the monsters so that listOfTilesUsed is in decending order +void CMapWin::remapMonsters() +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + //----get the ID of the first monster-------------------------------- + short int firstCharacterID; + firstCharacterID = (E_TILEBMPSIZEX >> 4) * (E_TILEBMPSIZEY >> 4); + + //----initialize the sort data-------------------------------------- + unsigned char tempArray[257]; + SwapStruct SortMeArray[257]; + int i,j; + + for(i = 0; i<=256; i++) + { + SortMeArray[i].index = i; + SortMeArray[i].classID = listOfTilesUsed[i]; + } + + + if(controls->GetSortClassesBy()==0){ + //sort linear low to high + //--------------bubble sort here... hehehe ------------------------- + + for(i=0;i<=totalTilesUsed;i++) + { + for( j=0;j<(totalTilesUsed-1);j++) + { + if(SortMeArray[j].classID > SortMeArray[j+1].classID) + {//SWAP!! + SwapStruct tmp; + tmp.classID = SortMeArray[j].classID; + tmp.index = SortMeArray[j].index; + SortMeArray[j].classID = SortMeArray[j+1].classID; + SortMeArray[j].index = SortMeArray[j+1].index; + SortMeArray[j+1].classID = tmp.classID; + SortMeArray[j+1].index = tmp.index; + } + } + } + }else{ + //keep same order except all monsters after all bg tiles + for(i=0;i<=totalTilesUsed;i++) + { + for( j=0;j<(totalTilesUsed-1);j++) + { + if(SortMeArray[j].classID>=firstCharacterID && SortMeArray[j+1].classIDGetMapWidth();i++) + for(j=0;jGetMapHeight();j++) + if(envArray[i][j].index) + envArray[i][j].index = tempArray[envArray[i][j].index]; + +} + +//Clear the level and start fresh... +void CMapWin::clearLevel() +{ + // Member initializations + showGrids = false; + backgroundColor = 0x808080; + gridColor = 0x0000ff; + curTile = 0; + for(int i=0;i<256;i++){ + for(int j=0;j<256;j++){ + envArray[i][j].index = 0; + zoneArray[i][j] = 1; + exitArray[i][j] = 0; + } + } + + totalTilesUsed = 1; + for(i=0;i<=256;i++) + listOfTilesUsed[i] = -1; + for(i=0;i<65536;i++) + listOfAllTiles[i] = 0; + + drawingPath=0; + pathStartX=0; + pathStartY=0; + selectedZone=0; + drawingRect = 0; + + g_wayPointList.Reset(); +} + +//-------------------------------------------------------------------------- +// Mouse Methods +//-------------------------------------------------------------------------- + +void CMapWin::OnRButtonDown(UINT nFlags, CPoint point) +{ + rmb_isDown = 1; + + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = (CControls*) view->GrabControls(); + + if(controls->GetDrawingZones()!=0){ + this->EraseTile(point); + }else{ + //screwing around with path stuff + CPoint tPoint = point; + tPoint.x += controls->GetOffsetX(); + tPoint.y += controls->GetOffsetY(); + + int i = tPoint.x >> 4; + int j = tPoint.y >> 4; + + if(i >= controls->GetMapWidth()) + return; + if(j >= controls->GetMapHeight()) + return; + + if(drawingPath==0){ + //start drawing a path? + if(!g_wayPointList.WayPointExists(i,j)){ + pathStartX = i; + pathStartY = j; + selectedZone = zoneArray[i][j]; + drawingPath = g_wayPointList.BeginPath(selectedZone); + }else{ + //delete waypoint + g_wayPointList.RemoveWayPoint(i,j); + } + this->InvalidateRect(0); + } + } + + CWnd::OnRButtonDown(nFlags, point); +} + + +void CMapWin::OnLButtonDown(UINT nFlags, CPoint point) +{ + this->SetFocus(); + + lmb_isDown = 1; + + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = (CControls*) view->GrabControls(); + + if(controls->GetDrawingZones()!=0){ + if(::GetAsyncKeyState(VK_SHIFT) & 0x8000){ + drawingRect = 1; + rectStartX = (point.x + controls->GetOffsetX()) >> 4; + rectStartY = (point.y + controls->GetOffsetY()) >> 4; + rectEndX = rectStartX; + rectEndY = rectStartY; + + }else{ + this->PlaceCurrentTile(point); + FlagTooMuchOpenSpace(); + } + }else{ + //make a waypoint or add to a path + + //account for scrolling + CPoint tPoint = point; + tPoint.x += controls->GetOffsetX(); + tPoint.y += controls->GetOffsetY(); + + int i = tPoint.x >> 4; + int j = tPoint.y >> 4; + + + if(i >= controls->GetMapWidth()) + return; + if(j >= controls->GetMapHeight()) + return; + + if(drawingPath){ + if(g_wayPointList.WayPointExists(i,j)){ + g_wayPointList.AddWayPointToPath(i,j); + }else{ + int pathnum = g_wayPointList.EndPath(zoneArray[i][j]); + if(::GetAsyncKeyState(VK_SHIFT) & 0x8000){ //make a new path + //make a separate path that is the same w/o last waypoint + int wpcount = 0; + if(g_wayPointList.GetFirstWayPoint(pathnum)>0){ + wpcount++; + while(g_wayPointList.GetNextWayPoint(pathnum)>0) wpcount++; + } + drawingPath = g_wayPointList.BeginPath(selectedZone); + wpcount--; + + if(wpcount>0){ + g_wayPointList.AddWayPointToPath( + g_wayPointList.GetWayPoint(g_wayPointList.GetFirstWayPoint(pathnum))); + int x; + for(x=1; xInvalidateRect(0); + } + + //CWnd::OnLButtonDown(nFlags, point); +} + + +void CMapWin::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + this->SetScrollBarPositions(); + this->InvalidateRect(0); +} + +void CMapWin::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + SCROLLINFO scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + scrollInfo.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; + this->GetScrollInfo(SB_HORZ, &scrollInfo, SIF_ALL); + int pos = this->GetScrollPos(SB_HORZ); + + switch(nSBCode){ + case SB_LEFT: //Scroll to far left. + pos = 0; + break; + case SB_ENDSCROLL: //End scroll. + break; + case SB_LINELEFT: //Scroll left. + pos -= 128; + break; + case SB_LINERIGHT: //Scroll right. + pos += 128; + break; + case SB_PAGELEFT: //Scroll one page left. + pos -= (scrollInfo.nPage * 3) / 4; + break; + case SB_PAGERIGHT: //Scroll one page right. + pos += (scrollInfo.nPage * 3) / 4; + break; + case SB_RIGHT: //Scroll to far right. + pos = scrollInfo.nMax; + break; + case SB_THUMBPOSITION: //Scroll to absolute position + case SB_THUMBTRACK: + pos = nPos; + break; + } + + //adjust pos so it won't be out of bounds (looks nicer than letting win do it) + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + + int mapWidth = controls->GetMapWidth() * 16; + CRect rect; + this->GetClientRect(&rect); + if(pos<0){ + pos = 0; + }else if(pos + rect.Width() > mapWidth){ + pos = mapWidth - rect.Width(); + } + + + scrollInfo.nPos = pos; + this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask); + + controls->SetOffsetX(pos); + this->InvalidateRect(0); +} + +void CMapWin::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + SCROLLINFO scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + scrollInfo.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; + this->GetScrollInfo(SB_VERT, &scrollInfo, SIF_ALL); + int pos = this->GetScrollPos(SB_VERT); + + switch(nSBCode){ + case SB_LEFT: //Scroll to far left. + pos = 0; + break; + case SB_ENDSCROLL: //End scroll. + break; + case SB_LINELEFT: //Scroll left. + pos -= 128; + break; + case SB_LINERIGHT: //Scroll right. + pos += 128; + break; + case SB_PAGELEFT: //Scroll one page left. + pos -= (scrollInfo.nPage * 3) / 4; + break; + case SB_PAGERIGHT: //Scroll one page right. + pos += (scrollInfo.nPage * 3) / 4; + break; + case SB_RIGHT: //Scroll to far right. + pos = scrollInfo.nMax; + break; + case SB_THUMBPOSITION: //Scroll to absolute position + case SB_THUMBTRACK: + pos = nPos; + break; + } + + //adjust pos so it won't be out of bounds (looks nicer than letting win do it) + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + + int mapHeight = controls->GetMapHeight() * 16; + CRect rect; + this->GetClientRect(&rect); + if(pos<0){ + pos = 0; + }else if(pos + rect.Height() > mapHeight){ + pos = mapHeight - rect.Height(); + } + + + scrollInfo.nPos = pos; + this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask); + + controls->SetOffsetY(pos); + this->InvalidateRect(0); + + CWnd::OnVScroll(nSBCode, nPos, pScrollBar); +} + +void CMapWin::SetScrollBarPositions() +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + CRect rect; + this->GetClientRect(&rect); + + int mapWidth = (controls->GetMapWidth() * 16); + int mapHeight = (controls->GetMapHeight() * 16); + int extraWidth = rect.Width() - mapWidth; + int extraHeight = rect.Height() - mapHeight; + + SCROLLINFO scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + + if(extraWidth>=0){ + //don't need the scroll bar + scrollInfo.fMask = SIF_POS | SIF_RANGE; + scrollInfo.nMin = scrollInfo.nMax = scrollInfo.nPos = 0; + this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask); + }else{ + scrollInfo.fMask = SIF_RANGE | SIF_PAGE; + scrollInfo.nMin = 0; + scrollInfo.nMax = mapWidth; + scrollInfo.nPos = 0; + scrollInfo.nPage = rect.Width(); + controls->SetOffsetX(this->GetScrollPos(SB_HORZ)); + this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask); + + } + + if(extraHeight>=0){ + scrollInfo.fMask = SIF_POS | SIF_RANGE; + scrollInfo.nMin = scrollInfo.nMax = scrollInfo.nPos = 0; + this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask); + }else{ + scrollInfo.fMask = SIF_RANGE | SIF_PAGE; + scrollInfo.nMin = 0; + scrollInfo.nMax = mapHeight+15; + scrollInfo.nPos = 0; + scrollInfo.nPage = rect.Height(); + controls->SetOffsetY(this->GetScrollPos(SB_VERT)); + this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask); + } +} + +void CMapWin::PlaceCurrentTile(CPoint point) +{ + + + CPoint originalPoint = point; + + + if(!::IsWindow(this->m_hWnd)) + return; + + //grab a pointer to the view + CChildView* papa; + papa = (CChildView*)this->GetParent(); + CControls *controls = papa->GrabControls(); + + //account for scrolling + point.x += controls->GetOffsetX(); + point.y += controls->GetOffsetY(); + + if((point.x>>4) >= controls->GetMapWidth()) + return; + if((point.y>>4) >= controls->GetMapHeight()) + return; + + if(controls->GetDrawingZones()==-1){ + if(controls->GetDrawingExits()==-1){ + int index = controls->GrabCurTileIndex(); + if(index==1){ + EraseTile(originalPoint); + controls->SetCurTilePointer(1); + return; + } + + int i,j; + int width = controls->metaWidth; + for(j=0; jmetaHeight; j++){ + for(i=0; i>4][point.y>>4] = controls->GetDrawingExits(); + } + }else if(controls->GetDrawingZones()>0){ + //drawing zones, not tiles: + int i = point.x>>4; + int j = point.y>>4; + zoneArray[i][j] = controls->GetDrawingZones(); + }else{ + //placing a waypoint + } + + this->InvalidateRect(0); +} + +void CMapWin::PlaceTile(int tileIndex, CPoint point) +{ + //grab a pointer to the view + CChildView* papa; + papa = (CChildView*)this->GetParent(); + CControls *controls = papa->GrabControls(); + + //lets see if we are placing a new tile + int whatsCurTile; + whatsCurTile = tileIndex; + + int tileExists = listOfAllTiles[whatsCurTile]; + if(controls->isWall){ + int i; + for(i=0; i<16; i++){ + if(!listOfAllTiles[whatsCurTile+i]) tileExists = 0; + } + } + + if(!tileExists) + {//looks like this is a new one :-) + if(totalTilesUsed > 256 || (controls->isWall && totalTilesUsed > 256-15)) + {//have we used 255 tiles yet? + this->MessageBox("You've used too many tiles Bitch Ass"); + return; + } + + if(!controls->isWall){ + listOfTilesUsed[totalTilesUsed++] = whatsCurTile; + listOfAllTiles[whatsCurTile] = 1; + }else{ + int i; + for(i=0; i<16; i++){ + listOfTilesUsed[totalTilesUsed++] = whatsCurTile + i; + listOfAllTiles[whatsCurTile + i] = 1; + } + } + } + + // find game index of tile + int tempIndex; + for(int i = 0; i < totalTilesUsed; i++){ + if(listOfTilesUsed[i] == whatsCurTile){ + tempIndex = i; + } + } + + int dx = point.x >> 4; + int dy = point.y >> 4; + + //if part of a wall, change the drawn index based on surrounding similar walls + int offsetOriginal=0; + int offset = 0; + + static int offsetRemap[16] = + { 0, 12, 1, 13, + 4, 8, 5, 9, + 3, 15, 2, 14, + 7, 11, 6, 10 + }; + + static int offsetRemapBack[16] = + { 0, 2, 10, 8, + 4, 6, 14, 12, + 5, 7, 15, 13, + 1, 3, 11, 9 + }; + + if(controls->isWall){ + if(dy > 0 && (((envArray[dx][dy-1].index - tempIndex) | 15) == 15)) offset |= 1; + if(dx < controls->GetMapWidth()-1 && (((envArray[dx+1][dy].index - tempIndex) | 15)) == 15) offset |= 2; + if(dy < controls->GetMapHeight()-1 && (((envArray[dx][dy+1].index - tempIndex) | 15)) == 15) offset |= 4; + if(dx > 0 && (((envArray[dx-1][dy].index - tempIndex) | 15) == 15)) offset |= 8; + + /* + { 0, 2, 10, 8, + 4, 6, 14, 12, + 5, 7, 15, 13, + 1, 3, 11, 9}; + */ + + offsetOriginal = offset; + offset = offsetRemap[offset]; + } + + //CHANGE grab real index from controls + envArray[dx][dy].index = (tempIndex+offset); + envArray[dx][dy].pic = papa->GrabControls()->GrabTilePointer(tileIndex+offset); + + //make sure adjacent similar walls are modified accordingly + if(offsetOriginal & 1){ + int off = offsetRemap[offsetRemapBack[envArray[dx][dy-1].index - tempIndex] | 4]; + envArray[dx][dy-1].index = tempIndex + off; + envArray[dx][dy-1].pic = controls->GrabTilePointer(tileIndex + off); + } + if(offsetOriginal & 2){ + int off = offsetRemap[offsetRemapBack[envArray[dx+1][dy].index - tempIndex] | 8]; + envArray[dx+1][dy].index = tempIndex + off; + envArray[dx+1][dy].pic = controls->GrabTilePointer(tileIndex + off); + } + if(offsetOriginal & 4){ + int off = offsetRemap[offsetRemapBack[envArray[dx][dy+1].index - tempIndex] | 1]; + envArray[dx][dy+1].index = tempIndex + off; + envArray[dx][dy+1].pic = controls->GrabTilePointer(tileIndex + off); + } + if(offsetOriginal & 8){ + int off = offsetRemap[offsetRemapBack[envArray[dx-1][dy].index - tempIndex] | 2]; + envArray[dx-1][dy].index = tempIndex + off; + envArray[dx-1][dy].pic = controls->GrabTilePointer(tileIndex + off); + } +} + +void CMapWin::OnLButtonUp(UINT nFlags, CPoint point) +{ + lmb_isDown = 0; + + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + if(drawingRect){ + + drawingRect = 0; + + if(controls->GetDrawingZones()!=0){ + { + int temp; + if(rectEndY < rectStartY){ + temp = rectStartY; + rectStartY = rectEndY; + rectEndY = temp; + } + if(rectEndX < rectStartX){ + temp = rectStartX; + rectStartX = rectEndX; + rectEndX = temp; + } + } + if(controls->areaSpecial==0){ //no special fx + //loop through every tile in the rect, drawing an item there + int i,j; + int lineToggle = 1; + for(j=rectStartY; j<=rectEndY; j+=controls->metaHeight){ + int toggle = lineToggle; + lineToggle ^= 1; + for(i=rectStartX; i<=rectEndX; i+=controls->metaWidth){ + CPoint curPoint; + if(!(::GetKeyState(VK_MENU) & 0x8000) || toggle){ + curPoint.x = (i<<4) - controls->GetOffsetX(); + curPoint.y = (j<<4) - controls->GetOffsetY(); + PlaceCurrentTile(curPoint); + } + toggle ^= 1; + } + } + FlagTooMuchOpenSpace(); + }else{ + //do a special effect in the rect + + //if paste force the rect to be at least as large as the copy size + if(controls->areaSpecial & 64){ + int width = rectEndX - rectStartX + 1; + int height = rectEndY - rectStartY + 1; + if(width < copyWidth) width = copyWidth; + if(height < copyHeight) height = copyHeight; + rectEndX = rectStartX + width - 1; + rectEndY = rectStartY + height - 1; + } + + //clip the rect first + if(rectStartX<0) rectStartX = 0; + if(rectStartY<0) rectStartY = 0; + if(rectEndX >= controls->GetMapWidth()) rectEndX = controls->GetMapWidth()-1; + if(rectEndY >= controls->GetMapHeight()) rectEndY = controls->GetMapHeight()-1; + + int i,j; + picstruct temp; + + if(controls->areaSpecial & 1){ //shift up + for(i=rectStartX; i<=rectEndX; i++){ + temp = envArray[i][rectStartY]; + for(j=rectStartY; jareaSpecial & 2){ //shift right + for(j=rectStartY; j<=rectEndY; j++){ + temp = envArray[rectEndX][j]; + for(i=rectEndX; i>rectStartX; i--){ + envArray[i][j] = envArray[i-1][j]; + } + envArray[rectStartX][j] = temp; + } + } + if(controls->areaSpecial & 4){ //shift down + for(i=rectStartX; i<=rectEndX; i++){ + temp = envArray[i][rectEndY]; + for(j=rectEndY; j>rectStartY; j--){ + envArray[i][j] = envArray[i][j-1]; + } + envArray[i][rectStartY] = temp; + } + } + if(controls->areaSpecial & 8){ //shift left + for(j=rectStartY; j<=rectEndY; j++){ + temp = envArray[rectStartX][j]; + for(i=rectStartX; iareaSpecial & 16){ //copy up (cut) + for(i=rectStartX; i<=rectEndX; i++){ + for(j=rectStartY; j<=rectEndY; j++){ + copyBuffer[i-rectStartX][j-rectStartY] = envArray[i][j]; + envArray[i][j].index = 0; + } + } + copyWidth = rectEndX - rectStartX + 1; + copyHeight = rectEndY - rectStartY + 1; + } + if(controls->areaSpecial & 32){ //copy right (copy) + for(i=rectStartX; i<=rectEndX; i++){ + for(j=rectStartY; j<=rectEndY; j++){ + copyBuffer[i-rectStartX][j-rectStartY] = envArray[i][j]; + } + } + copyWidth = rectEndX - rectStartX + 1; + copyHeight = rectEndY - rectStartY + 1; + } + if(controls->areaSpecial & 64){ //copy down (paste) + for(i=rectStartX; i<=rectEndX; i++){ + for(j=rectStartY; j<=rectEndY; j++){ + envArray[i][j] = copyBuffer[(i-rectStartX)%copyWidth][(j-rectStartY)%copyHeight]; + } + } + } + if(controls->areaSpecial & 128){ //copy left + for(i=rectStartX; i<=rectEndX; i++){ + for(j=rectStartY; j<=rectEndY; j++){ + int di = i - rectWidth; + int dj = j; + if(di<0||dj<0||di>255||dj>255) continue; + + envArray[di][dj] = envArray[i][j]; + } + } + } + } + }else{ + //moving waypoint + g_wayPointList.MoveWayPoint(rectStartX, rectStartY, rectEndX, rectEndY); + } + + this->InvalidateRect(0); + this->FlagTooMuchOpenSpace(); + } + + CWnd::OnLButtonUp(nFlags, point); +} + +void CMapWin::OnMouseMove(UINT nFlags, CPoint point) +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + CMainFrame *frame = (CMainFrame*) this->GetParentFrame(); + + if(lmb_isDown){ + if(drawingRect){ + rectEndX = (point.x + controls->GetOffsetX())>>4; + rectEndY = (point.y + controls->GetOffsetY())>>4; + this->InvalidateRect(0); + }else{ + this->PlaceCurrentTile(point); + FlagTooMuchOpenSpace(); + } + }else if(rmb_isDown){ + this->EraseTile(point); + }else if(drawingPath){ + this->InvalidateRect(0); + } + + int i = (point.x + controls->GetOffsetX()) >> 4; + int j = (point.y + controls->GetOffsetY()) >> 4; + + char st[80]; + ostrstream stout(st,80); + stout << "(" << i << "," << j; + g_wayPointList.GetPitch(); + stout << " / $" << (hex) << (0xd000 + (j * g_wayPointList.GetPitch()) + i); + stout << (dec) << ") index: " << envArray[i][j].index; + stout << " class: " << listOfTilesUsed[envArray[i][j].index]; + stout << " zone: " << (int) zoneArray[i][j] << ends; + frame->ShowStatus(st); + + CWnd::OnMouseMove(nFlags, point); +} + +void CMapWin::EraseTile(CPoint point) +{ + if(!::IsWindow(this->m_hWnd)) + return; + //grab a pointer to the view + CControls *controls; + controls = (CControls*)(((CChildView*)this->GetParent())->GrabControls()); + + //account for scrolling + point.x += controls->GetOffsetX(); + point.y += controls->GetOffsetY(); + + int i = point.x>>4; + int j = point.y>>4; + if(i>=0 && j>=0 && iGetMapWidth() && jGetMapHeight()){ + if(controls->GetDrawingZones()==-1){ + if(controls->GetDrawingExits()==-1){ + int curIndex = envArray[i][j].index; + + if(curIndex>0){ + //set the current tile + controls->SetCurTilePointer(listOfTilesUsed[envArray[point.x>>4][point.y>>4].index]); + } + + //reset index to zero + envArray[point.x>>4][point.y>>4].index = 0; + }else{ + //erasing exits + exitArray[point.x>>4][point.y>>4] = 0; + } + }else if(!drawingPath){ + //"erase" selects a zone when drawing zones + this->selectedZone = zoneArray[i][j]; + this->pathStartX = i; + this->pathStartY = j; + } + } + + this->InvalidateRect(0); + FlagTooMuchOpenSpace(); +} + +void CMapWin::OnRButtonUp(UINT nFlags, CPoint point) +{ + rmb_isDown = 0; + + CWnd::OnRButtonUp(nFlags, point); +} + +void CMapWin::DrawPath(int destZone, int nPath, gkWinShape &tileBuffer) +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + int c = CZoneList::GetZoneColor(destZone); + gkRGB color(c&0xff, (c>>8)&0xff, (c>>16)&0xff); + int prev_i = pathStartX; + int prev_j = pathStartY; + int next_i; + int next_j; + //CPoint tempP; + //if(::GetCursorPos(&tempP)){ +// if(tempP.x > 600) ASSERT(0); +// } + int afterFirst = 0; + int nextWP = g_wayPointList.GetFirstWayPoint(nPath); + while(nextWP){ + + int wp = g_wayPointList.GetWayPoint(nextWP); + next_i = wp & 0xff; + next_j = (wp>>8) & 0xff; + int si = (prev_i<<4) - controls->GetOffsetX() + (destZone&afterFirst); + int sj = (prev_j<<4) - controls->GetOffsetY() + (destZone&afterFirst); + int di = (next_i<<4) - controls->GetOffsetX() + destZone; + int dj = (next_j<<4) - controls->GetOffsetY() + destZone; + afterFirst = 0xffffffff; + + tileBuffer.Line(si,sj,di,dj,color); + + prev_i = next_i; + prev_j = next_j; + nextWP = g_wayPointList.GetNextWayPoint(nPath); + } + + //connect to mouse if currently drawing + if(drawingPath){ + CPoint mousePoint; + ::GetCursorPos(&mousePoint); + this->ScreenToClient(&mousePoint); + + int si = (prev_i<<4) - controls->GetOffsetX() + destZone; + int sj = (prev_j<<4) - controls->GetOffsetY() + destZone; + int di = mousePoint.x; + int dj = mousePoint.y; + + tileBuffer.Line(si,sj,di,dj,color); + } +} + +void CMapWin::WriteZones(ostream &out) +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + //pack the zone bytes 2:1 + int compressed[128][256]; + int i,j; + for(j=0; jGetMapHeight(); j++){ + for(i=0; iGetMapWidth(); i+=2){ + int byte1 = this->zoneArray[i][j] & 0x0f; + int byte2 = zoneArray[i+1][j] & 0x0f; + compressed[i/2][j] = (byte1<<4) | byte2; + } + } + + //write out zone info using RLE + int numContinuous = 0; + int continuousByte = compressed[0][0]; + for(j=0; jGetMapHeight(); j++){ + for(i=0; i<(controls->GetMapWidth()>>1); i++){ + if(compressed[i][j] == continuousByte){ + numContinuous++; + }else{ + out.put((char) numContinuous); + out.put((char) continuousByte); + continuousByte = compressed[i][j]; + numContinuous = 1; + } + if(numContinuous == 256){ + out.put((char) 255); + out.put((char) continuousByte); + numContinuous = 1; + } + } + } + out.put((char) numContinuous); + out.put((char) continuousByte); +// if(numContinuous != 0){ +// out.put((char) 0); +// out.put((char) 0); +// } +} + +void CMapWin::ReadZones(istream &in) +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + //reads & inflates zones stored using Run Lengh Encoding and compressed 2:1 + int i,j,continuousByte,numContinuous; + + int temp = in.tellg(); + numContinuous = in.get() & 0xff; + if(in.eof()) return; + continuousByte = in.get() & 0xff; + + for(j=0; jGetMapHeight(); j++){ + for(i=0; iGetMapWidth(); i+=2){ + if(!numContinuous){ + numContinuous = in.get() & 0xff; + continuousByte = in.get() & 0xff; + } + zoneArray[i][j] = (continuousByte>>4) & 0x0f; + zoneArray[i+1][j] = continuousByte & 0x0f; + numContinuous--; + } + } + + //in.get(); //junk null terminator + //in.get(); +} + +short int * CMapWin::getListOfAllTiles() +{ + return this->listOfAllTiles; +} + +void CMapWin::RemakeListOfTilesUsed() +{ + //regenerates the tiles used list using the tiles from the map and the tiles + //in the list of all tiles. Called after the "classes used" dialog finishes. + + //first off flag any of the classes used in the map in the "listOfAllClasses" + //and convert the map indices into actual classes + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + int i,j; + for(i=0; i<256; i++){ + for(j=0; j<256; j++){ + if(envArray[i][j].index){ + if(iGetMapWidth() && jGetMapHeight()){ + listOfAllTiles[listOfTilesUsed[envArray[i][j].index]] = 1; + envArray[i][j].index = listOfTilesUsed[envArray[i][j].index]; + }else{ + envArray[i][j].index = 0; + } + } + } + } + + //clear the list of tiles used + totalTilesUsed = 1; + for(i=0;i<=256;i++) + listOfTilesUsed[i] = -1; + + //refresh the listOfTilesUsed from the listOfAllTiles + for(i=0; i<65536; i++){ + if(listOfAllTiles[i]){ + listOfTilesUsed[totalTilesUsed++] = i; + } + } + + //remap each location in the map back to an index + for(i=0; i<256; i++){ + for(j=0; j<256; j++){ + int lookfor = envArray[i][j].index; + if(lookfor){ + int n; + for(n=1; n<=totalTilesUsed; n++){ + if(listOfTilesUsed[n]==lookfor){ + envArray[i][j].index = n; + break; + } + } + } + } + } +} + +void CMapWin::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + controls->SendToKeyDown(nChar,nRepCnt,nFlags); + + CWnd::OnKeyDown(nChar, nRepCnt, nFlags); +} + +void CMapWin::WriteExits(ostream &out) +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + //pack the exit bytes 2:1 + int compressed[128][256]; + int i,j; + for(j=0; jGetMapHeight(); j++){ + for(i=0; iGetMapWidth(); i+=2){ + int byte1 = this->exitArray[i][j] & 0x0f; + int byte2 = exitArray[i+1][j] & 0x0f; + compressed[i/2][j] = (byte1<<4) | byte2; + } + } + + //int temp = out.tellp(); + //char st[80]; + //ostrstream stout(st,80); + //stout << temp << ends; + //this->MessageBox(st); + + //write out exit info using RLE + int numContinuous = 0; + int continuousByte = compressed[0][0]; + for(j=0; jGetMapHeight(); j++){ + for(i=0; i<(controls->GetMapWidth()>>1); i++){ + if(compressed[i][j] == continuousByte){ + numContinuous++; + }else{ + out.put((char) numContinuous); + out.put((char) continuousByte); + continuousByte = compressed[i][j]; + numContinuous = 1; + } + if(numContinuous == 256){ + out.put((char) 255); + out.put((char) continuousByte); + numContinuous = 1; + } + } + } + + out.put((char) numContinuous); + out.put((char) continuousByte); + //if(numContinuous != 0){ + //out.put((char) 0); + //out.put((char) 0); + //} +} + +void CMapWin::ReadExits(istream &in) +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + + //reads & inflates zones stored using Run Lengh Encoding and compressed 2:1 + int i,j,continuousByte,numContinuous; + + //int temp = in.tellg(); + //char st[80]; + //ostrstream stout(st,80); + //stout << temp << ends; + //this->MessageBox(st); + + numContinuous = in.get() & 0xff; + if(in.eof()) return; + continuousByte = in.get() & 0xff; + + for(j=0; jGetMapHeight(); j++){ + for(i=0; iGetMapWidth(); i+=2){ + if(!numContinuous){ + numContinuous = in.get() & 0xff; + continuousByte = in.get() & 0xff; + } + exitArray[i][j] = (continuousByte>>4) & 0x0f; + exitArray[i+1][j] = continuousByte & 0x0f; + numContinuous--; + } + } + + //in.get(); //junk null terminator + //in.get(); +} + + + + +void CMapWin::FlagTooMuchOpenSpace() +{ + CChildView *view = (CChildView*) this->GetParent(); + CControls *controls = view->GrabControls(); + int width = controls->GetMapWidth(); + int height = controls->GetMapHeight(); + + int max_x = 18; + int max_y = 16; + + int count, start_i, start_j; + int i,j; + + //set all flags to zero + for(j=0; jtooMuchOpenSpace[i][j] = 0; + } + } + + //loop row by row + for(j=0; j=E_FIRSTOBJ){ + start_i = i; + count++; + } + }else{ + //continue finding open space + if(envArray[i][j].index==0 || listOfTilesUsed[envArray[i][j].index]>=E_FIRSTOBJ) count++; + else{ + if(count > max_x){ + while(start_i < i){ + tooMuchOpenSpace[start_i++][j] = 1; + } + } + count = 0; + } + } + } + } + + //loop again column by column + for(i=0; i=E_FIRSTOBJ){ + start_j = j; + count++; + } + }else{ + //continue finding open space + if(envArray[i][j].index==0 || listOfTilesUsed[envArray[i][j].index]>=E_FIRSTOBJ) count++; + else{ + if(count > max_y){ + while(start_j < j){ + tooMuchOpenSpace[i][start_j++] = 1; + } + } + count = 0; + } + } + } + } + +} diff --git a/Tools/LevelEditor/Source/MapWin.h b/Tools/LevelEditor/Source/MapWin.h new file mode 100644 index 0000000..db02490 --- /dev/null +++ b/Tools/LevelEditor/Source/MapWin.h @@ -0,0 +1,127 @@ +#if !defined(AFX_MAPWIN_H__CA2832D2_B4C7_11D3_958B_00A0CC533895__INCLUDED_) +#define AFX_MAPWIN_H__CA2832D2_B4C7_11D3_958B_00A0CC533895__INCLUDED_ + + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MapWin.h : header file +// + +#include "wingk.h" +#include "EditDefines.h" + + +///////////////////////////////////////////////////////////////////////////// +// CMapWin window + +class CMapWin : public CWnd +{ +// Construction +public: + CMapWin(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMapWin) + //}}AFX_VIRTUAL + +// Implementation +public: + void FlagTooMuchOpenSpace(); + void PlaceTile(int tileIndex, CPoint point); + void ReadExits(istream &in); + gkWinShape exitTiles[8]; + void WriteExits(ostream &out); + void RemakeListOfTilesUsed(); + short int * getListOfAllTiles(); + void ReadZones(istream &in); + void WriteZones(ostream &out); + void DrawPath(int destZone, int nPath, gkWinShape &tileBuffer); + void EraseTile(CPoint point); + void PlaceCurrentTile(CPoint point); + void SetScrollBarPositions(); + virtual ~CMapWin(); + + // Application specific public methods // + + void SetGrids(bool); + void setBackgroundColor(int color); + int getBackgroundColor(); + void setGridColor(int color); + void getEnvArray(PicStruct[256][256]); + unsigned char getTotalTilesUsed(); + short int* getListOfTilesUsed(); + void loadLevel(char*); + //sort the tiles in decending order for abe! + void remapMonsters(); + //clear the current level + void clearLevel(); + + // End Application specific pubilc methods // + + + // Generated message map functions +protected: + char tooMuchOpenSpace[256][256]; + PicStruct copyBuffer[256][256]; + int copyWidth, copyHeight; + int drawingRect, rectStartX, rectStartY, rectEndX, rectEndY; + int lmb_isDown, rmb_isDown; + int drawingPath, pathStartX, pathStartY; + int selectedZone; + +////// Application Specific Variables /////////// + bool showGrids; + + //current tile to be blitted + gkWinShape *curTile; + + //2-D array ofenvironment tiles + PicStruct envArray[256][256]; + + //2-D array of zone/attribute tiles + unsigned char zoneArray[256][256]; + unsigned char exitArray[256][256]; + + //background color + int backgroundColor; + int gridColor; + + //total number of tiles uesd + unsigned char totalTilesUsed; + short int listOfTilesUsed[257]; + short int listOfAllTiles[65536]; + +////// end App Specific Variables ///////////// + + + + //{{AFX_MSG(CMapWin) + afx_msg void OnPaint(); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAPWIN_H__CA2832D2_B4C7_11D3_958B_00A0CC533895__INCLUDED_) diff --git a/Tools/LevelEditor/Source/ReadMe.txt b/Tools/LevelEditor/Source/ReadMe.txt new file mode 100644 index 0000000..0743c97 --- /dev/null +++ b/Tools/LevelEditor/Source/ReadMe.txt @@ -0,0 +1,94 @@ +======================================================================== + MICROSOFT FOUNDATION CLASS LIBRARY : LevelEditor +======================================================================== + + +AppWizard has created this LevelEditor application for you. This application +not only demonstrates the basics of using the Microsoft Foundation classes +but is also a starting point for writing your application. + +This file contains a summary of what you will find in each of the files that +make up your LevelEditor application. + +LevelEditor.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +LevelEditor.h + This is the main header file for the application. It includes other + project specific headers (including Resource.h) and declares the + CLevelEditorApp application class. + +LevelEditor.cpp + This is the main application source file that contains the application + class CLevelEditorApp. + +LevelEditor.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +LevelEditor.clw + This file contains information used by ClassWizard to edit existing + classes or add new classes. ClassWizard also uses this file to store + information needed to create and edit message maps and dialog data + maps and to create prototype member functions. + +res\LevelEditor.ico + This is an icon file, which is used as the application's icon. This + icon is included by the main resource file LevelEditor.rc. + +res\LevelEditor.rc2 + This file contains resources that are not edited by Microsoft + Visual C++. You should place all resources not editable by + the resource editor in this file. + + + +///////////////////////////////////////////////////////////////////////////// + +For the main frame window: + +MainFrm.h, MainFrm.cpp + These files contain the frame class CMainFrame, which is derived from + CFrameWnd and controls all SDI frame features. + +res\Toolbar.bmp + This bitmap file is used to create tiled images for the toolbar. + The initial toolbar and status bar are constructed in the CMainFrame + class. Edit this toolbar bitmap using the resource editor, and + update the IDR_MAINFRAME TOOLBAR array in LevelEditor.rc to add + toolbar buttons. +///////////////////////////////////////////////////////////////////////////// + + + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named LevelEditor.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +If your application uses MFC in a shared DLL, and your application is +in a language other than the operating system's current language, you +will need to copy the corresponding localized resources MFC42XXX.DLL +from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, +and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. +For example, MFC42DEU.DLL contains resources translated to German.) If you +don't do this, some of the UI elements of your application will remain in the +language of the operating system. + +///////////////////////////////////////////////////////////////////////////// diff --git a/Tools/LevelEditor/Source/StdAfx.cpp b/Tools/LevelEditor/Source/StdAfx.cpp new file mode 100644 index 0000000..fd027ec --- /dev/null +++ b/Tools/LevelEditor/Source/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// LevelEditor.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/Tools/LevelEditor/Source/StdAfx.h b/Tools/LevelEditor/Source/StdAfx.h new file mode 100644 index 0000000..a97821b --- /dev/null +++ b/Tools/LevelEditor/Source/StdAfx.h @@ -0,0 +1,26 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__CA2832C6_B4C7_11D3_958B_00A0CC533895__INCLUDED_) +#define AFX_STDAFX_H__CA2832C6_B4C7_11D3_958B_00A0CC533895__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__CA2832C6_B4C7_11D3_958B_00A0CC533895__INCLUDED_) diff --git a/Tools/LevelEditor/Source/TerrainTiles.cpp b/Tools/LevelEditor/Source/TerrainTiles.cpp new file mode 100644 index 0000000..dddb0ad --- /dev/null +++ b/Tools/LevelEditor/Source/TerrainTiles.cpp @@ -0,0 +1,237 @@ +// TerrainTiles.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "TerrainTiles.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#include "Controls.h" + +///////////////////////////////////////////////////////////////////////////// +// CTerrainTiles + +CTerrainTiles::CTerrainTiles() +{ +} + +CTerrainTiles::~CTerrainTiles() +{ +} + + +BEGIN_MESSAGE_MAP(CTerrainTiles, CWnd) + //{{AFX_MSG_MAP(CTerrainTiles) + ON_WM_PAINT() + ON_WM_HSCROLL() + ON_WM_VSCROLL() + ON_WM_RBUTTONDOWN() + ON_WM_LBUTTONDOWN() + ON_WM_CREATE() + ON_WM_SIZE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CTerrainTiles message handlers + +void CTerrainTiles::OnPaint() +{ + CPaintDC dc(this); // device context for painting + CControls* papa; + papa = (CControls*)this->GetParent(); + + // TODO: Add your message handler code here + //dc.FillSolidRect(0,0,100,100, 0x000000); + + (papa->GrabTileBuffer())->BlitToDC(&dc,-(this->GetScrollPos(SB_HORZ)), + -(this->GetScrollPos(SB_VERT))); + + int index = papa->GrabCurTileIndex(); + if(index<2047) index--; + int frame_x = ((index % 32) * 16) - this->GetScrollPos(SB_HORZ); + int frame_y = ((index / 32) * 16) - this->GetScrollPos(SB_VERT); + + CRect rect(frame_x, frame_y, frame_x+16, frame_y+16); + + + CBrush whiteBrush; + whiteBrush.Attach((HBRUSH) ::GetStockObject(WHITE_BRUSH)); + dc.FrameRect(rect,&whiteBrush); + whiteBrush.Detach(); + + + // Do not call CWnd::OnPaint() for painting messages +} + +void CTerrainTiles::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + // TODO: Add your message handler code here and/or call default + + int pos = this->GetScrollPos(SB_HORZ); + + switch(nSBCode){ +//SB_LEFT + case SB_LINELEFT: + pos -= 16; + break; + case SB_LINERIGHT: + pos += 16; + break; + case SB_PAGELEFT: + pos -= 256; + break; + case SB_PAGERIGHT: + pos += 256; + break; + case SB_THUMBPOSITION: + ; + case SB_THUMBTRACK: + pos = nPos; + break; + default: + pos = pos; + } + + if(pos<0) pos = 0; + if(pos>(TERRAINSCROLLMAXH - 1)) pos = (TERRAINSCROLLMAXH - 1); + this->SetScrollPos(SB_HORZ, pos); + + this->InvalidateRect(0); +} + +void CTerrainTiles::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + // TODO: Add your message handler code here and/or call default + + int pos = this->GetScrollPos(SB_VERT); + + switch(nSBCode){ + + case SB_LINELEFT: + pos -= 16; + break; + case SB_LINERIGHT: + pos += 16; + break; + case SB_PAGELEFT: + pos -= 64; + break; + case SB_PAGERIGHT: + pos += 64; + break; + case SB_THUMBPOSITION: + ; + case SB_THUMBTRACK: + pos = nPos; + break; + default: + pos = pos; + } + + if(pos<0) pos = 0; + if(pos>(TERRAINSCROLLMAXV - 1)) pos = (TERRAINSCROLLMAXV - 1); + this->SetScrollPos(SB_VERT, pos); + + + CWnd::OnVScroll(nSBCode, nPos, pScrollBar); + this->InvalidateRect(0); +} + +void CTerrainTiles::OnRButtonDown(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default1 + CControls* papa; + int newCurTile; + + if(!::IsWindow(this->m_hWnd)) + return; + + //grab a pointer to the view + papa = (CControls*)this->GetParent(); + + + //set current tile from x position + newCurTile = (point.x + this->GetScrollPos(SB_HORZ)) >> 4; + //figure in y component of index + newCurTile += (32 * ((point.y + this->GetScrollPos(SB_VERT)) >> 4))+1; + if(newCurTile >= 2048) newCurTile--; + + papa->SetCurTilePointer(newCurTile); + papa->InvalidateRect(0); + + this->InvalidateRect(0); + + + CWnd::OnRButtonDown(nFlags, point); +} + +void CTerrainTiles::OnLButtonDown(UINT nFlags, CPoint point) +{ + // TODO: Add your message handler code here and/or call default + this->OnRButtonDown(nFlags, point); + CWnd::OnLButtonDown(nFlags, point); +} + +int CTerrainTiles::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + return 0; +} + +void CTerrainTiles::SetScrollBarPositions() +{ + CRect rect; + this->GetClientRect(&rect); + + int mapWidth = TERRAINSCROLLMAXH; + int mapHeight = TERRAINSCROLLMAXV; + int extraWidth = rect.Width() - mapWidth; + int extraHeight = rect.Height() - mapHeight; + + SCROLLINFO scrollInfo; + scrollInfo.cbSize = sizeof(SCROLLINFO); + + if(extraWidth>=0){ + //don't need the scroll bar + scrollInfo.fMask = SIF_POS | SIF_RANGE; + scrollInfo.nMin = scrollInfo.nMax = scrollInfo.nPos = 0; + this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask); + }else{ + scrollInfo.fMask = SIF_RANGE | SIF_PAGE; + scrollInfo.nMin = 0; + scrollInfo.nMax = mapWidth-1; + scrollInfo.nPos = 0; + scrollInfo.nPage = rect.Width(); + this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask); + + } + + if(extraHeight>=0){ + scrollInfo.fMask = SIF_POS | SIF_RANGE; + scrollInfo.nMin = scrollInfo.nMax = scrollInfo.nPos = 0; + this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask); + }else{ + scrollInfo.fMask = SIF_RANGE | SIF_PAGE; + scrollInfo.nMin = 0; + scrollInfo.nMax = mapHeight-1; + scrollInfo.nPos = 0; + scrollInfo.nPage = rect.Height(); + this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask); + } +} + +void CTerrainTiles::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + SetScrollBarPositions(); +} diff --git a/Tools/LevelEditor/Source/TerrainTiles.h b/Tools/LevelEditor/Source/TerrainTiles.h new file mode 100644 index 0000000..d46d8ea --- /dev/null +++ b/Tools/LevelEditor/Source/TerrainTiles.h @@ -0,0 +1,58 @@ +#if !defined(AFX_TERRAINTILES_H__5105A4C0_BC7B_11D3_958B_00A0CC533895__INCLUDED_) +#define AFX_TERRAINTILES_H__5105A4C0_BC7B_11D3_958B_00A0CC533895__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TerrainTiles.h : header file +// + + +#include "EditDefines.h" + + +///////////////////////////////////////////////////////////////////////////// +// CTerrainTiles window + +class CTerrainTiles : public CWnd +{ +// Construction +public: + CTerrainTiles(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTerrainTiles) + //}}AFX_VIRTUAL + +// Implementation +public: + void SetScrollBarPositions(); + virtual ~CTerrainTiles(); + + // Generated message map functions +protected: + //{{AFX_MSG(CTerrainTiles) + afx_msg void OnPaint(); + afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSize(UINT nType, int cx, int cy); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TERRAINTILES_H__5105A4C0_BC7B_11D3_958B_00A0CC533895__INCLUDED_) diff --git a/Tools/LevelEditor/Source/TileLimitDialog.cpp b/Tools/LevelEditor/Source/TileLimitDialog.cpp new file mode 100644 index 0000000..2e90a4d --- /dev/null +++ b/Tools/LevelEditor/Source/TileLimitDialog.cpp @@ -0,0 +1,43 @@ +// TileLimitDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "TileLimitDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CTileLimitDialog dialog + + +CTileLimitDialog::CTileLimitDialog(CWnd* pParent /*=NULL*/) + : CDialog(CTileLimitDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTileLimitDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CTileLimitDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTileLimitDialog) + DDX_Control(pDX, IDC_LIMIT_TEXTBOX, m_selection); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTileLimitDialog, CDialog) + //{{AFX_MSG_MAP(CTileLimitDialog) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTileLimitDialog message handlers diff --git a/Tools/LevelEditor/Source/TileLimitDialog.h b/Tools/LevelEditor/Source/TileLimitDialog.h new file mode 100644 index 0000000..f017be3 --- /dev/null +++ b/Tools/LevelEditor/Source/TileLimitDialog.h @@ -0,0 +1,46 @@ +#if !defined(AFX_TILELIMITDIALOG_H__A65950A1_6466_11D4_B6CE_525400E2D57B__INCLUDED_) +#define AFX_TILELIMITDIALOG_H__A65950A1_6466_11D4_B6CE_525400E2D57B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TileLimitDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CTileLimitDialog dialog + +class CTileLimitDialog : public CDialog +{ +// Construction +public: + CTileLimitDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CTileLimitDialog) + enum { IDD = IDD_TILELIMIT }; + CButton m_selection; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTileLimitDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTileLimitDialog) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TILELIMITDIALOG_H__A65950A1_6466_11D4_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/LevelEditor/Source/WayPointList.cpp b/Tools/LevelEditor/Source/WayPointList.cpp new file mode 100644 index 0000000..bbb2266 --- /dev/null +++ b/Tools/LevelEditor/Source/WayPointList.cpp @@ -0,0 +1,305 @@ +#include "WayPointList.h" + +WayPointList::WayPointList(){ + Reset(); + pitch = 32; +} + +WayPointList::~WayPointList(){ +} + +void WayPointList::Reset(){ + int i,j; + for(i=1; i<16; i++){ + for(j=1; j<16; j++){ + zoneMatrix[i][j] = 0; + } + } + + for(i=0; i<256; i++){ + for(j=0; j<32; j++){ + path[i][j] = 0; + } + } + + numWayPoints = 0; + numPaths = 0; + curPathStartZone = 0; +} + +void WayPointList::CreateWayPoint(int i, int j){ + if(numWayPoints==255) return; + + //don't create if it's a duplicate of existing + int wp = (j<<8) + i; + + int index; + for(index=1; index<=numWayPoints; index++){ + if(wayPoints[index]==wp) return; + } + + wayPoints[++numWayPoints] = wp; +} + +void WayPointList::RemoveWayPoint(int i, int j){ + int wp = (j<<8) + i; + + //find the index of the existing waypoint + int index; + for(index=1; index<=numWayPoints; index++){ + if(wayPoints[index] == wp) break; + } + if(index>numWayPoints) return; //wasn't there + + //delete all paths that included the deleted waypoint + int n,m; + for(n=1; n<=numPaths; n++){ + if(path[n][0]>0){ + for(m=0; m<32; m++){ + if(path[n][m]==index){ + RemovePath(n); + n--; + break; + } + } + } + } + + //delete the waypoint itself by switching it with the end waypoint + int replaceWith = numWayPoints--; + if(numWayPoints>0){ + wayPoints[index] = wayPoints[replaceWith]; + + //change all paths that use the replacer to use its new index + for(n=1; nnumWayPoints) return; + + //add waypoint index to path + int n; + for(n=0; n<32; n++){ + if(path[curPath][n] == 0){ + path[curPath][n] = index; + break; + } + } + */ +} + +void WayPointList::AddWayPointToPath(int waypoint){ + int wp = waypoint; + int index; + for(index=1; index<=numWayPoints; index++){ + if(wayPoints[index] == wp) break; + } + if(index>numWayPoints) return; + + //add waypoint index to path + int n; + for(n=0; n<32; n++){ + if(path[curPath][n] == 0){ + path[curPath][n] = index; + break; + } + } +} + +int WayPointList::EndPath(int endZone){ + //remove the old path + int oldPath = zoneMatrix[curPathStartZone][endZone]; + if(oldPath){ + int shifted = RemovePath(zoneMatrix[curPathStartZone][endZone]); + if(shifted==curPath){ + zoneMatrix[curPathStartZone][endZone] = oldPath; + }else{ + zoneMatrix[curPathStartZone][endZone] = curPath; + } + }else{ + zoneMatrix[curPathStartZone][endZone] = curPath; + } + return zoneMatrix[curPathStartZone][endZone]; +} + +int WayPointList::GetPathLength(int nPath){ + int length=0; + int i; + for(i=0; i<32; i++){ + if(path[nPath][i]==0) break; + length++; + } + return length; +} + +int WayPointList::GetPath(int startZone, int endZone){ + return zoneMatrix[startZone][endZone]; +} + +int WayPointList::GetFirstWayPoint(int npath){ + curReturnedWayPoint = 0; + return path[npath][0]; +} + +int WayPointList::WayPointExists(int i, int j){ + int wp = (j<<8) + i; + + int index; + for(index=0; index<=numWayPoints; index++){ + if(wayPoints[index]==wp) return 1; + } + return 0; +} + +int WayPointList::GetNextWayPoint(int npath){ + curReturnedWayPoint++; + if(curReturnedWayPoint==32) return 0; + return path[npath][curReturnedWayPoint]; +} + +void WayPointList::Write(ostream &out){ + out.put((char) numWayPoints); + if(!numWayPoints) return; + out.put((char) 0); + + //write waypoints (up to 255) + int i,j; + for(i=1; i<=numWayPoints; i++){ + int wp = wayPoints[i]; + int w_i = wp & 0xff; + int w_j = (wp >> 8) & 0xff; + wp = (0xd000 + w_j*pitch + w_i); + out.put((char) (wp & 0xff)); + out.put((char) ((wp>>8) & 0xff)); + } + + //write paths (up to 255 paths, 4 bytes each) + out.put((char) numPaths); + for(i=1; i<=numPaths; i++){ + for(j=0; j<4; j++){ + out.put((char) path[i][j]); + } + } + + //write zone matrix containing paths 16 x 16 = 256 bytes + for(j=0; j<16; j++){ + for(i=0; i<16; i++){ + out.put((char) zoneMatrix[i][j]); + } + } +} + +void WayPointList::Read(istream &in){ + Reset(); + + int pos = in.tellg(); + + numWayPoints = in.get(); //get num waypoints + numWayPoints &= 0xff; + + if(in.eof() || !numWayPoints){ + numWayPoints = 0; + return; + } + + in.get(); //discard pad + + //read waypoints + int i,j; + for(i=1; i<=numWayPoints; i++){ + int wp = in.get() & 0xff; + wp |= in.get() << 8; + wp &= 0xffff; + wp -= 0xd000; + int w_j = wp / pitch; + int w_i = wp % pitch; + wayPoints[i] = (w_j<<8) | w_i; + } + + //read paths + numPaths = in.get() & 0xff; + for(i=1; i<=numPaths; i++){ + for(j=0; j<4; j++){ + path[i][j] = in.get() & 0xff; + } + } + + //read zone matrix + for(j=0; j<16; j++){ + for(i=0; i<16; i++){ + zoneMatrix[i][j] = in.get() & 0xff; + } + } +} + + +//global declaration +WayPointList g_wayPointList; + diff --git a/Tools/LevelEditor/Source/WayPointList.h b/Tools/LevelEditor/Source/WayPointList.h new file mode 100644 index 0000000..531a298 --- /dev/null +++ b/Tools/LevelEditor/Source/WayPointList.h @@ -0,0 +1,62 @@ +#ifndef WAYPOINTLIST_H +#define WAYPOINTLIST_H + +#include + +class WayPointList{ + protected: + //Lookup zoneMatrix[i][j] to find out the index of the path list + //to go to to get from zone i to zone j. Upon saving each path list + //will be a linked list that may merge with another waypoint list. + //But in the editor it's just a list of waypoints up to 32 long. + int zoneMatrix[16][16]; + + //The contents of path[i] is a list of 32 indices to waypoints + //that a unit must travel. + int path[256][32]; + + //Each waypoint is a ((j<<8)+i) coordinate that will be + //$c000 + (j*pitch) + i upon saving + int wayPoints[256]; + + //up to 255 + int numWayPoints; + int numPaths; + int curPath; + int curPathStartZone; + int curReturnedWayPoint; + int pitch; + + public: + WayPointList(); + ~WayPointList(); + void Reset(); + void CreateWayPoint(int i, int j); + void RemoveWayPoint(int i, int j); + void MoveWayPoint(int si, int sj, int di, int dj); + int RemovePath(int n); + int BeginPath(int zone); + void AddWayPointToPath(int i, int j); + void AddWayPointToPath(int waypoint); + int EndPath(int endZone); + + int GetPathLength(int nPath); + int GetPath(int startZone, int endZone); + int WayPointExists(int i, int j); + int GetFirstWayPoint(int npath); + int GetNextWayPoint(int npath); + + inline void SetPitch(int p){ pitch = p; } + inline int GetPitch(){ return pitch; } + inline int GetNumPaths(){ return numPaths; } + inline int GetNumWayPoints(){ return numWayPoints; } + inline int GetWayPoint(int n){ return wayPoints[n]; } + + void Write(ostream &out); + void Read(istream &in); +}; + +extern WayPointList g_wayPointList; + +#endif + diff --git a/Tools/LevelEditor/Source/ZoneList.cpp b/Tools/LevelEditor/Source/ZoneList.cpp new file mode 100644 index 0000000..718b416 --- /dev/null +++ b/Tools/LevelEditor/Source/ZoneList.cpp @@ -0,0 +1,132 @@ +// ZoneList.cpp : implementation file +// + +#include "stdafx.h" +#include "LevelEditor.h" +#include "ZoneList.h" +#include "wingk.h" +#include "Controls.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CZoneList + +CZoneList::CZoneList() +{ + gkWinShape buffer; + buffer.LoadBMP("exitTiles.bmp"); + + int i; + for(i=0; i<7; i++) exitTiles[i+1].GetShape(&buffer, i*16, 0, 16, 16); +} + +CZoneList::~CZoneList() +{ +} + + +BEGIN_MESSAGE_MAP(CZoneList, CListBox) + //{{AFX_MSG_MAP(CZoneList) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CZoneList message handlers + +void CZoneList::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + CControls *controls = (CControls*) this->GetParent(); + + CDC dc; + dc.Attach(lpDrawItemStruct->hDC); + + if(controls->GetDrawingExits()==-1){ + int color = this->GetZoneColor(lpDrawItemStruct->itemData); + + dc.FillSolidRect(&(lpDrawItemStruct->rcItem), + color); + + CBrush brush; + + CRect rect = lpDrawItemStruct->rcItem; + rect.DeflateRect(1,1); + + //Draw outline around selected + if(lpDrawItemStruct->itemState & ODS_SELECTED){ + + + if(color!=0){ + brush.Attach(GetStockObject(BLACK_BRUSH)); + dc.FrameRect(&rect,&brush); + }else{ + brush.Attach(GetStockObject(WHITE_BRUSH)); + dc.FrameRect(&rect,&brush); + } + + brush.Detach(); + + } + + //draw the orange dot that means waypoint + if(color==0){ + rect.DeflateRect(4,4); + //brush.CreateSolidBrush(0x0080ff); //orange brush + dc.FillSolidRect(&rect,0x0080ff); + } + }else{ + //drawing exits + int index = controls->MapIndexToExit(lpDrawItemStruct->itemID); + CRect rect = lpDrawItemStruct->rcItem; + exitTiles[index].BlitToDC(&dc,rect.left, rect.top); + + rect.DeflateRect(1,1); + + //Draw outline around selected + CBrush brush; + if(lpDrawItemStruct->itemState & ODS_SELECTED){ + brush.Attach(GetStockObject(WHITE_BRUSH)); + dc.FrameRect(&rect,&brush); + brush.Detach(); + } + } + + dc.Detach(); +} + +int CZoneList::GetZoneColor(int n) +{ + int color=0; + switch(n){ + case 0: break; + case 1: color = 0xffffff; break; //white + case 2: color = 0x8888ff; break; //pink + case 3: color = 0x0000ff; break; //red + case 4: color = 0x0088ff; break; //orange + case 5: color = 0x00ffff; break; //yellow + case 6: color = 0x004488; break; //brown + case 7: color = 0x88ff88; break; //bright green + case 8: color = 0x00ff00; break; //green + case 9: color = 0x008800; break; //dark green + case 10: color = 0xffff00; break; //cyan + case 11: color = 0xff8888; break; //light blue + case 12: color = 0xff0000; break; //royal blue + case 13: color = 0x880000; break; //dark blue + case 14: color = 0xff88ff; break; //light purple + case 15: color = 0xff00ff; break; //purple + } + return color; +} + +void CZoneList::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) +{ + //tell windows the dimensions of each member of our selection box + lpMeasureItemStruct->itemWidth = 16; + lpMeasureItemStruct->itemHeight = 16; + +} diff --git a/Tools/LevelEditor/Source/ZoneList.h b/Tools/LevelEditor/Source/ZoneList.h new file mode 100644 index 0000000..af7b832 --- /dev/null +++ b/Tools/LevelEditor/Source/ZoneList.h @@ -0,0 +1,56 @@ +#if !defined(AFX_ZONELIST_H__FF8F62A8_C532_11D3_B6CE_525400E2D57B__INCLUDED_) +#define AFX_ZONELIST_H__FF8F62A8_C532_11D3_B6CE_525400E2D57B__INCLUDED_ + +#include "wingk.h" // Added by ClassView +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ZoneList.h : header file +// + +#include "wingk.h" + +///////////////////////////////////////////////////////////////////////////// +// CZoneList window + +class CZoneList : public CListBox +{ +// Construction +public: + CZoneList(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CZoneList) + public: + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); + //}}AFX_VIRTUAL + +// Implementation +public: + static int GetZoneColor(int n); + virtual ~CZoneList(); + + // Generated message map functions +protected: + gkWinShape exitTiles[8]; + //{{AFX_MSG(CZoneList) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ZONELIST_H__FF8F62A8_C532_11D3_B6CE_525400E2D57B__INCLUDED_) diff --git a/Tools/LevelEditor/Source/res/LevelEditor.ico b/Tools/LevelEditor/Source/res/LevelEditor.ico new file mode 100644 index 0000000..1776962 Binary files /dev/null and b/Tools/LevelEditor/Source/res/LevelEditor.ico differ diff --git a/Tools/LevelEditor/Source/res/LevelEditor.rc2 b/Tools/LevelEditor/Source/res/LevelEditor.rc2 new file mode 100644 index 0000000..b9fcc00 --- /dev/null +++ b/Tools/LevelEditor/Source/res/LevelEditor.rc2 @@ -0,0 +1,13 @@ +// +// LEVELEDITOR.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Tools/LevelEditor/Source/res/Toolbar.bmp b/Tools/LevelEditor/Source/res/Toolbar.bmp new file mode 100644 index 0000000..627d86b Binary files /dev/null and b/Tools/LevelEditor/Source/res/Toolbar.bmp differ diff --git a/Tools/LevelEditor/Source/resource.h b/Tools/LevelEditor/Source/resource.h new file mode 100644 index 0000000..a6a29ed --- /dev/null +++ b/Tools/LevelEditor/Source/resource.h @@ -0,0 +1,83 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by LevelEditor.rc +// +#define IDD_ABOUTBOX 100 +#define IDR_MAINFRAME 128 +#define IDR_LEVELETYPE 129 +#define IDD_CONTROLS 130 +#define IDD_CLASS_LIST_DIALOG 132 +#define IDD_COLORPICKER 133 +#define IDD_LINKEXITS 134 +#define IDD_TILELIMIT 135 +#define IDC_SHOWGRIDS 1003 +#define IDC_CURTILE 1004 +#define IDC_WRITEFILE 1005 +#define IDC_SAVELEVEL 1006 +#define IDC_LOADME 1007 +#define IDC_LOAD 1008 +#define IDC_CLEAR 1011 +#define IDC_EDIT_WIDTH 1012 +#define IDC_EDIT_HEIGHT 1013 +#define IDC_ZONELIST 1018 +#define IDC_CLASS_LIST 1020 +#define IDC_BUTTON_CLASSLIST 1021 +#define IDC_BUTTON_LINKEXITS 1022 +#define IDC_LOAD_FILENAME 1023 +#define IDC_RADIO_TILES 1024 +#define IDC_RADIO_ZONES 1025 +#define IDC_COLOR 1025 +#define IDC_RADIO_EXITS 1026 +#define IDC_RED 1027 +#define IDC_GREEN 1028 +#define IDC_BGCOLOR 1028 +#define IDC_BLUE 1029 +#define IDC_META_WIDTH 1029 +#define IDC_META_HEIGHT 1030 +#define IDC_SETMETA_1X1 1031 +#define IDC_SETMETA_2X2 1032 +#define IDC_SETMETA_3x3 1033 +#define IDC_SHIFTUP 1034 +#define IDC_SHIFTRIGHT 1035 +#define IDC_NORTHEXIT 1035 +#define IDC_SHIFTDOWN 1036 +#define IDC_EASTEXIT 1036 +#define IDC_SHIFTLEFT 1037 +#define IDC_SOUTHEXIT 1037 +#define IDC_COPYUP 1038 +#define IDC_WESTEXIT 1038 +#define IDC_COPYRIGHT 1039 +#define IDC_UPEXIT 1039 +#define IDC_COPYDOWN 1040 +#define IDC_DOWNEXIT 1040 +#define IDC_COPYLEFT 1041 +#define IDC_EXITEXIT 1041 +#define IDC_WALLCHECK 1042 +#define IDC_SETMETA_4x4 1043 +#define IDC_CLASSLIST_CLEARALL 1043 +#define IDC_LIMIT_TEXTBOX 1044 +#define IDC_LIMIT_FONT 1045 +#define IDC_SORTCLASSESBY 1045 +#define IDC_LIMIT_NONE 1046 +#define MENU_RED 32771 +#define MENU_BLACK 32772 +#define MENU_BLUE 32773 +#define MENU_YELLOW 32774 +#define MENU_WHITE 32775 +#define MENU_GRAY 32776 +#define GRID_RED 32777 +#define GRID_BLACK 32778 +#define GRID_WHITE 32779 +#define MENU_GREEN 32780 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 136 +#define _APS_NEXT_COMMAND_VALUE 32781 +#define _APS_NEXT_CONTROL_VALUE 1046 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Tools/LevelEditor/Source/waypoint.txt b/Tools/LevelEditor/Source/waypoint.txt new file mode 100644 index 0000000..a240905 --- /dev/null +++ b/Tools/LevelEditor/Source/waypoint.txt @@ -0,0 +1,20 @@ +Manipulating Paths and Waypoints: + +Click on "Show Zones" + + +Waypoints: + Set: Click on orange button, left-click on map to place new waypoint. + Delete: Right-click on existing waypoint. + +Path: + Place waypoint in current zone, adjacent zone, and destination zone. + With waypoint button selected, right-click on the "from" zone (but + not on a waypoint), left-click on "from" zone's waypoint, adjacent + zone's waypoint, destination zone's waypoint, and finally destination + zone (not on waypoint). + +To show paths leaving a specific zone: + Select zone color but not waypoint button. Right click on an existing + zone. + diff --git a/Tools/LevelEditor/Source/wingk.cpp b/Tools/LevelEditor/Source/wingk.cpp new file mode 100644 index 0000000..a22f875 --- /dev/null +++ b/Tools/LevelEditor/Source/wingk.cpp @@ -0,0 +1,1820 @@ +#include "wingk.h" +#include + +#include + + +gkTransparencyTable gkWinShape::tranTable; + +struct BMP_header{ + gkLONG fSize; //54 byte header + 4*numColors (1-8bit) + (w*h*bpp)/8 + gkWORD zero1, zero2; //0,0 + gkLONG offsetBytes; //should be header (54) plus Palette Size + + gkLONG headerSize; //size of remaining header (40) + gkLONG width, height; //w,h in pixels + gkWORD planes, bpp; //plane=1, bpp=1,2,4, or most commonly 8 + gkLONG compression, imageSize; //compression to zero, size is w*h(8bit) + gkLONG xpels, ypels, zero3, zero4; //set to 0,0,0,0 +}; + +int gkIO::ReadWord(istream &in){ + int retval = in.get() << 8; + return retval | (in.get() & 0xff); +} + +int gkIO::ReadLong(istream &in){ + int retval = ReadWord(in) << 16; + return retval | (ReadWord(in) & 0xffff); +} + +char *gkIO::ReadString(istream &in){ + static char st[80]; + int len = ReadWord(in); + if(!len) return 0; + in.read(st,len); + st[len] = 0; + return st; +} + +char *gkIO::ReadNewString(istream &in){ + int len = ReadWord(in); + if(!len) return 0; + + char *st = new char[len+1]; + in.read(st,len); + st[len] = 0; + return st; +} + +void gkIO::WriteLong(ostream &out, int n){ + WriteWord(out, n>>16); + WriteWord(out, n); +} + +void gkIO::WriteWord(ostream &out, int n){ + out << (char) ((n>>8)&0xff); + out << (char) (n&0xff); +} + +void gkIO::WriteString(ostream &out, char *st){ + WriteWord(out,strlen(st)); + out.write(st,strlen(st)); +} + + +int gkRGB::operator==(gkRGB &c2){ + return ((color.argb & 0xffffff) == (c2.color.argb & 0xffffff)); +} + +int gkRGB::Equals(int _r, int _g, int _b){ + return _r==color.bytes.r && _g==color.bytes.g && _b==color.bytes.b; +} + +int gkRGB::GetCategory(){ + int r = GetR() >> 6; //rough categories 0-3 + int g = GetG() >> 6; + int b = GetB() >> 6; + + int highest = r; + if(g > highest) highest = g; + if(b > highest) highest = b; + + int hash; + + if(r > g && r > b){ //red high + if(g < b) hash = 0; // r > (g < b) + else if(g==b) hash = 1; // r > (g = b) + else hash = 2; // r > (g > b) + }else if(g > r && g > b){ //green high + if(r < b) hash = 3; // g > (r < b) + else if(r==b) hash = 4; // g > (r = b) + else hash = 5; // g > (r > b) + }else if(b > r && b > g){ //blue high + if(r < g) hash = 6; // b > (r < g) + else if(r==g) hash = 7; // b > (r = g) + else hash = 8; // b > (r > g) + }else if(r==b && b==g){ //r = g = b + hash = 9; + }else if(r==b){ //(r = b) > g + hash = 10; + }else if(r==g){ //(r = g) > b + hash = 11; + }else{ //(g = b) > r + hash = 12; + } + + //make room in each category for four levels of intensity (0-3) + hash = hash*4 + highest; + + return hash; +} + +void gkRGB::Combine(gkRGB c2, int alpha){ + //mix alpha + color.bytes.r += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetR()-GetR(), alpha); + color.bytes.g += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetG()-GetG(), alpha); + color.bytes.b += + gkWinShape::tranTable.LookupTransparencyOffset(c2.GetB()-GetB(), alpha); +} + +gkPalGenItem::gkPalGenItem(gkRGB _color){ + color = _color; + occurrences = 1; + nextItem = 0; +} + +gkPalGenItem::gkPalGenItem(gkPalGenItem *item){ + color = item->color; + occurrences = item->occurrences; + nextItem = 0; +} + +gkPalGenItem::~gkPalGenItem(){ +} + +gkRGB gkPalGenItem::GetColor(){ + return color; +} + +void gkPalGenItem::AddOccurrence(){ + occurrences++; +} + +int gkPalGenItem::GetOccurrences(){ + return occurrences; +} + +void gkPalGenItem::SetOccurrences(int n){ + occurrences = n; +} + +void gkPalGenItem::SetNextItem(gkPalGenItem *item){ + nextItem = item; +} + +gkPalGenItem *gkPalGenItem::GetNextItem(){ + return nextItem; +} + +int gkPalGenItem::SortCallback(const void *e1, const void *e2){ + gkPalGenItem *i1 = *((gkPalGenItem**) e1); + gkPalGenItem *i2 = *((gkPalGenItem**) e2); + if(i1->occurrences > i2->occurrences) return -1; + if(i1->occurrences == i2->occurrences) return 0; + return 1; +} + +gkColorCategory::gkColorCategory(){ + int i; + for(i=0; i<64; i++) hashHead[i] = hashTail[i] = 0; + curHash = 0; + curItem = 0; + uniqueCount = 0; +} + +gkColorCategory::~gkColorCategory(){ + int i; + for(i=0; i<64; i++){ + gkPalGenItem *cur, *next; + for(cur=hashHead[i]; cur; cur=next){ + next = cur->GetNextItem(); + delete cur; + } + hashHead[i] = hashTail[i] = 0; + } + uniqueCount = 0; +} + +gkPalGenItem *gkColorCategory::GetFirstItem(){ + if(!uniqueCount) return 0; + curHash = -1; + curItem = 0; + return GetNextItem(); +} + +gkPalGenItem *gkColorCategory::GetNextItem(){ + if(curHash>=64) return 0; + + if(!curItem || !curItem->GetNextItem()){ + while(curHash<(64-1)){ + curHash++; + if(hashHead[curHash]){ + curItem = hashHead[curHash]; + return curItem; + } + } + return 0; + } + + curItem = curItem->GetNextItem(); + return curItem; +} + +gkPalGenItem *gkColorCategory::Exists(gkRGB color){ + int hash = GetHash(color); + gkPalGenItem *cur; + for(cur=hashHead[hash]; cur; cur=cur->GetNextItem()){ + if(cur->GetColor() == color) return cur; + } + return 0; +} + +void gkColorCategory::AddColor(gkRGB color){ + int hash = GetHash(color); + gkPalGenItem *item = new gkPalGenItem(color); + uniqueCount++; + if(!hashHead[hash]){ + hashHead[hash] = hashTail[hash] = item; + }else{ + gkPalGenItem *prev = hashTail[hash]; + //gkPalGenItem *cur, *prev; + //for(cur=hashHead[hash]; cur; cur=cur->GetNextItem()){ + //prev = cur; + //} + prev->SetNextItem(item); + hashTail[hash] = item; + } +} + +void gkColorCategory::SetZeroOccurrences(gkRGB color){ + int hash = GetHash(color); + gkPalGenItem *cur; + for(cur=hashHead[hash]; cur; cur=cur->GetNextItem()){ + if(cur->GetColor()==color){ + cur->SetOccurrences(0); + uniqueCount--; + break; + } + } +} + +int gkColorCategory::GetHash(gkRGB color){ + //hash is concatenation of lower 2 bits of r, g, and b so that minute color + //differences will elicit a different hash + int hash = ((color.GetR() & 3) << 4) | ((color.GetG() & 3) << 2) + | (color.GetB() & 3); + return hash; +} + +gkRGB gkColorCategory::GetMostFrequent(){ + gkPalGenItem *cur = GetMostFrequentItem(); + if(!cur) return gkRGB(0,0,0); + return cur->GetColor(); +} + +gkPalGenItem *gkColorCategory::GetMostFrequentItem(){ + gkPalGenItem *cur, *highest=0; + int highestCount=0; + for(cur=GetFirstItem(); cur; cur=GetNextItem()){ + if(cur->GetOccurrences() > highestCount){ + highest = cur; + highestCount = cur->GetOccurrences(); + } + } + return highest; +} + +gkPaletteGenerator::gkPaletteGenerator(){ +} + +gkPaletteGenerator::~gkPaletteGenerator(){ + Reset(); +} + +void gkPaletteGenerator::Reset(){ +} + +void gkPaletteGenerator::AddColor(gkRGB color){ + int i = GetHash(color); + gkPalGenItem *cur; + if(cur = colorCube[i].Exists(color)){ + cur->AddOccurrence(); + }else{ + //color not in list + colorCube[i].AddColor(color); + } +} + +int gkPaletteGenerator::CreatePalette(gkRGB *palette, int numEntries){ + if(numEntries<=0) return 0; + + //Set all entries to black + int i; + for(i=0; i0){ + first--; + count += colorCube[first].GetUniqueCount(); + } + if(last<(512-1)){ + last++; + count += colorCube[last].GetUniqueCount(); + } + } + + //Create an array to hold all the colors for sorting purposes + gkPalGenItem **colors = new gkPalGenItem*[count]; + gkPalGenItem *cur; + i = 0; + int j; + for(j=first; j<=last; j++){ + for(cur=colorCube[j].GetFirstItem(); cur; + cur=colorCube[j].GetNextItem()){ + if(cur->GetOccurrences()){ + colors[i++] = cur; + } + } + } + count = i; //i may be different from "count" since occurrences is set + //to zero after a color is selected + + //figure out how many colors will come from this section of the cube + int numToGrab = 1; + int tempCurEntry = curEntry; + while(nextEntry==first && tempCurEntry<(512-1)){ + tempCurEntry++; + nextEntry = (int) (scaleFactor * (tempCurEntry+1)); + numToGrab++; + } + + //sort colors into descending order and pick "num" most frequent + qsort(colors, count, sizeof(gkPalGenItem*), gkPalGenItem::SortCallback); + + for(i=0; iGetColor(); + curEntry++; + colorCube[GetHash(colors[i]->GetColor())].SetZeroOccurrences( + colors[i]->GetColor()); + } + + //delete sorting table + delete colors; + } + return numEntries; +} + +int gkPaletteGenerator::GetHash(gkRGB color){ + int r = color.GetR() >> 5; //rough categories 0-3 + int g = color.GetG() >> 5; + int b = color.GetB() >> 5; + return (r<<6) | (g<<3) | b; + + /* + int highest = r; + if(g > highest) highest = g; + if(b > highest) highest = b; + + int hash; + + // r > (g < b) + // r > (g = b) + // r > (g > b) + // g > (r < b) + // g > (r = b) + // g > (r > b) + // b > (r < g) + // b > (r = g) + // b > (r > g) + // (r = b) > g + // (r = g) > b + // (g = b) > r + // (r = g) = b + if(r > g && r > b){ //red high + if(g < b) hash = 0; // r > (g < b) + else if(g==b) hash = 1; // r > (g = b) + else hash = 2; // r > (g > b) + }else if(g > r && g > b){ //green high + if(r < b) hash = 3; // g > (r < b) + else if(r==b) hash = 4; // g > (r = b) + else hash = 5; // g > (r > b) + }else if(b > r && b > g){ //blue high + if(r < g) hash = 6; // b > (r < g) + else if(r==g) hash = 7; // b > (r = g) + else hash = 8; // b > (r > g) + }else if(r==b && b==g){ //r = g = b + hash = 9; + }else if(r==b){ //(r = b) > g + hash = 10; + }else if(r==g){ //(r = g) > b + hash = 11; + }else{ //(g = b) > r + hash = 12; + } + + //make room in each category for four levels of intensity (0-3) + hash = hash*4 + highest; + + return hash; + */ +} + +gkRGB gkPaletteGenerator::MatchColor(gkRGB color){ + int hash = GetHash(color); + int r = color.GetR(); + int g = color.GetG(); + int b = color.GetB(); + if(colorCube[hash].GetFirstItem()){ //near colors; search just this section + gkPalGenItem *cur, *bestMatch; + int bestDiff; + bestMatch = colorCube[hash].GetFirstItem(); + int r2, g2, b2; + r2 = abs(r - bestMatch->GetColor().GetR()); + g2 = abs(g - bestMatch->GetColor().GetG()); + b2 = abs(b - bestMatch->GetColor().GetB()); + bestDiff = r2*r2 + g2*g2 + b2*b2; + for(cur=colorCube[hash].GetNextItem(); cur; cur=colorCube[hash].GetNextItem()){ + r2 = abs(r - cur->GetColor().GetR()); + g2 = abs(g - cur->GetColor().GetG()); + b2 = abs(b - cur->GetColor().GetB()); + int curDiff = r2*r2 + g2*g2 + b2*b2; + if(curDiff < bestDiff){ + bestDiff = curDiff; + bestMatch = cur; + if(!curDiff) return bestMatch->GetColor(); + } + } + return bestMatch->GetColor(); + }else{ + //no colors nearby; expand search + //Get it from ~greyscale if possible + int first, last; + //first = last = 36 + (hash % 4); + //if(!colorCube[first].GetFirstItem()){ + first = 0; //nothing there either; search everything + last = (512-1); + /* + first = 36; + last = 39; + //first = hash - (hash%4); //different intensities, same color + //last = first + 3; + if(!colorCube[first] && !colorCube[first+1] && !colorCube[first+2] + && !colorCube[last]){ + first = 0; //nothing there either; search everything + last = 51; + } + */ + //} + gkPalGenItem *cur, *bestMatch; + int bestDiff = 0x7fffffff; + bestMatch = 0; + int i; + for(i=first; i<=last; i++){ + for(cur=colorCube[i].GetFirstItem(); cur; + cur=colorCube[i].GetNextItem()){ + int r2 = abs(r - cur->GetColor().GetR()); + int g2 = abs(g - cur->GetColor().GetG()); + int b2 = abs(b - cur->GetColor().GetB()); + int curDiff = r2*r2 + g2*g2 + b2*b2; + if(curDiff < bestDiff){ + bestDiff = curDiff; + bestMatch = cur; + if(!curDiff) return bestMatch->GetColor(); + } + } + } + if(!bestMatch) return gkRGB(0,0,0); + return bestMatch->GetColor(); + } +} + +gkRGB gkPaletteGenerator::GetMostFrequent(){ + int i, highestCount=0; + gkRGB highestColor; + for(i=0; i<512; i++){ + gkPalGenItem *cur; + for(cur=colorCube[i].GetFirstItem(); cur; cur=colorCube[i].GetNextItem()){ + int count = cur->GetOccurrences(); + if(count > highestCount){ + highestCount = count; + highestColor = cur->GetColor(); + } + } + } + return highestColor; +} + +int gkPaletteGenerator::NumUniqueColors(){ + int totalUnique = 0; + int i; + for(i=0; i<512; i++){ + totalUnique += colorCube[i].GetUniqueCount(); + } + return totalUnique; +} + +gkColorCategory *gkPaletteGenerator::GetCategory(int hash){ + return &colorCube[hash]; +} + +gkTransparencyTable::gkTransparencyTable(){ + lookup = new gkBYTE[256*256]; + + int baseOffset, alpha, i; + i = 0; + for(baseOffset=0; baseOffset<256; baseOffset++){ + for(alpha=0; alpha<256; alpha++){ + lookup[i++] = (baseOffset * alpha) / 255; + } + } +} + +gkTransparencyTable::~gkTransparencyTable(){ + if(lookup) delete lookup; + lookup = 0; +} + +int gkTransparencyTable::LookupTransparencyOffset(int baseOffset, int alpha){ + return (baseOffset>=0) ? lookup[(baseOffset<<8)+alpha] + : (-lookup[((-baseOffset)<<8)+alpha]); +} + + +gkWinShape::gkWinShape(){ + data = 0; + width = height = bpp = 0; + x_origin = y_origin = x_handle = y_handle = 0; +} + +gkWinShape::~gkWinShape(){ + FreeData(); +} + +void gkWinShape::FreeData(){ + if(data){ + delete data; + data = 0; + } +} + +void gkWinShape::Create(int _width, int _height){ + if(_width <= 0 || _height <= 0) return; + + FreeData(); + width = _width; + height = _height; + + //round up width to ensure multiple of 4 pixels + width = (width + 3) & (~3); + + data = new gkBYTE[(width*height)<<2]; + bpp = 32; +} + +void gkWinShape::Cls(){ + if(!this->data) return; + memset(this->data, 0, (this->width * this->height)<<2); +} + +void gkWinShape::Cls(gkRGB color){ + if(!this->data) return; + + gkLONG *dest = (gkLONG*) this->data; + int i = this->width * this->height; + while(i--){ + *(dest++) = color.GetARGB(); + } +} + +void gkWinShape::Plot(int x, int y, gkRGB color, int testBoundaries){ + if(!data) return; + if(testBoundaries){ + if(x<0 || x>=width || y<0 || y>=height) return; + } + + gkRGB *dest = (gkRGB*) (data + ((((height - (y+1)) * width) + x) <<2)); + *dest = color; +} + +gkRGB gkWinShape::Point(int x, int y, int testBoundaries){ + if(!data) return gkRGB(0,0,0); + if(testBoundaries){ + if(x<0 || x>=width || y<0 || y>=height) return gkRGB(0,0,0); + } + + gkRGB *color = (gkRGB*) (data + ((((height - (y+1)) * width) + x) <<2)); + return *color; +} + +void gkWinShape::Line(int x1, int y1, int x2, int y2, gkRGB color){ + int temp; + if(y1==y2){ //straight horizontal line + if(x2 < x1) RectFill(x2,y1,(x1-x2)+1,1,color); + else RectFill(x1,y1,(x2-x1)+1,1,color); + return; + }else if(x1==x2){ //straight vertical line + if(y2 < y1) RectFill(x1,y2,1,(y1-y2)+1,color); + else RectFill(x1,y1,1,(y2-y1)+1,color); + return; + } + + + //clip line to screen + if(y2 < y1){ //orient line to be drawn from top to + temp = x1; x1 = x2; x2 = temp; //bottom for initial clipping tests + temp = y1; y1 = y2; y2 = temp; + } + if(y2 < 0 || y1 >= height) return; + + double xdiff = x2-x1, ydiff = y2-y1; + double slopexy = xdiff / ydiff; + int diff; + + //perform vertical clipping + diff = 0 - y1; + if(diff > 0){ //y1 is above top boundary + x1 += (int) (slopexy * diff); + y1 = 0; + } + diff = (y2 - height) + 1; + if(diff > 0){ //y2 is below bottom boundary + x2 -= (int) (slopexy * diff); + y2 = height - 1; + } + + //reorient line to be drawn from left to right for horizontal clipping tests + if(x2 < x1){ + temp = x1; x1 = x2; x2 = temp; + temp = y1; y1 = y2; y2 = temp; + xdiff = x2-x1; + ydiff = y2-y1; + } + double slopeyx = ydiff / xdiff; + + if(x2 < 0 || x1 >= width) return; + + diff = 0 - x1; + if(diff > 0){ //x1 is to left of left boundary + y1 += (int) (slopeyx * diff); + x1 = 0; + } + diff = (x2 - width) + 1; + if(diff > 0){ //x2 is to right of right boundary + y2 -= (int) (slopeyx * diff); + x2 = width - 1; + } + + //draw the line using Bresenham's + //coordinates are now such that x increment is always positive + int xdist = x2-x1; + int ydist = y2-y1; + int pitch = width; + gkRGB *dest = (gkRGB*) (data + ((((height - (y1+1)) * width) + x1) <<2)); + if(ydist < 0){ + ydist = -ydist; + pitch = -pitch; + } + + int err, i; + if(xdist >= ydist){ //loop on x, change y every so often + err = 0; + for(i=xdist; i>=0; i--){ + *(dest++) = color; + err += ydist; + if(err >= xdist){ + err -= xdist; + dest -= pitch; + } + } + }else{ //loop on y, change x every so often + err = 0; + for(i=ydist; i>=0; i--){ + *dest = color; + dest -= pitch; + err += xdist; + if(err >= ydist){ + err -= ydist; + dest++; + } + } + } +} + +void gkWinShape::LineAlpha(int x1, int y1, int x2, int y2, gkRGB color, + int alpha){ + int temp; + if(y1==y2){ //straight horizontal line + if(x2 < x1) RectFill(x2,y1,(x1-x2)+1,1,color); + else RectFill(x1,y1,(x2-x1)+1,1,color); + return; + }else if(x1==x2){ //straight vertical line + if(y2 < y1) RectFill(x1,y2,1,(y1-y2)+1,color); + else RectFill(x1,y1,1,(y2-y1)+1,color); + return; + } + + + //clip line to screen + if(y2 < y1){ //orient line to be drawn from top to + temp = x1; x1 = x2; x2 = temp; //bottom for initial clipping tests + temp = y1; y1 = y2; y2 = temp; + } + if(y2 < 0 || y1 >= height) return; + + double xdiff = x2-x1, ydiff = y2-y1; + double slopexy = xdiff / ydiff; + int diff; + + //perform vertical clipping + diff = 0 - y1; + if(diff > 0){ //y1 is above top boundary + x1 += (int) (slopexy * diff); + y1 = 0; + } + diff = (y2 - height) + 1; + if(diff > 0){ //y2 is below bottom boundary + x2 -= (int) (slopexy * diff); + y2 = height - 1; + } + + //reorient line to be drawn from left to right for horizontal clipping tests + if(x2 < x1){ + temp = x1; x1 = x2; x2 = temp; + temp = y1; y1 = y2; y2 = temp; + xdiff = x2-x1; + ydiff = y2-y1; + } + double slopeyx = ydiff / xdiff; + + if(x2 < 0 || x1 >= width) return; + + diff = 0 - x1; + if(diff > 0){ //x1 is to left of left boundary + y1 += (int) (slopeyx * diff); + x1 = 0; + } + diff = (x2 - width) + 1; + if(diff > 0){ //x2 is to right of right boundary + y2 -= (int) (slopeyx * diff); + x2 = width - 1; + } + + //draw the line using Bresenham's + //coordinates are now such that x increment is always positive + int xdist = x2-x1; + int ydist = y2-y1; + int pitch = width; + gkRGB *dest = (gkRGB*) (data + ((((height - (y1+1)) * width) + x1) <<2)); + if(ydist < 0){ + ydist = -ydist; + pitch = -pitch; + } + + int err, i; + if(xdist >= ydist){ //loop on x, change y every so often + err = 0; + for(i=xdist; i>=0; i--){ + dest->Combine(color,alpha); + dest++; + err += ydist; + if(err >= xdist){ + err -= xdist; + dest -= pitch; + } + } + }else{ //loop on y, change x every so often + err = 0; + for(i=ydist; i>=0; i--){ + dest->Combine(color,alpha); + dest -= pitch; + err += xdist; + if(err >= ydist){ + err -= ydist; + dest++; + } + } + } +} + + +void gkWinShape::RectFill(int x, int y, int w, int h, gkRGB color){ + int x2 = (x + w) - 1; + int y2 = (y + h) - 1; + + //Clip rectangle + if(x < 0) x = 0; + if(y < 0) y = 0; + + if(x2 >= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkRGB *destStart = (gkRGB*) (data + ((((height - (y+1)) * width) + x) <<2)); + gkRGB *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; i= width) x2 = width - 1; + if(y2 >= height) y2 = height - 1; + + if(x2 < x || y2 < y) return; + + //Set pointers and offsets + gkRGB *destStart = (gkRGB*) (data + ((((height - (y+1)) * width) + x) <<2)); + gkRGB *dest; + int numRows = (y2 - y) + 1; + int rowWidth = (x2 - x) + 1; + + //do it + while(numRows--){ + dest = destStart; + + int i; + for(i=0; iCombine(color,alpha); + dest++; + } + destStart -= width; + } +} + + +void gkWinShape::RemapColor(gkRGB oldColor, gkRGB newColor){ + if(!data) return; + + gkRGB *src = (gkRGB*) data; + int i, j; + for(j=0; jGetShape(this, (i<<3), (j<<3), 8, 8); + tiles[numTiles]->ReduceTo4Colors(); +if(numTiles==5) g_sixth = tiles[numTiles]; + numTiles++; + } + } + + int numTilePalettes = numTiles; + gkGBCPalette **tilePalettes = new gkGBCPalette*[numTilePalettes]; + for(i=0; iGetPalette(), + tiles[i]->GetColorsUsed()); + tiles[i]->SetCurPalette(tilePalettes[i]); + } + + //Sort into "most frequent first" + //qsort(tilePalettes, numTilePalettes, sizeof(gkGBCPalette*), + //gkGBCPalette::SortByReferences); + + + //Attempt to merge each palette with any of the previous ones in the list + for(i=0; iCanUnionWith(tilePalettes[j], colorsPerPalette)){ + tilePalettes[i]->MakeUnionWith(tilePalettes[j]); + for(k=0; kGetCurPalette()==tilePalettes[i]){ + tiles[k]->SetCurPalette(tilePalettes[j]); + } + } + delete tilePalettes[i]; + tilePalettes[i] = tilePalettes[--numTilePalettes]; + i--; //try new occupant of this index next loop + break; + } + } + } + + while(numTilePalettes > 8){ + //okay now re-sort, get rid of the least-used palette, and pick one + //of the remaining palettes for its tiles + qsort(tilePalettes, numTilePalettes, sizeof(gkGBCPalette*), + gkGBCPalette::SortByReferences); + + numTilePalettes--; //numTilePalettes is now index of disappearing palette + for(int t=0; tGetCurPalette() != tilePalettes[numTilePalettes]) continue; + int bestMatch = 0; + int smallestDifference = 0x7fffffff; + for(i=0; iMatchPalette(tilePalettes[i]->GetPalette(), + tilePalettes[i]->GetColorsUsed()); + if(diffSetNumReferences( + tilePalettes[bestMatch]->GetNumReferences() + 1); + tiles[t]->SetCurPalette(tilePalettes[bestMatch]); + } + + delete tilePalettes[numTilePalettes]; + } + + //Remap tiles to the palettes they've chosen + for(i=0; iGetCurPalette()) + tiles[i]->Finalize(j); + //} + } + + + ofstream outfile("gbpic.bin",ios::out|ios::binary); + if(!outfile) return; + + int totalTiles = (width>>3) * (height>>3); + if(totalTiles > 512) totalTiles = 512; + + int numBank0Tiles, numBank1Tiles; + + if(totalTiles > 256){ + numBank0Tiles = 256; + numBank1Tiles = totalTiles - 256; + }else{ + numBank0Tiles = totalTiles; + numBank1Tiles = 0; + } + + outfile.put((char)(numBank0Tiles>0)); + if(numBank0Tiles){ + outfile.put((char)numBank0Tiles); + for(i=0; iGetCurPalette()->GetPalette(); + int cbyte1, cbyte2; + for(int row=0; row<8; row++){ + for(int col=0; col<8; col++){ + gkRGB pixel = tile->Point(col,row); + int j; + for(j=0; j<4; j++) if(pal[j]==pixel) break; + cbyte1 = (cbyte1<<1) | (j&1); + cbyte2 = (cbyte2<<1) | ((j>>1)&1); + } + outfile.put((char)cbyte1); + outfile.put((char)cbyte2); + } + } + } + + outfile.put((char)(numBank1Tiles>0)); + if(numBank1Tiles){ + outfile.put((char)numBank1Tiles); + for(i=0; iGetCurPalette()->GetPalette(); + int cbyte1, cbyte2; + for(int row=0; row<8; row++){ + for(int col=0; col<8; col++){ + gkRGB pixel = tile->Point(col,row); + for(j=0; j<4; j++) if(pal[j]==pixel) break; + cbyte1 = (cbyte1<<1) | (j&1); + cbyte2 = (cbyte2<<1) | ((j>>1)&1); + } + outfile.put((char)cbyte1); + outfile.put((char)cbyte2); + } + } + } + + + outfile.put((char)tilesWide); + outfile.put((char)tilesHigh); + + for(j=0; jGetCurPalette(); + int p; + for(p=0; pGetCurPalette(); + for(p=0; p 255) spec1 |= 8; + if(j*tilesWide+i+1 > 255) spec2 |= 8; + + outfile.put((char)((spec1<<4) | spec2)); + } + } + + //write color palettes + for(j=0; j<8; j++){ + gkGBCPalette *gbpal = tilePalettes[j]; + gkRGB *pal = gbpal->GetPalette(); + for(i=0; i<4; i++){ + int sel = (j<<3) | (i<<1); + int p1 = ((pal[i].GetB()>>3)<<10) | ((pal[i].GetG()>>3)<<5) + | (pal[i].GetR()>>3); + int p2 = p1>>8; + p1 &= 0xff; + outfile.put((char)sel); + outfile.put((char)p1); + outfile.put((char)p2); + } + } + + outfile.close(); + + for(i=0; iBlit(this); + + //clean up + for(i=0; iSetA(alpha); + } +} + +void gkWinShape::SetColorAlpha(gkRGB color, int alpha){ + if(!data) return; + + gkRGB *src = (gkRGB*) data; + int i, j; + for(j=0; jSetA(alpha); + } + src++; + } + } +} + +int gkWinShape::GetShape(gkWinShape *srcShape, int x, int y, int w, int h){ + if(!srcShape || !srcShape->data) return 0; + + //adjust src rectangle until it fits within source data + if(x<0){ + w += x; + x = 0; + } + if(y<0){ + h += y; + y = 0; + } + if(x + w > srcShape->width){ + w = srcShape->width - x; + } + if(y + h > srcShape->height){ + h = srcShape->height - y; + } + + if(w<=0 || h<=0) return 0; + + FreeData(); + Create(w, h); + x_origin = x; + y_origin = y; + + gkBYTE *src = (gkBYTE*) ((((srcShape->height-1) - y) * srcShape->width) + x); + src = srcShape->data + ((int)src <<2); + gkBYTE *dest = this->data + (((h-1) * w) << 2); + int srcSkip = srcShape->width << 2; + w <<= 2; + + while(h--){ + memcpy(dest, src, w); + dest -= w; + src -= srcSkip; + } + + return 1; +} + +int gkWinShape::GetShape(gkWinShape *srcShape){ + if(this->width != srcShape->width || this->height != srcShape->height + || (!this->data) || (!srcShape->data)){ + //mem needs to be reallocated + FreeData(); + memcpy(this, srcShape, sizeof(gkWinShape)); + data = 0; + if(srcShape->data){ + data = new gkBYTE[(width * height) << 2]; + memcpy(data, srcShape->data, (width * height) << 2 ); + } + }else{ + //already got right size mem, just copy data over + memcpy(data, srcShape->data, (width * height) << 2); + fontSpacing = srcShape->fontSpacing; + fontKerning = srcShape->fontKerning; + x_handle = srcShape->x_handle; + y_handle = srcShape->y_handle; + x_origin = srcShape->x_origin; + y_origin = srcShape->y_origin; + } + return data!=0; +} + +int gkWinShape::SaveShape(char *filename){ + ofstream outfile(filename, ios::out | ios::binary); + if(!outfile) return 0; + + int result = SaveShape(outfile); + outfile.close(); + + return result; +} + +int gkWinShape::SaveShape(ostream &out){ + int totalSize = ((width * height) << 2); + + out << "SHPE"; + int skipSize = totalSize + 20; + gkIO::WriteLong(out, skipSize); + + //Write shape header + gkIO::WriteWord(out, 3); //type 3 + gkIO::WriteWord(out, width); + gkIO::WriteWord(out, height); + gkIO::WriteWord(out, (bpp==8)?8:32); + out << (char) fontSpacing << (char) fontKerning; + gkIO::WriteWord(out, x_handle); + gkIO::WriteWord(out, y_handle); + gkIO::WriteWord(out, 0); //6 bytes of reserved space + gkIO::WriteLong(out, 0); + + + //Write data + if(data){ + int pitch = width << 2; + gkLONG *src; + gkBYTE *srcStart=(gkBYTE*) ((height-1) * pitch); + + int i,j; + for(j=0; jLoadShape(infile); + infile.close(); + + return result; +} + +int gkWinShape::LoadShape(istream &infile){ + FreeData(); + if(infile.get() != 'S') return 0; + if(infile.get() != 'H') return 0; + if(infile.get() != 'P') return 0; + if(infile.get() != 'E') return 0; + + gkIO::ReadLong(infile); //discard skipsize + + //Read shape header + if(gkIO::ReadWord(infile) != 2) return 0; + width = gkIO::ReadWord(infile); + height = gkIO::ReadWord(infile); + int filebpp = gkIO::ReadWord(infile); + if(!bpp) bpp = filebpp; + + if(width && height){ + Create(width,height); + } + + fontSpacing = infile.get(); + fontKerning = infile.get(); + x_handle = gkIO::ReadWord(infile); + y_handle = gkIO::ReadWord(infile); + + gkIO::ReadWord(infile); + gkIO::ReadLong(infile); //discard reserved space + + if(!width || !height) return 1; //nothing to load, null shape + + int pitch = width << 2; + gkBYTE *destStart = data + (height-1) * pitch; + gkLONG *dest; + int x,y; + for(y=0; ySetA(infile.get()); + //dest->SetR(infile.get()); + //dest->SetG(infile.get()); + //dest->SetB(infile.get()); + //dest++; + } + destStart -= pitch; + } + + return 1; +} + +int gkWinShape::LoadBMP(char *filename){ + ifstream infile(filename,ios::in | ios::binary | ios::nocreate); + if(!infile) return 0; + + int result = this->LoadBMP(infile); + infile.close(); + + return result; +} + +int gkWinShape::LoadBMP(istream &infile){ + BMP_header header; + if(gkIO::ReadWord(infile)!=0x424d){ //check for "BM" + return 0; + } + infile.read((char*)&header, sizeof(BMP_header)); + if(header.bpp != 24){ + cout << "LoadBMP can only handle 24-bit files" << endl; + return 0; + } + + FreeData(); + width = header.width; + height = header.height; + bpp = (char) header.bpp; + Create(width,height); + + // load graphics, coverting every three (B,R,G) bytes to one ARGB value. + // lines padded to even multiple of 4 bytes + int srcPitch = ((header.width * 3) + 3) & (~3); + gkBYTE *buffer = new gkBYTE[srcPitch * height]; + gkBYTE *nextBuffPtr = buffer; + gkBYTE *buffPtr; + + infile.read(buffer, srcPitch * height); + + gkBYTE *nextDest = data; + gkRGB *dest; + int destPitch = (width << 2); + + int i, j; + j = height; + while(j--){ + buffPtr = nextBuffPtr; + nextBuffPtr += srcPitch; + dest = (gkRGB*) nextDest; + nextDest += destPitch; + i = header.width; + while(i--){ + dest->SetB(*(buffPtr++)); + dest->SetG(*(buffPtr++)); + dest->SetR(*(buffPtr++)); + dest->SetA(0xff); + dest++; + } + for(i=header.width; iSetARGB(0); + dest++; + } + } + + delete buffer; + + return 1; +} + + +void gkWinShape::Blit(gkWinShape *destShape, int flags){ + Blit(destShape, x_origin, y_origin, flags); +} + +void gkWinShape::Blit(gkWinShape *destShape, int x, int y, int flags){ + if(!data || !destShape || !destShape->data) return; + + //keep in mind that we're dealing with info organized in the screwy + //BMP bottom-to-top, left-to-right format + + gkBYTE *src = (gkBYTE*) ((this->height - 1) * this->width); + int srcWidth = this->width; + int srcSkip = this->width; + int lines = this->height; + + //clip left side + if(x < 0){ + src += -x; + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src -= (-y * this->width); + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = + (gkBYTE*) ((((destShape->height-1) - y) * destShape->width) + x); + src = this->data + ((int)src << 2); + dest = destShape->data + ((int)dest << 2); + srcWidth <<= 2; + srcSkip <<= 2; + destSkip <<= 2; + + if(flags & GKBLT_TRANSPARENT){ + //blit using alpha 0 as fully transparent + while(lines--){ + MemCpyTrans(dest, src, srcWidth); + src -= srcSkip; + dest -= destSkip; + } + }else{ + //blit without a transparent color + while(lines--){ + memcpy(dest, src, srcWidth); + src -= srcSkip; + dest -= destSkip; + } + } +} + +void gkWinShape::BlitHalfBrite(gkWinShape *destShape, int x, int y, + int flags){ + if(!data || !destShape || !destShape->data) return; + + //keep in mind that we're dealing with info organized in the screwy + //BMP bottom-to-top, left-to-right format + + gkBYTE *src = (gkBYTE*) ((this->height - 1) * this->width); + int srcWidth = this->width; + int srcSkip = this->width; + int lines = this->height; + + //clip left side + if(x < 0){ + src += -x; + srcWidth -= -x; + x = 0; + } + + //clip right side + int diff = (x + srcWidth) - destShape->width; + if(diff > 0){ + srcWidth -= diff; + } + + if(srcWidth <= 0) return; + + //clip top + if(y<0){ + src -= (-y * this->width); + lines += y; //lines -= (-y) + y = 0; + } + + //clip bottom + diff = (y + lines) - destShape->height; + if(diff > 0){ + lines -= diff; + } + + if(lines <= 0) return; + + int destSkip = destShape->width; + + gkBYTE *dest = + (gkBYTE*) ((((destShape->height-1) - y) * destShape->width) + x); + src = this->data + ((int)src << 2); + dest = destShape->data + ((int)dest << 2); + srcWidth <<= 2; + srcSkip <<= 2; + destSkip <<= 2; + + if(flags & GKBLT_TRANSPARENT){ + //blit using alpha 0 as fully transparent + while(lines--){ + MemCpyTransHalfBrite(dest, src, srcWidth); + src -= srcSkip; + dest -= destSkip; + } + }else{ + //blit without a transparent color + while(lines--){ + MemCpyHalfBrite(dest, src, srcWidth); + src -= srcSkip; + dest -= destSkip; + } + } +} + +void gkWinShape::BlitToDC(CDC *pDC, int x, int y){ + //static BITMAPINFOHEADER bmHeader={40, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0}; + static BITMAPINFO bmInfo={{40, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0}}; + static CDC srcDC; + static int setup=0; + + if(!setup){ + setup = 1; + + //HDC hdc = CreateDC("DISPLAY",0,0,0); + //srcDC.Attach(hdc); + srcDC.CreateCompatibleDC(0); + *((int*)(&bmInfo.bmiColors[0])) = 0xff0000; //red mask + *((int*)(&bmInfo.bmiColors[4])) = 0x00ff00; //green mask + *((int*)(&bmInfo.bmiColors[8])) = 0x0000ff; //blue mask + } + + bmInfo.bmiHeader.biWidth = width; + bmInfo.bmiHeader.biHeight = height; + + HBITMAP dib = CreateDIBitmap((HDC) (*pDC), + &bmInfo.bmiHeader, + CBM_INIT, + data, + &bmInfo, + DIB_RGB_COLORS); + + CBitmap bitmap; + bitmap.Attach(dib); + + CBitmap *oldBitmap = srcDC.SelectObject(&bitmap); + pDC->BitBlt(x, y, width, height, &srcDC, 0, 0, SRCCOPY); + srcDC.SelectObject(oldBitmap); + + bitmap.Detach(); + DeleteObject(dib); +} + +void gkWinShape::MemCpyTrans(gkBYTE *dest, gkBYTE *src, + int numBytes){ + //copies colors using the Alpha for transparency + gkRGB *destColor = (gkRGB*) dest; + gkRGB *srcColor = (gkRGB*) src; + int numColors = numBytes >> 2; + int c1; + while(numColors--){ + int alpha; + switch(alpha = (srcColor->GetA())){ + case 0: break; + case 255: //Straight copy + *destColor = *srcColor; + break; + default: //mix alpha + c1 = destColor->GetR(); + c1 += tranTable.LookupTransparencyOffset(srcColor->GetR()-c1, alpha); + destColor->SetR(c1); + c1 = destColor->GetG(); + c1 += tranTable.LookupTransparencyOffset(srcColor->GetG()-c1, alpha); + destColor->SetG(c1); + c1 = destColor->GetB(); + c1 += tranTable.LookupTransparencyOffset(srcColor->GetB()-c1, alpha); + destColor->SetB(c1); + break; + } + srcColor++; + destColor++; + } +} + +void gkWinShape::MemCpyTransHalfBrite(gkBYTE *dest, gkBYTE *src, + int numBytes){ + //copies colors using the Alpha for transparency + gkRGB *destColor = (gkRGB*) dest; + gkRGB *srcColor = (gkRGB*) src; + int numColors = numBytes >> 2; + int c1; + while(numColors--){ + int alpha; + switch(alpha = (srcColor->GetA())){ + case 0: break; + case 255: //Straight copy + destColor->SetR((srcColor->GetR()>>1)&0x7f); + destColor->SetG((srcColor->GetG()>>1)&0x7f); + destColor->SetB((srcColor->GetB()>>1)&0x7f); + break; + default: //mix alpha + c1 = destColor->GetR(); + c1 += tranTable.LookupTransparencyOffset( + (srcColor->GetR()>>1)-c1, alpha); + destColor->SetR(c1); + c1 = destColor->GetG(); + c1 += tranTable.LookupTransparencyOffset( + (srcColor->GetG()>>1)-c1, alpha); + destColor->SetG(c1); + c1 = destColor->GetB(); + c1 += tranTable.LookupTransparencyOffset( + (srcColor->GetB()>>1)-c1, alpha); + destColor->SetB(c1); + break; + } + srcColor++; + destColor++; + } +} + +void gkWinShape::MemCpyHalfBrite(gkBYTE *dest, gkBYTE *src, + int numBytes){ + //copies colors using the Alpha for transparency + gkRGB *destColor = (gkRGB*) dest; + gkRGB *srcColor = (gkRGB*) src; + int numColors = numBytes >> 2; + while(numColors--){ + //Straight copy + destColor->SetR((srcColor->GetR()>>1)&0x7f); + destColor->SetG((srcColor->GetG()>>1)&0x7f); + destColor->SetB((srcColor->GetB()>>1)&0x7f); + srcColor++; + destColor++; + } +} + +gkGBCShape::gkGBCShape() : gkWinShape(){ + colorsMapped = 0; + numColorsMapped = 0; + curPalette = 0; +} + +gkGBCShape::~gkGBCShape(){ + gkWinShape::~gkWinShape(); +} + +void gkGBCShape::ReduceTo4Colors(){ + gkWinShape::ReduceColors(4); + + //record the colors used + colorsUsed = 0; + int i, j; + for(i=0; i<4; i++) occurrences[i] = 0; + gkRGB *src = (gkRGB*) data; + i = width*height; + while(i--){ + //generator.AddColor(*src); + for(j=0; j=colorsUsed){ //found unrecorded color + occurrences[colorsUsed] = 1; + colors[colorsUsed++] = *src; + } + if(colorsUsed==4) break; + src++; + } +} + +int gkGBCShape::MatchPalette(gkRGB *palette, int numColors){ + gkPaletteGenerator generator; + + //Add other palette to gen + int i; + for(i=0; iGetPalette()[0]; + gkRGB c2 = curPalette->GetPalette()[1]; + gkRGB c3 = curPalette->GetPalette()[2]; + gkRGB c4 = curPalette->GetPalette()[3]; + int cUsed = curPalette->GetColorsUsed(); + ASSERT(n!=1); + */ +//if(this==g_sixth) ASSERT(0); + RemapToPalette(curPalette->GetPalette(), + curPalette->GetColorsUsed()); +} + +gkGBCPalette::gkGBCPalette(gkRGB *init_colors, int init_colorsUsed){ + int i; + colorsUsed = init_colorsUsed; + for(i=0; inumReferences > p2->numReferences) return -1; + if(p1->numReferences < p2->numReferences) return 1; + return 0; +} + +int gkGBCPalette::CanUnionWith(gkGBCPalette *p2, int maxColors){ + gkPaletteGenerator generator; + + //add all colors in both palettes to generator + int i; + for(i=0; icolorsUsed; i++) generator.AddColor(p2->colors[i]); + + if(generator.NumUniqueColors() > maxColors) return 0; //no union possible + return 1; //can do a union +} + +void gkGBCPalette::MakeUnionWith(gkGBCPalette *p2){ + gkPaletteGenerator generator; + + //add all colors in both palettes to generator + int i; + for(i=0; icolorsUsed; i++) generator.AddColor(p2->colors[i]); + + p2->colorsUsed = + generator.CreatePalette(p2->colors, generator.NumUniqueColors()); + p2->numReferences += numReferences; +} + diff --git a/Tools/LevelEditor/Source/wingk.h b/Tools/LevelEditor/Source/wingk.h new file mode 100644 index 0000000..1473dfa --- /dev/null +++ b/Tools/LevelEditor/Source/wingk.h @@ -0,0 +1,242 @@ +#ifndef WINGK_H +#define WINGK_H + +#include "stdafx.h" + +#include +#include +#include +#include +#include + +typedef unsigned char gkBYTE; +typedef short int gkWORD; +typedef int gkLONG; + +#define GKHANDLE_TL 0 +#define GKHANDLE_TC 1 +#define GKHANDLE_TR 2 +#define GKHANDLE_CR 3 +#define GKHANDLE_BR 4 +#define GKHANDLE_BC 5 +#define GKHANDLE_BL 6 +#define GKHANDLE_CL 7 +#define GKHANDLE_CENTER 8 + +#define GKBLT_TRANSPARENT 1 + +class gkIO{ + public: + inline static int ReadByte(istream &in){ return in.get(); } + static int ReadWord(istream &in); + static int ReadLong(istream &in); + static char *ReadString(istream &in); + static char *ReadNewString(istream &in); + inline static void WriteByte(ostream &out, int n){ out << (char) n; } + static void WriteLong(ostream &out, int n); + static void WriteWord(ostream &out, int n); + static void WriteString(ostream &out, char *st); +}; + +struct gkRGB_4bytes{ + unsigned char b, g, r, a; +}; + +union gkRGB_ColorUnion{ + gkRGB_4bytes bytes; + gkLONG argb; +}; + +class gkRGB{ + public: + gkRGB_ColorUnion color; + + inline gkRGB(){ color.argb = 0xff000000; } + inline gkRGB(int _r, int _g, int _b, int _a=255){ + color.bytes.r=_r; color.bytes.g=_g; color.bytes.b=_b; color.bytes.a=_a;} + inline void SetR(gkBYTE n){ color.bytes.r = n; } + inline void SetG(gkBYTE n){ color.bytes.g = n; } + inline void SetB(gkBYTE n){ color.bytes.b = n; } + inline void SetA(gkBYTE n){ color.bytes.a = n; } + inline void SetARGB(gkLONG n){ color.argb = n; } + inline gkBYTE GetR(){ return color.bytes.r; } + inline gkBYTE GetG(){ return color.bytes.g; } + inline gkBYTE GetB(){ return color.bytes.b; } + inline gkBYTE GetA(){ return color.bytes.a; } + inline gkLONG GetARGB(){ return color.argb; } + inline int operator==(gkRGB &c2); + inline int Equals(int _r, int _g, int _b); + int GetCategory(); + void Combine(gkRGB c2, int alpha); +}; + +class gkPalGenItem{ + protected: + gkRGB color; + int occurrences; + gkPalGenItem *nextItem; + + public: + gkPalGenItem(gkRGB _color); + gkPalGenItem(gkPalGenItem *item); + ~gkPalGenItem(); + inline gkRGB GetColor(); + inline void AddOccurrence(); + inline int GetOccurrences(); + inline void SetOccurrences(int n); + inline void SetNextItem(gkPalGenItem *item); + inline gkPalGenItem *GetNextItem(); + static int SortCallback(const void *e1, const void *e2); +}; + +class gkColorCategory{ + protected: + gkPalGenItem *hashHead[64]; + gkPalGenItem *hashTail[64]; + int uniqueCount; + short int curHash; + gkPalGenItem *curItem; + + public: + gkColorCategory(); + ~gkColorCategory(); + gkPalGenItem *GetFirstItem(); + gkPalGenItem *GetNextItem(); + gkPalGenItem *Exists(gkRGB color); + void AddColor(gkRGB color); + void SetZeroOccurrences(gkRGB color); + int GetHash(gkRGB color); + int GetUniqueCount(){ return uniqueCount; } + gkRGB GetMostFrequent(); + gkPalGenItem *GetMostFrequentItem(); +}; + +class gkPaletteGenerator{ + protected: + gkColorCategory colorCube[512]; //8*8*8 + + public: + gkPaletteGenerator(); + ~gkPaletteGenerator(); + void Reset(); + void AddColor(gkRGB color); + int CreatePalette(gkRGB *palette, int numEntries); + int GetHash(gkRGB color); + gkRGB MatchColor(gkRGB color); + gkRGB GetMostFrequent(); + int NumUniqueColors(); + gkColorCategory *GetCategory(int hash); +}; + +class gkTransparencyTable{ + protected: + gkBYTE *lookup; + + public: + gkTransparencyTable(); + ~gkTransparencyTable(); + inline int LookupTransparencyOffset(int baseOffset, int alpha); +}; + +class gkGBCPalette; + +class gkWinShape{ + protected: + gkBYTE *data; + int width, height; + char bpp, fontSpacing, fontKerning; + short int x_handle, y_handle; + short int x_origin, y_origin; + + public: + static gkTransparencyTable tranTable; + + public: + gkWinShape(); + ~gkWinShape(); + void FreeData(); + void Create(int _width, int _height); + void Cls(); + void Cls(gkRGB color); + void Plot(int x, int y, gkRGB color, int testBoundaries=1); + gkRGB Point(int x, int y, int testBoundaries=1); + void Line(int x1, int y1, int x2, int y2, gkRGB color); + void LineAlpha(int x1, int y1, int x2, int y2, gkRGB color, int alpha); + void RectFill(int x, int y, int w, int h, gkRGB color); + void RectFillAlpha(int x, int y, int w, int h, gkRGB color, int alpha); + void RemapColor(gkRGB oldColor, gkRGB newColor); + void RemapToPalette(gkRGB *palette, int numColors); + int ReduceColors(int numColors); + void RemapToGBC(gkRGB *palettes, int numPalettes, + int colorsPerPalette); + void ExchangeColors(gkRGB c1, gkRGB c2); + void SetAlpha(int alpha); + void SetColorAlpha(gkRGB color, int alpha); + + int GetShape(gkWinShape *srcShape, int x, int y, int w, int h); + int GetShape(gkWinShape *srcShape); + int SaveShape(char *filename); + int SaveShape(ostream &outfile); + int LoadShape(char *filename); + int LoadShape(istream &infile); + int LoadBMP(char *filename); + int LoadBMP(istream &infile); + void Blit(gkWinShape *destShape, int flags=GKBLT_TRANSPARENT); + void Blit(gkWinShape *destShape, int x, int y, + int flags=GKBLT_TRANSPARENT); + void BlitHalfBrite(gkWinShape *destShape, int x, int y, + int flags=GKBLT_TRANSPARENT); + void BlitToDC(CDC *pDC, int x, int y); + + int GetWidth(){ return width; } + int GetHeight(){ return height; } + gkBYTE *GetData(){ return data; } + + //internal support routines + static void MemCpyTrans(gkBYTE *dest, gkBYTE *src, int nBytes); + static void MemCpyTransHalfBrite(gkBYTE *dest, gkBYTE *src, int nBytes); + static void MemCpyHalfBrite(gkBYTE *dest, gkBYTE *src, int nBytes); +}; + +class gkGBCShape : public gkWinShape{ + protected: + gkRGB colors[4]; + int occurrences[4]; + int colorsUsed; + int colorsMapped; //bits 0-3 determine which colors are mapped + int numColorsMapped; + gkGBCPalette *curPalette; + + public: + gkGBCShape(); + ~gkGBCShape(); + + inline int GetColorsUsed(){ return colorsUsed; } + inline gkRGB *GetPalette(){ return colors; } + inline gkGBCPalette *GetCurPalette(){ return curPalette; } + inline void SetCurPalette(gkGBCPalette *pal){ curPalette = pal; } + + void ReduceTo4Colors(); + int MatchPalette(gkRGB *palette, int numColors); + void Finalize(int n); +}; + +class gkGBCPalette{ + protected: + gkRGB colors[4]; + int colorsUsed; + int numReferences; + + public: + gkGBCPalette(gkRGB *init_colors, int init_colorsUsed); + inline gkRGB *GetPalette(){ return colors; } + inline int GetColorsUsed(){ return colorsUsed; } + inline void SetNumReferences(int n){ numReferences = n; } + inline int GetNumReferences(){ return numReferences; } + static int SortByReferences(const void *e1, const void *e2); + int CanUnionWith(gkGBCPalette *p2, int maxColors); + void MakeUnionWith(gkGBCPalette *p2); +}; + +#endif + diff --git a/Tools/LevelEditor/background0001-1535.bmp b/Tools/LevelEditor/background0001-1535.bmp new file mode 100644 index 0000000..3bb9bb9 Binary files /dev/null and b/Tools/LevelEditor/background0001-1535.bmp differ diff --git a/Tools/LevelEditor/exitTiles.bmp b/Tools/LevelEditor/exitTiles.bmp new file mode 100644 index 0000000..d0bd0fa Binary files /dev/null and b/Tools/LevelEditor/exitTiles.bmp differ diff --git a/Tools/LevelEditor/objects2048-2303.bmp b/Tools/LevelEditor/objects2048-2303.bmp new file mode 100644 index 0000000..0557dc8 Binary files /dev/null and b/Tools/LevelEditor/objects2048-2303.bmp differ