/* Starshatter OpenSource Distribution Copyright (c) 1997-2004, Destroyer Studios LLC. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name "Destroyer Studios" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SUBSYSTEM: Magic.exe FILE: MagicView.cpp AUTHOR: John DiCamillo OVERVIEW ======== Implementation of the MagicView class */ #include "stdafx.h" #include "Magic.h" #include "MagicDoc.h" #include "MagicView.h" #include "MainFrm.h" #include "MaterialDialog.h" #include "SurfacePropertiesDialog.h" #include "TextureMapDialog.h" #include "Editor.h" #include "Grid.h" #include "GridProps.h" #include "Selection.h" #include "Selector.h" #include "UVMapView.h" #include "ActiveWindow.h" #include "Color.h" #include "Layout.h" #include "Light.h" #include "Scene.h" #include "Screen.h" #include "Shadow.h" #include "Solid.h" #include "Video.h" #include "VideoDX9.h" #include "VideoSettings.h" #include "ModelView.h" DWORD GetRealTime(); #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif extern PALETTEENTRY standard_palette[256]; extern BYTE inverse_palette[32768]; // +--------------------------------------------------------------------+ IMPLEMENT_DYNCREATE(MagicView, CView) BEGIN_MESSAGE_MAP(MagicView, CView) //{{AFX_MSG_MAP(MagicView) ON_WM_SIZE() ON_COMMAND(ID_VIEW_RENDER, OnRender) ON_WM_PAINT() ON_COMMAND(ID_VIEW_ALL, OnViewAll) ON_UPDATE_COMMAND_UI(ID_VIEW_ALL, OnUpdateViewAll) ON_COMMAND(ID_VIEW_FRONT, OnViewFront) ON_UPDATE_COMMAND_UI(ID_VIEW_FRONT, OnUpdateViewFront) ON_COMMAND(ID_VIEW_PERSPECTIVE, OnViewPerspective) ON_UPDATE_COMMAND_UI(ID_VIEW_PERSPECTIVE, OnUpdateViewPerspective) ON_COMMAND(ID_VIEW_SIDE, OnViewSide) ON_UPDATE_COMMAND_UI(ID_VIEW_SIDE, OnUpdateViewSide) ON_COMMAND(ID_VIEW_TOP, OnViewTop) ON_UPDATE_COMMAND_UI(ID_VIEW_TOP, OnUpdateViewTop) ON_COMMAND(ID_MODIFY_TEXTURE_MAP, OnTextureMap) ON_COMMAND(ID_MODIFY_MATERIAL, OnModifyMaterial) ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_LBUTTONDBLCLK() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_MOUSEWHEEL() ON_COMMAND(ID_VIEW_ZOOM_NORMAL, OnViewZoomNormal) ON_COMMAND(ID_VIEW_ZOOM_IN, OnViewZoomIn) ON_COMMAND(ID_VIEW_ZOOM_OUT, OnViewZoomOut) ON_COMMAND(ID_VIEW_MODE_WIREFRAME, OnViewModeWireframe) ON_COMMAND(ID_VIEW_MODE_SOLID, OnViewModeSolid) ON_COMMAND(ID_VIEW_MODE_TEXTURED, OnViewModeTextured) ON_WM_RBUTTONDBLCLK() ON_COMMAND(ID_PROP_GRID, OnGridProperties) ON_COMMAND(ID_GRID_SHOW, OnGridShow) ON_COMMAND(ID_GRID_SNAP, OnGridSnap) ON_UPDATE_COMMAND_UI(ID_GRID_SNAP, OnUpdateGridSnap) ON_COMMAND(ID_VIEW_BACK_COLOR, OnViewBackColor) ON_COMMAND(ID_FILE_IMPORT, OnFileImport) ON_COMMAND(ID_FILE_EXPORT, OnFileExport) ON_COMMAND(ID_EDIT_SELECT_ALL, OnSelectAll) ON_COMMAND(ID_EDIT_SELECT_NONE, OnSelectNone) ON_UPDATE_COMMAND_UI(ID_MODIFY_TEXTURE_MAP, OnUpdateTextureMap) ON_UPDATE_COMMAND_UI(ID_MODIFY_MATERIAL, OnUpdateModifyMaterial) ON_COMMAND(ID_EDIT_SELECT_INVERSE, OnSelectInverse) ON_COMMAND(ID_MODIFY_UV_MAP, OnModifyUVMap) ON_UPDATE_COMMAND_UI(ID_MODIFY_UV_MAP, OnUpdateModifyUVMap) ON_COMMAND(ID_VIEW_SHADOWS, OnViewShadows) ON_UPDATE_COMMAND_UI(ID_VIEW_SHADOWS, OnUpdateViewShadows) ON_COMMAND(ID_VIEW_ANIMATELIGHT, OnViewAnimatelight) ON_UPDATE_COMMAND_UI(ID_VIEW_ANIMATELIGHT, OnUpdateViewAnimatelight) ON_COMMAND(ID_VIEW_BUMPMAPS, OnViewBumpmaps) ON_UPDATE_COMMAND_UI(ID_VIEW_BUMPMAPS, OnUpdateViewBumpmaps) ON_COMMAND(ID_VIEW_VERTEXSHADER, OnViewVertexshader) ON_UPDATE_COMMAND_UI(ID_VIEW_VERTEXSHADER, OnUpdateViewVertexshader) ON_COMMAND(ID_VIEW_PIXELSHADER, OnViewPixelshader) ON_UPDATE_COMMAND_UI(ID_VIEW_PIXELSHADER, OnUpdateViewPixelshader) ON_COMMAND(ID_VIEW_VISIBLESHADOWS, OnViewVisibleshadows) ON_UPDATE_COMMAND_UI(ID_VIEW_VISIBLESHADOWS, OnUpdateViewVisibleshadows) ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo) ON_COMMAND(ID_EDIT_REDO, OnEditRedo) ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo) ON_COMMAND(ID_PROP_SURFACE, OnSurfaceProperties) ON_UPDATE_COMMAND_UI(ID_PROP_SURFACE, OnUpdateSurfaceProperties) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP() // +--------------------------------------------------------------------+ static MagicView* magic_view = 0; MagicView::MagicView() : video(0), video_settings(0), screen(0), scene(0), drag_left(false), drag_right(false), grid(0), main_light(0), back_light(0), view_shadows(true), view_bumpmaps(true), animate_light(false) { window_style = 0; is_minimized = false; is_maximized = false; is_sizing = false; view_mode = VIEW_ALL; main_win = 0; view_win[0] = 0; view_win[1] = 0; view_win[2] = 0; view_win[3] = 0; model_view[0] = 0; model_view[1] = 0; model_view[2] = 0; model_view[3] = 0; uvmap_win = 0; grid = new Grid; magic_view = this; Solid::EnableCollision(false); } MagicView::~MagicView() { if (grid) { delete grid; } if (scene) { scene->Graphics().clear(); delete scene; } if (screen) delete screen; if (video) delete video; if (video_settings) delete video_settings; if (magic_view == this) magic_view = 0; } MagicView* MagicView::GetInstance() { return magic_view; } BOOL MagicView::PreCreateWindow(CREATESTRUCT& cs) { return CView::PreCreateWindow(cs); } // +--------------------------------------------------------------------+ // // MagicView diagnostics #ifdef _DEBUG void MagicView::AssertValid() const { CView::AssertValid(); } void MagicView::Dump(CDumpContext& dc) const { CView::Dump(dc); } MagicDoc* MagicView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(MagicDoc))); return (MagicDoc*)m_pDocument; } #endif //_DEBUG // +--------------------------------------------------------------------+ void MagicView::OnInitialUpdate() { CView::OnInitialUpdate(); Color::SetPalette(standard_palette, 256, inverse_palette); if (!video_settings) video_settings = new VideoSettings; GetClientRect(&client_rect); // Use client area to set video window size int w = client_rect.right - client_rect.left; int h = client_rect.bottom - client_rect.top; video_settings->is_windowed = true; video_settings->window_width = w; video_settings->window_height = h; if (!video) { video = new VideoDX9(GetSafeHwnd(), video_settings); *video_settings = *video->GetVideoSettings(); if (video) { Color::UseVideo(video); video->UseXFont("System", 12, false, false); screen = new Screen(video); if (!screen) { ::Print("ERROR: Could not create Screen object.\n"); return; } ::Print(" Created screen object (%d x %d).\n", w, h); if (!screen->SetBackgroundColor(Color::Black)) ::Print(" WARNING: could not set video background color to Black\n"); screen->ClearAllFrames(true); ::Print(" Established requested video parameters.\n"); ::Print(" ---------------------------------------\n\n"); if (!scene) { scene = new Scene; scene->SetAmbient(Color(60,60,60)); Point light_pos(3e6, 5e6, 4e6); main_light = new Light(1.0f); //1.25f); main_light->MoveTo(light_pos); main_light->SetType(Light::LIGHT_DIRECTIONAL); main_light->SetColor(Color::White); main_light->SetShadow(true); scene->AddLight(main_light); back_light = new Light(0.5f); back_light->MoveTo(light_pos * -1); back_light->SetType(Light::LIGHT_DIRECTIONAL); back_light->SetColor(Color::White); scene->AddLight(back_light); Selection* seln = GetDocument()->GetSelection(); Selector* selector = GetDocument()->GetSelector(); if (seln && selector) { scene->Graphics().clear(); scene->AddGraphic(seln); scene->AddGraphic(selector); selector->UseModel(0); } } int mins[2] = { 0, 0 }; float weights[2] = { 1, 1 }; main_win = new ActiveWindow(screen, 0, 0, w, h, 100, 0); main_win->UseLayout(2, 2, mins, mins, weights, weights); main_win->SetBackColor(Color::Gray); screen->AddWindow(main_win); DWORD view_types[] = { ModelView::VIEW_PLAN, ModelView::VIEW_PROJECT, ModelView::VIEW_SIDE, ModelView::VIEW_FRONT }; for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++) { int index = 2*row + col; ActiveWindow* win = new ActiveWindow(screen, col*w/2, row*h/2, w/2, h/2, 101+index, WIN_BLACK_FRAME, main_win); win->SetCells(col, row, 1, 1); win->SetCellInsets(Insets(1,1,1,1)); win->SetBackColor(Color(160,160,160)); ModelView* mv = new ModelView(win, scene, view_types[index]); if (view_types[index] == ModelView::VIEW_PROJECT) mv->SetFillMode(ModelView::FILL_TEXTURE); mv->UseGrid(grid); win->AddView(mv); view_win[index] = win; model_view[index] = mv; } } view_win[0]->SetStyle(WIN_WHITE_FRAME); uvmap_win = new ActiveWindow(screen, 0, 0, w, h, 110, WIN_BLACK_FRAME, main_win); uvmap_view = new UVMapView(uvmap_win); uvmap_win->AddView(uvmap_view); main_win->DoLayout(); } else { ::Print(" Could not establish requested video parameters.\n"); ::Print(" -----------------------------------------------\n\n"); } } } // +--------------------------------------------------------------------+ void MagicView::SetupModelViews() { switch (view_mode) { case VIEW_ALL: { for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++) { int index = 2*row + col; ActiveWindow* win = view_win[index]; win->Show(); win->SetCells(col, row, 1, 1); win->SetCellInsets(Insets(1,1,1,1)); } } uvmap_win->Hide(); uvmap_win->SetCells(0,0,0,0); } break; case VIEW_TOP: case VIEW_SIDE: case VIEW_FRONT: case VIEW_PERSPECTIVE: { view_focus = view_mode; for (int i = 0; i < 4; i++) { ActiveWindow* win = view_win[i]; if (i == view_mode) { win->Show(); win->SetCells(0,0,2,2); win->SetStyle(WIN_WHITE_FRAME); } else { win->Hide(); win->SetCells(0,0,0,0); win->SetStyle(WIN_BLACK_FRAME); } } uvmap_win->Hide(); uvmap_win->SetCells(0,0,0,0); } break; case VIEW_UV_MAP: { view_focus = view_mode; for (int i = 0; i < 4; i++) { ActiveWindow* win = view_win[i]; win->Hide(); win->SetCells(0,0,0,0); win->SetStyle(WIN_BLACK_FRAME); } uvmap_win->Show(); uvmap_win->SetCells(0,0,2,2); } break; default: break; } main_win->DoLayout(); } void MagicView::SetFocusModelView(int f) { if (view_mode == VIEW_ALL) { view_focus = f; for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++) { int index = 2*row + col; ActiveWindow* win = view_win[index]; win->Show(); win->SetCells(col, row, 1, 1); win->SetCellInsets(Insets(1,1,1,1)); if (index == view_focus) { win->SetStyle(WIN_WHITE_FRAME); } else { win->SetStyle(WIN_BLACK_FRAME); } } } } else if (IsUVEdit()) { view_focus = view_mode; } else { view_mode = f; view_focus = f; for (int i = 0; i < 4; i++) { ActiveWindow* win = view_win[i]; if (i == view_mode) { win->Show(); win->SetCells(0,0,2,2); win->SetStyle(WIN_WHITE_FRAME); } else { win->Hide(); win->SetCells(0,0,0,0); win->SetStyle(WIN_BLACK_FRAME); } } } main_win->DoLayout(); } int MagicView::GetWinIndexByPoint(int x, int y) { if (view_mode == VIEW_ALL) { for (int row = 0; row < 2; row++) { for (int col = 0; col < 2; col++) { int index = 2*row + col; ActiveWindow* win = view_win[index]; if (win->GetRect().Contains(x, y)) return index; } } } return view_mode; } ModelView* MagicView::GetModelViewByIndex(int index) { if (index >= 0 && index < 4) { return model_view[index]; } return model_view[0]; } // +--------------------------------------------------------------------+ void MagicView::OnPaint() { ValidateRect(0); OnRender(); } void MagicView::OnDraw(CDC* dc) { } // +--------------------------------------------------------------------+ void MagicView::ResizeVideo() { if (!video || !video_settings) return; HRESULT hr = S_OK; RECT client_old; client_old = client_rect; // Update window properties GetClientRect(&client_rect); if (client_old.right - client_old.left != client_rect.right - client_rect.left || client_old.bottom - client_old.top != client_rect.bottom - client_rect.top) { // A new window size will require a new backbuffer // size, so the 3D structures must be changed accordingly. video_settings->is_windowed = true; video_settings->window_width = client_rect.right - client_rect.left; video_settings->window_height = client_rect.bottom - client_rect.top; ::Print("ResizeVideo() %d x %d\n", video_settings->window_width, video_settings->window_height); if (video) { video->Reset(video_settings); } } // save a copy of the device-specific video settings: if (video->GetVideoSettings()) { *video_settings = *video->GetVideoSettings(); } if (screen) screen->Resize(video_settings->window_width, video_settings->window_height); video->InvalidateCache(); video->SetShadowEnabled(view_shadows); video->SetBumpMapEnabled(view_bumpmaps); } // +--------------------------------------------------------------------+ void MagicView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { CView::OnUpdate(pSender, lHint, pHint); Solid* solid = GetDocument()->GetSolid(); Selection* seln = GetDocument()->GetSelection(); Selector* selector = GetDocument()->GetSelector(); if (solid && scene) { scene->Graphics().clear(); scene->AddGraphic(solid); scene->AddGraphic(seln); scene->AddGraphic(selector); } if (selector) selector->UseModel(solid->GetModel()); } CPoint MagicView::LPtoWP(const CPoint& p) { CPoint result; ModelView* view = GetModelViewByIndex(view_focus); CPoint origin = view->ProjectPoint(Vec3(0,0,0)); double scale = view->GetFieldOfView() / 2; result.x = (LONG) (( p.x - origin.x) / scale); result.y = (LONG) ((-p.y + origin.y) / scale); return result; } // +--------------------------------------------------------------------+ // // MagicView message handlers void MagicView::OnEnterSizeMove() { is_sizing = true; } void MagicView::OnExitSizeMove() { is_sizing = false; ResizeVideo(); } void MagicView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); window_style = GetWindowLong(m_hWnd, GWL_STYLE); if (nType == SIZE_MINIMIZED) { is_minimized = true; is_maximized = false; } else if (nType == SIZE_MAXIMIZED) { is_minimized = false; is_maximized = true; ResizeVideo(); } else if (nType == SIZE_RESTORED) { if (is_maximized) { is_maximized = false; ResizeVideo(); } else if (is_minimized) { is_minimized = false; ResizeVideo(); } else if (!is_sizing) { // if this is not a resize due to dragging... ResizeVideo(); } else { // If we're neither maximized nor minimized, the window size // is changing by the user dragging the window edges. In this // case, we don't reset the device yet -- we wait until the // user stops dragging, and a WM_EXITSIZEMOVE message comes. } } } // +--------------------------------------------------------------------+ void MagicView::OnRender() { if (!screen || !video) return; double s = sin(timeGetTime() * 0.001); double c = cos(timeGetTime() * 0.001); // IF LIGHTS ANIMATED: if (animate_light) { Point light_pos(3e6*s, 5e6*c, 4e6*s); if (main_light) { main_light->SetType(Light::LIGHT_POINT); main_light->MoveTo(light_pos); main_light->SetType(Light::LIGHT_DIRECTIONAL); } if (back_light) { back_light->SetType(Light::LIGHT_POINT); back_light->MoveTo(light_pos * -1); back_light->SetType(Light::LIGHT_DIRECTIONAL); } } if (screen->Refresh()) { video->Present(); } else { ::Print("ERROR: Screen refresh failed.\n"); } } void MagicView::CloseUVEditor() { if (IsUVEdit()) { MagicDoc* doc = GetDocument(); Editor* editor = doc->GetEditor(); Solid* solid = doc->GetSolid(); if (editor && solid) { editor->UseModel(solid->GetModel()); editor->Resegment(); } } } // +--------------------------------------------------------------------+ void MagicView::OnViewAll() { CloseUVEditor(); view_mode = VIEW_ALL; SetupModelViews(); } void MagicView::OnUpdateViewAll(CCmdUI* pCmdUI) { if (pCmdUI) pCmdUI->SetCheck(view_mode == VIEW_ALL); } void MagicView::OnViewFront() { CloseUVEditor(); view_mode = VIEW_FRONT; SetupModelViews(); } void MagicView::OnUpdateViewFront(CCmdUI* pCmdUI) { if (pCmdUI) pCmdUI->SetCheck(view_mode == VIEW_FRONT); } void MagicView::OnViewPerspective() { CloseUVEditor(); view_mode = VIEW_PERSPECTIVE; SetupModelViews(); } void MagicView::OnUpdateViewPerspective(CCmdUI* pCmdUI) { if (pCmdUI) pCmdUI->SetCheck(view_mode == VIEW_PERSPECTIVE); } void MagicView::OnViewSide() { CloseUVEditor(); view_mode = VIEW_SIDE; SetupModelViews(); } void MagicView::OnUpdateViewSide(CCmdUI* pCmdUI) { if (pCmdUI) pCmdUI->SetCheck(view_mode == VIEW_SIDE); } void MagicView::OnViewTop() { CloseUVEditor(); view_mode = VIEW_TOP; SetupModelViews(); } void MagicView::OnUpdateViewTop(CCmdUI* pCmdUI) { if (pCmdUI) pCmdUI->SetCheck(view_mode == VIEW_TOP); } // +--------------------------------------------------------------------+ void MagicView::OnFileImport() { DWORD err = 0; char filename[256]; filename[0] = '\0'; CFileDialog ofd(TRUE, "mag"); ofd.m_ofn.lpstrFilter = "All 3D Files\0*.mag; *.obj; *.3ds\0Magic Files (*.mag)\0*.mag\0Wavefront/OBJ Files (*.obj)\0*.obj\0003DS MAX Files (*.3ds)\0*.3ds\0\0"; ofd.m_ofn.lpstrFile = filename; ofd.m_ofn.nMaxFile = sizeof(filename); if (ofd.DoModal() != IDOK) return; char mag_name[256]; sprintf_s(mag_name, "%s", ofd.GetFileName().GetBuffer(0)); MagicDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (pDoc->ImportFile(mag_name)) { Invalidate(); pDoc->SetModifiedFlag(TRUE); pDoc->UpdateAllViews(this); } } void MagicView::OnFileExport() { DWORD err = 0; char filename[256]; filename[0] = '\0'; CFileDialog ofd(FALSE, "mag"); ofd.m_ofn.lpstrFilter = "All 3D Files\0*.mag; *.obj; *.3ds\0Magic Files (*.mag)\0*.mag\0Wavefront/OBJ Files (*.obj)\0*.obj\0003DS MAX Files (*.3ds)\0*.3ds\0\0"; ofd.m_ofn.lpstrFile = filename; ofd.m_ofn.nMaxFile = sizeof(filename); if (ofd.DoModal() != IDOK) return; char mag_name[256]; sprintf_s(mag_name, "%s", ofd.GetFileName().GetBuffer(0)); MagicDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (pDoc->ExportFile(mag_name)) { pDoc->SetModifiedFlag(FALSE); pDoc->UpdateAllViews(this); } } // +--------------------------------------------------------------------+ void MagicView::OnSurfaceProperties() { SurfacePropertiesDialog dlg(this); dlg.DoModal(); } void MagicView::OnUpdateSurfaceProperties(CCmdUI* pCmdUI) { Solid* solid = GetDocument()->GetSolid(); pCmdUI->Enable(solid && solid->GetModel()); } // +--------------------------------------------------------------------+ void MagicView::OnTextureMap() { TextureMapDialog dlg(this); if (dlg.DoModal() == IDOK) { MagicDoc* doc = GetDocument(); Solid* solid = doc->GetSolid(); Selection* seln = doc->GetSelection(); Selector* selector = doc->GetSelector(); Editor* editor = doc->GetEditor(); Material* mtl = 0; if (dlg.mMaterialIndex >= 0) { mtl = solid->GetModel()->GetMaterials()[dlg.mMaterialIndex]; } editor->UseModel(solid->GetModel()); editor->ApplyMaterial(mtl, seln->GetPolys(), dlg.mMapType, 2-dlg.mAxis, (float) dlg.mScaleU, (float) dlg.mScaleV, dlg.mFlip, dlg.mMirror, dlg.mRotate); selector->Reselect(); Invalidate(); doc->SetModifiedFlag(TRUE); doc->UpdateAllViews(this); } } void MagicView::OnUpdateTextureMap(CCmdUI* pCmdUI) { Solid* solid = GetDocument()->GetSolid(); Selection* seln = GetDocument()->GetSelection(); pCmdUI->Enable(solid && solid->GetModel() && seln && seln->GetPolys().size() > 0); } void MagicView::OnModifyMaterial() { MaterialDialog dlg(this); dlg.DoModal(); Invalidate(); GetDocument()->SetModifiedFlag(TRUE); GetDocument()->UpdateAllViews(this); } void MagicView::OnUpdateModifyMaterial(CCmdUI* pCmdUI) { Solid* solid = GetDocument()->GetSolid(); pCmdUI->Enable(solid && solid->GetModel()); } void MagicView::OnModifyUVMap() { Selection* seln = GetDocument()->GetSelection(); view_mode = VIEW_UV_MAP; SetupModelViews(); if (seln && uvmap_view) { Poly* p = seln->GetPolys().first(); if (p) { uvmap_view->UseMaterial(p->material); uvmap_view->UsePolys(seln->GetPolys()); } } } void MagicView::OnUpdateModifyUVMap(CCmdUI* pCmdUI) { OnUpdateTextureMap(pCmdUI); } // +--------------------------------------------------------------------+ void MagicView::OnGridProperties() { GridProps dlg(grid, this); dlg.DoModal(); } void MagicView::OnGridShow() { if (grid) grid->SetShow(!grid->IsShow()); } void MagicView::OnGridSnap() { if (grid) grid->SetSnap(!grid->IsSnap()); } void MagicView::OnUpdateGridSnap(CCmdUI* pCmdUI) { if (grid) pCmdUI->SetCheck(grid->IsSnap()); } // +--------------------------------------------------------------------+ void MagicView::OnLButtonDown(UINT nFlags, CPoint point) { CView::OnLButtonDown(nFlags, point); SetCapture(); // set focus to the view that was clicked: int index = GetWinIndexByPoint(point.x, point.y); SetFocusModelView(index); drag_start = point; drag_left = true; drag_right = false; ModelView* mv = GetModelViewByIndex(index); MagicDoc* pDoc = GetDocument(); Model* model = pDoc->GetSolid()->GetModel(); Selector* selector = pDoc->GetSelector(); if (IsUVEdit()) { int select_mode = UVMapView::SELECT_APPEND; if (nFlags & MK_CONTROL) select_mode = UVMapView::SELECT_REMOVE; if (!uvmap_view->WillSelect(point)) { uvmap_view->Begin(select_mode); uvmap_view->AddMark(point); } } else if (mv && selector) { int select_mode = Selector::SELECT_APPEND; if (nFlags & MK_CONTROL) select_mode = Selector::SELECT_REMOVE; selector->Begin(model, mv->GetViewMode(), select_mode); selector->AddMark(point); } } void MagicView::OnLButtonUp(UINT nFlags, CPoint point) { CView::OnLButtonUp(nFlags, point); ReleaseCapture(); drag_left = false; MagicDoc* pDoc = GetDocument(); Selector* selector = pDoc->GetSelector(); if (IsUVEdit()) uvmap_view->End(); else if (selector && selector->IsActive()) selector->End(); } void MagicView::OnLButtonDblClk(UINT nFlags, CPoint point) { CView::OnLButtonDblClk(nFlags, point); drag_left = false; MagicDoc* pDoc = GetDocument(); Selector* selector = pDoc->GetSelector(); if (IsUVEdit()) uvmap_view->Clear(); else if (selector) selector->Clear(); } void MagicView::OnRButtonDown(UINT nFlags, CPoint point) { CView::OnRButtonDown(nFlags, point); SetCapture(); // set focus to the view that was clicked: int index = GetWinIndexByPoint(point.x, point.y); SetFocusModelView(index); drag_start = point; drag_left = false; drag_right = true; } void MagicView::OnRButtonUp(UINT nFlags, CPoint point) { CView::OnRButtonUp(nFlags, point); ReleaseCapture(); drag_right = false; } void MagicView::OnRButtonDblClk(UINT nFlags, CPoint point) { CView::OnRButtonDblClk(nFlags, point); ReleaseCapture(); drag_right = false; if (view_mode == VIEW_ALL) { view_mode = view_focus; } else if (IsUVEdit()) { CloseUVEditor(); view_mode = VIEW_ALL; SetupModelViews(); } else { view_mode = VIEW_ALL; } SetFocusModelView(view_focus); } void MagicView::OnMouseMove(UINT nFlags, CPoint point) { if (drag_right) { CPoint offset = point - drag_start; if (view_focus == VIEW_PERSPECTIVE) { ModelView* view = GetModelViewByIndex(view_focus); view->SpinBy(offset.x * 0.5 * DEGREES, offset.y * 0.5 * DEGREES); } else if (IsUVEdit()) { uvmap_view->MoveBy(offset.x, offset.y); } else { ModelView* view = GetModelViewByIndex(view_focus); view->MoveBy(offset.x, offset.y); } drag_start = point; Invalidate(); } else if (drag_left) { CPoint offset = point - drag_start; MagicDoc* pDoc = GetDocument(); Selector* selector = pDoc->GetSelector(); if (IsUVEdit()) { if (uvmap_view->IsActive()) { uvmap_view->AddMark(point); } else { uvmap_view->DragBy(offset.x, offset.y); drag_start = point; } } else if (selector && selector->IsActive()) { selector->AddMark(point); } } // xy status message: if (view_focus != VIEW_PERSPECTIVE) { char xy[80]; CPoint mouse = LPtoWP(point); Selection* seln = GetDocument()->GetSelection(); int nv = seln ? seln->GetVerts().size() : 0; int np = seln ? seln->GetPolys().size() : 0; if (np || nv) sprintf_s(xy, "(%05d,%05d) Verts:%d Polys:%d", mouse.x, mouse.y, nv, np); else sprintf_s(xy, "(%05d,%05d)", mouse.x, mouse.y); MainFrame::StatusXY(xy); } CView::OnMouseMove(nFlags, point); } BOOL MagicView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { if (view_focus == VIEW_PERSPECTIVE) { ModelView* view = GetModelViewByIndex(view_focus); if (view) { Camera* cam = view->GetCamera(); Point pos = cam->Pos(); double len = pos.length(); if (zDelta < 0) { if (len < 10000) pos *= 1.15; } else { if (len > 0.10) pos *= 0.85; } cam->MoveTo(pos); } } else if (IsUVEdit()) { if (zDelta < 0) { uvmap_view->ZoomOut(); } else { uvmap_view->ZoomIn(); } } else { if (zDelta > 0) OnViewZoomIn(); else OnViewZoomOut(); } return 0; } // +--------------------------------------------------------------------+ void MagicView::OnViewZoomNormal() { for (int i = 0; i < 4; i++) { ModelView* view = GetModelViewByIndex(i); if (view) { view->ZoomNormal(); } } } void MagicView::OnViewZoomIn() { for (int i = 0; i < 4; i++) { ModelView* view = GetModelViewByIndex(i); if (view && view->GetViewMode() != ModelView::VIEW_PROJECT) { double fov = view->GetFieldOfView() * 1.15; view->SetFieldOfView(fov); } } } void MagicView::OnViewZoomOut() { for (int i = 0; i < 4; i++) { ModelView* view = GetModelViewByIndex(i); if (view && view->GetViewMode() != ModelView::VIEW_PROJECT) { double fov = view->GetFieldOfView() * 0.85; view->SetFieldOfView(fov); } } } // +--------------------------------------------------------------------+ void MagicView::OnViewModeWireframe() { ModelView* view = GetModelViewByIndex(view_focus); if (view) { view->SetFillMode(ModelView::FILL_WIRE); } } void MagicView::OnViewModeSolid() { ModelView* view = GetModelViewByIndex(view_focus); if (view) { view->SetFillMode(ModelView::FILL_SOLID); } } void MagicView::OnViewModeTextured() { ModelView* view = GetModelViewByIndex(view_focus); if (view) { view->SetFillMode(ModelView::FILL_TEXTURE); } } void MagicView::OnViewBackColor() { ModelView* view = GetModelViewByIndex(view_focus); if (view) { ActiveWindow* win = (ActiveWindow*) view->GetWindow(); Color c = win->GetBackColor(); COLORREF crgb = RGB(c.Red(), c.Green(), c.Blue()); CColorDialog chooser(crgb); if (chooser.DoModal() == IDOK) { crgb = chooser.GetColor(); win->SetBackColor( Color(GetRValue(crgb), GetGValue(crgb), GetBValue(crgb)) ); } } } // +--------------------------------------------------------------------+ void MagicView::OnSelectAll() { Solid* solid = GetDocument()->GetSolid(); Selector* selector = GetDocument()->GetSelector(); if (IsUVEdit()) { uvmap_view->SelectAll(); } else if (solid && selector) { selector->UseModel(solid->GetModel()); selector->SelectAll(Selector::SELECT_APPEND); } } void MagicView::OnSelectNone() { Solid* solid = GetDocument()->GetSolid(); Selector* selector = GetDocument()->GetSelector(); if (IsUVEdit()) { uvmap_view->SelectNone(); } else if (solid && selector) { selector->UseModel(solid->GetModel()); selector->SelectAll(Selector::SELECT_REMOVE); } } void MagicView::OnSelectInverse() { Solid* solid = GetDocument()->GetSolid(); Selector* selector = GetDocument()->GetSelector(); if (IsUVEdit()) { uvmap_view->SelectInverse(); } else if (solid && selector) { selector->UseModel(solid->GetModel()); selector->SelectInverse(); } } void MagicView::OnViewShadows() { view_shadows = !view_shadows; if (video) video->SetShadowEnabled(view_shadows); } void MagicView::OnUpdateViewShadows(CCmdUI* pCmdUI) { pCmdUI->SetCheck(view_shadows); } void MagicView::OnViewAnimatelight() { animate_light = !animate_light; } void MagicView::OnUpdateViewAnimatelight(CCmdUI* pCmdUI) { pCmdUI->SetCheck(animate_light); } void MagicView::OnViewBumpmaps() { view_bumpmaps = !view_bumpmaps; if (video) video->SetBumpMapEnabled(view_bumpmaps); } void MagicView::OnUpdateViewBumpmaps(CCmdUI* pCmdUI) { pCmdUI->SetCheck(view_bumpmaps); } void MagicView::OnViewVertexshader() { if (video) { VideoSettings* vs = (VideoSettings*) video->GetVideoSettings(); vs->enable_vs = !vs->enable_vs; } } void MagicView::OnUpdateViewVertexshader(CCmdUI* pCmdUI) { if (video) pCmdUI->SetCheck(video->GetVideoSettings()->enable_vs); } void MagicView::OnViewPixelshader() { if (video) { VideoSettings* vs = (VideoSettings*) video->GetVideoSettings(); vs->enable_ps = !vs->enable_ps; } } void MagicView::OnUpdateViewPixelshader(CCmdUI* pCmdUI) { if (video) pCmdUI->SetCheck(video->GetVideoSettings()->enable_ps); } void MagicView::OnViewVisibleshadows() { Shadow::SetVisibleShadowVolumes(!Shadow::GetVisibleShadowVolumes()); } void MagicView::OnUpdateViewVisibleshadows(CCmdUI* pCmdUI) { pCmdUI->SetCheck(Shadow::GetVisibleShadowVolumes()); } void MagicView::OnEditUndo() { MagicDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->Undo(); Solid* solid = GetDocument()->GetSolid(); Selector* selector = GetDocument()->GetSelector(); if (selector) { selector->UseModel(solid->GetModel()); selector->Reselect(); } Invalidate(); pDoc->SetModifiedFlag(TRUE); pDoc->UpdateAllViews(this); } void MagicView::OnUpdateEditUndo(CCmdUI* pCmdUI) { MagicDoc* pDoc = GetDocument(); if (pDoc->NumUndo() > 0) { pCmdUI->Enable(TRUE); pCmdUI->SetText(CString("Undo ") + pDoc->GetUndoName() + CString("\tCtrl+Z")); } else { pCmdUI->Enable(FALSE); pCmdUI->SetText("Can't Undo\tCtrl+Z"); } } void MagicView::OnEditRedo() { MagicDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->Redo(); Solid* solid = GetDocument()->GetSolid(); Selector* selector = GetDocument()->GetSelector(); if (selector) { selector->UseModel(solid->GetModel()); selector->Reselect(); } Invalidate(); pDoc->SetModifiedFlag(TRUE); pDoc->UpdateAllViews(this); } void MagicView::OnUpdateEditRedo(CCmdUI* pCmdUI) { MagicDoc* pDoc = GetDocument(); if (pDoc->NumRedo() > 0) { pCmdUI->Enable(TRUE); pCmdUI->SetText(CString("Redo ") + pDoc->GetRedoName() + CString("\tCtrl+Y")); } else { pCmdUI->Enable(FALSE); pCmdUI->SetText("Can't Redo"); } }