//--------------------------------------------------------------------------- // WorldDoc.cpp : implementation of the WorldDoc class // // (C) COPYRIGHT John Henckel, mailto:henckel@iname.com Aug 1998 // // Permission to use, copy, modify, distribute and sell this software // and its documentation for any purpose is hereby granted without fee, // provided that the above copyright notice appear in all copies. // // Visit my website! http://www.GeoCities.com/Paris/6502 #include "stdafx.h" #include "Poetry.h" #include "WorldDoc.h" #include "CameraView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //--------------------------------------------------------------------------- // WorldDoc IMPLEMENT_DYNCREATE(WorldDoc, CDocument) BEGIN_MESSAGE_MAP(WorldDoc, CDocument) //{{AFX_MSG_MAP(WorldDoc) // 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 ON_COMMAND(ID_FILE_SEND_MAIL, OnFileSendMail) ON_UPDATE_COMMAND_UI(ID_FILE_SEND_MAIL, OnUpdateFileSendMail) END_MESSAGE_MAP() //--------------------------------------------------------------------------- DWORD WINAPI AnimateWorld(LPVOID parm) { WorldDoc* pDoc = (WorldDoc*)parm; while (1) { Sleep(pDoc->waitTime); if (pDoc->isAwake) pDoc->Step(); } return 0; } //--------------------------------------------------------------------------- // WorldDoc construction/destruction WorldDoc::WorldDoc() { waitTime = 200; // millisec per time step isAwake = 1; count = 0; thread = CreateThread(NULL, 0, AnimateWorld, this, 0, &tid); } WorldDoc::~WorldDoc() { TerminateThread(thread,0); } BOOL WorldDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; } //--------------------------------------------------------------------------- // WorldDoc set up the views using the camera objects void WorldDoc::SetCameraViews() { CWinApp* app = AfxGetApp(); CMDIFrameWnd* frame = (CMDIFrameWnd*) app->m_pMainWnd; // Get the frame pointer so we can add views POSITION vpos = GetFirstViewPosition(); POSITION cpos = cameralist.GetHeadPosition(); CameraView* view; while (cpos) { if (vpos) { view = (CameraView*) GetNextView(vpos); } else { CMDIChildWnd* aChild = frame->MDIGetActive(); ASSERT(aChild); CDocTemplate* pTemplate = GetDocTemplate(); ASSERT_VALID(pTemplate); CFrameWnd* pFrame = pTemplate->CreateNewFrame(this, aChild); ASSERT(pFrame); pTemplate->InitialUpdateFrame(pFrame, this); view = (CameraView*) pFrame->GetActiveView(); } view->cam = (Camera*) cameralist.GetNext(cpos); // small memory leak here view->needRefresh = TRUE; } } //--------------------------------------------------------------------------- // WorldDoc serialization void WorldDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { Store(ar); } else { Load(ar); SetCameraViews(); } } #define FILE_TAG "Tru-Physics" //--------------------------------------------------------------------------- // WorldDoc Store void WorldDoc::Store(CArchive& ar) { ar << " " FILE_TAG "\n\nBox {\n location 1 0 0\n size 2 3 4\n}\n"; } //--------------------------------------------------------------------------- // This utility function glues together any data contained in brackets. static void MatchBracket(CArchive& ar, CString& data, CString& errmsg, int& line) { CString temp; int n,t1 = line; n = data.Find('['); if (n < 0) return; data.SetAt(n, ' '); n = data.Find(']'); while (n == -1) { if (!ar.ReadString(temp)) { data = "}"; temp.Format("Matching bracket not found for '[' on line %d.\n",t1); errmsg += temp; break; } ++line; temp.TrimLeft(); temp = temp.SpanExcluding("#;"); temp.TrimRight(); if (temp=="}") { data = temp; temp.Format("Matching bracket not found for '[' on line %d.\n",t1); errmsg += temp; break; } data += " "; data += temp; n = temp.Find(']'); } data = data.SpanExcluding("]"); data.TrimRight(); } //--------------------------------------------------------------------------- // WorldDoc Load void WorldDoc::Load(CArchive& ar) { CString vers; ar.ReadString(vers); if (vers.Find(FILE_TAG) < 0) { int button = AfxMessageBox("The first line of the file does not have the '" FILE_TAG "' identifier.\n\nPress OK to continue reading the file," " or press Cancel to stop reading it.", MB_OKCANCEL); if (button == IDCANCEL) { CException* badfile = new CArchiveException(CArchiveException::badIndex); THROW(badfile); } } int line; CString data; CString msg; Shape* sh = NULL; for (line = 2; ar.ReadString(data); ++line) { data.TrimLeft(); data = data.SpanExcluding("#;"); // trim comments data.TrimRight(); if (data=="") // empty line continue; MatchBracket(ar,data,msg,line); if (!sh) { // Shape Creation sh = Shape::CreateFromString(data,line,msg); } else { if (data=="}") { // End of shape sh->FinishInit(); if (sh->Type() == t_Camera) cameralist.AddTail(sh); else shapelist.AddTail(sh); sh = NULL; } else if (data!="{") // Shape Attributes sh->ParseAttr(data,line,msg); } if (msg.GetLength() > 1000) break; // too many errors } if (msg != "") AfxMessageBox(msg); // display all parser messages } //--------------------------------------------------------------------------- // WorldDoc diagnostics #ifdef _DEBUG void WorldDoc::AssertValid() const { CDocument::AssertValid(); } void WorldDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG //---------------------------------------------------------------------------- // Draw the document into the current OpenGL rc. void WorldDoc::Draw() { POSITION pos = shapelist.GetHeadPosition(); while (pos) { glPushMatrix(); shapelist.GetNext(pos)->Draw(0); glPopMatrix(); } } //---------------------------------------------------------------------------- // Draw the document into the current OpenGL rc. int WorldDoc::FrameCount() { return count; } //---------------------------------------------------------------------------- // Perform one time step to the world. This is called by the animator. void WorldDoc::Step() { int c = 0; POSITION pos = shapelist.GetHeadPosition(); while (pos) c += shapelist.GetNext(pos)->Step(); if (c) ++count; }