// TerrainLighting.cpp : implementation file // #include "stdafx.h" #include "TerrainLighting.h" #include "CryEditDoc.h" #include "TerrainTexture.h" #include "Heightmap.h" #include "WaitProgress.h" #include "GameEngine.h" #include "resource.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define LIGHTING_PREVIEW_RESOLUTION 256 ///////////////////////////////////////////////////////////////////////////// // CTerrainLighting dialog CTerrainLighting::CTerrainLighting(CWnd* pParent /*=NULL*/) : CDialog(CTerrainLighting::IDD, pParent), m_texGen(LIGHTING_PREVIEW_RESOLUTION) { //{{AFX_DATA_INIT(CTerrainLighting) m_sldAmbient = 0; m_optLightingAlgo = -1; m_sldSunDirection = 0; m_sldSunHeight = 0; m_bTerrainShadows = FALSE; m_bObjectShadows = FALSE; m_bTextured = FALSE; m_sldShadowIntensity = 0; m_sldShadowBlur=0; m_sldSkyQuality=0; //}}AFX_DATA_INIT m_bDraggingSunDirection = false; } CTerrainLighting::~CTerrainLighting() { } void CTerrainLighting::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CTerrainLighting) DDX_Slider(pDX, IDC_AMBIENT, m_sldAmbient); DDX_Radio(pDX, IDC_HEMISPHERE, m_optLightingAlgo); DDX_Slider(pDX, IDC_SUN_DIRECTION, m_sldSunDirection); DDX_Slider(pDX, IDC_SUN_HEIGHT, m_sldSunHeight); DDX_Check(pDX, IDC_TERRAINSHADOWS, m_bTerrainShadows); DDX_Check(pDX, IDC_OBJECTSHADOWS, m_bObjectShadows); DDX_Check(pDX, IDC_TEXTURED,m_bTextured ); DDX_Slider(pDX, IDC_SHADOW_INTENSITY, m_sldShadowIntensity); DDX_Slider(pDX, IDC_SHADOW_BLUR, m_sldShadowBlur); DDX_Slider(pDX, IDC_HEMISAMPLEQ, m_sldSkyQuality); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CTerrainLighting, CDialog) //{{AFX_MSG_MAP(CTerrainLighting) ON_WM_PAINT() ON_BN_CLICKED(IDC_GENERATE, OnGenerate) ON_WM_HSCROLL() ON_BN_CLICKED(IDC_TERRAINSHADOWS, OnTerrainShadows) ON_BN_CLICKED(IDC_OBJECTSHADOWS, OnObjectShadows) ON_COMMAND(ID_FILE_EXPORT, OnFileExport) ON_COMMAND(ID_FILE_IMPORT, OnFileImport) ON_BN_CLICKED(IDC_VIEW_WITH_TEXTURING, OnViewWithTexturing) ON_BN_CLICKED(IDC_SUN_COLOR, OnSunColor) ON_BN_CLICKED(IDC_SKY_COLOR, OnSkyColor) ON_BN_CLICKED(IDC_HEMISPHERE, OnHemisphere) ON_BN_CLICKED(IDC_DP3, OnDp3) ON_EN_UPDATE(IDC_SUNCOLOR_SCALE,OnSunMultiplier) //}}AFX_MSG_MAP ON_WM_MOUSEMOVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_BN_CLICKED(IDC_TEXTURED, OnBnClickedTextured) ON_BN_CLICKED(IDC_PRECISELIGHTING2, OnBnClickedPreciselighting2) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTerrainLighting message handlers void CTerrainLighting::OnPaint() { CPaintDC dc(this); // device context for painting RECT rcClient; CPen cGrayPen(PS_SOLID, 1, 0x007F7F7F); CPen cWhitePen(PS_SOLID, 1, 0x00FFFFFF); CPen cRedPen(PS_SOLID, 1, 0x000000FF); // Generate a preview if we don't have one if (!m_dcLightmap.m_hDC) OnGenerate(); // Draw the preview of the lightmap dc.BitBlt(19, 24, LIGHTING_PREVIEW_RESOLUTION, LIGHTING_PREVIEW_RESOLUTION, &m_dcLightmap, 0, 0, SRCCOPY); CRect rc(19,24,19+LIGHTING_PREVIEW_RESOLUTION,24+LIGHTING_PREVIEW_RESOLUTION); // Draw Sun direction. CPen *prevPen = dc.SelectObject(&cRedPen); CPoint center = rc.CenterPoint(); Vec3 sunVector = GetIEditor()->GetDocument()->GetLighting()->GetSunVector(); sunVector.z = 0; sunVector.Normalize(); CPoint source = center + CPoint(-sunVector.x*120,-sunVector.y*120); dc.MoveTo( center ); dc.LineTo( source ); // Draw a menu bar separator GetClientRect(&rcClient); dc.SelectObject(&cGrayPen); dc.MoveTo(0, 0); dc.LineTo(rcClient.right, 0); dc.SelectObject(&cWhitePen); dc.MoveTo(0, 1); dc.LineTo(rcClient.right, 1); dc.SelectObject(prevPen); // Do not call CDialog::OnPaint() for painting messages } void CTerrainLighting::OnGenerate() { //////////////////////////////////////////////////////////////////////// // Generate a preview of the lightmap //////////////////////////////////////////////////////////////////////// RECT rcUpdate; BeginWaitCursor(); // Create a DC and a bitmap if (!m_dcLightmap.m_hDC) VERIFY(m_dcLightmap.CreateCompatibleDC(NULL)); if (!m_bmpLightmap.m_hObject) VERIFY(m_bmpLightmap.CreateBitmap(LIGHTING_PREVIEW_RESOLUTION, LIGHTING_PREVIEW_RESOLUTION, 1, 32, NULL)); m_dcLightmap.SelectObject(&m_bmpLightmap); // Calculate the lighting. m_texGen.InvalidateLighting(); if (m_bTextured) m_texGen.GenerateSurfaceTexture( ETTG_LIGHTING|ETTG_QUIET|ETTG_ABGR|ETTG_INVALIDATE_LAYERS,m_lightmap ); else m_texGen.GenerateSurfaceTexture( ETTG_LIGHTING|ETTG_NOTEXTURE|ETTG_QUIET|ETTG_ABGR|ETTG_INVALIDATE_LAYERS,m_lightmap ); m_bmpLightmap.SetBitmapBits( m_lightmap.GetSize(),(DWORD*)m_lightmap.GetData() ); // Update the preview ::SetRect(&rcUpdate, 10, 10, 20 + LIGHTING_PREVIEW_RESOLUTION, 30 + LIGHTING_PREVIEW_RESOLUTION); InvalidateRect(&rcUpdate, FALSE); UpdateWindow(); EndWaitCursor(); } BOOL CTerrainLighting::OnInitDialog() { //////////////////////////////////////////////////////////////////////// // Initialize the dialog with the settings from the document //////////////////////////////////////////////////////////////////////// m_originalLightSettings = *GetIEditor()->GetDocument()->GetLighting(); CSliderCtrl ctrlSlider; CLogFile::WriteLine("Loading lighting dialog..."); CDialog::OnInitDialog(); // Set the ranges for the slider controls VERIFY(ctrlSlider.Attach(GetDlgItem(IDC_SUN_DIRECTION)->m_hWnd)); ctrlSlider.SetRange(0, 360, TRUE); ctrlSlider.Detach(); VERIFY(ctrlSlider.Attach(GetDlgItem(IDC_SUN_HEIGHT)->m_hWnd)); ctrlSlider.SetRange(0, 100, TRUE); ctrlSlider.Detach(); VERIFY(ctrlSlider.Attach(GetDlgItem(IDC_SHADOW_BLUR)->m_hWnd)); ctrlSlider.SetRange(0, 100, TRUE); ctrlSlider.Detach(); VERIFY(ctrlSlider.Attach(GetDlgItem(IDC_SHADOW_INTENSITY)->m_hWnd)); ctrlSlider.SetRange(0, 100, TRUE); ctrlSlider.Detach(); VERIFY(ctrlSlider.Attach(GetDlgItem(IDC_AMBIENT)->m_hWnd)); ctrlSlider.SetRange(0, 255, TRUE); ctrlSlider.Detach(); VERIFY(ctrlSlider.Attach(GetDlgItem(IDC_HEMISAMPLEQ)->m_hWnd)); ctrlSlider.SetRange(0, 10, TRUE); ctrlSlider.Detach(); m_sunMult.Create( this,IDC_SUNCOLOR_SCALE ); m_lightmap.Allocate( LIGHTING_PREVIEW_RESOLUTION,LIGHTING_PREVIEW_RESOLUTION ); m_bDraggingSunDirection = false; // Synchronize the controls with the values from the document UpdateControls(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CTerrainLighting::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { //////////////////////////////////////////////////////////////////////// // Update the document with the values from the sliders //////////////////////////////////////////////////////////////////////// UpdateData(TRUE); LightingSettings *ls = GetIEditor()->GetDocument()->GetLighting(); ls->iAmbient = m_sldAmbient; ls->iSunRotation = m_sldSunDirection; ls->iSunHeight = m_sldSunHeight; ls->iShadowIntensity = m_sldShadowIntensity; ls->iShadowBlur=m_sldShadowBlur; ls->iHemiSamplQuality = m_sldSkyQuality; // We modified the document GetIEditor()->SetModifiedFlag(); // Update the preview OnGenerate(); CDialog::OnHScroll(nSBCode, nPos, pScrollBar); } void CTerrainLighting::OnSunMultiplier() { GetIEditor()->GetDocument()->GetLighting()->sunMultiplier = m_sunMult.GetValue(); // We modified the document GetIEditor()->SetModifiedFlag(); OnGenerate(); } void CTerrainLighting::OnTerrainShadows() { //////////////////////////////////////////////////////////////////////// // Synchronize value in the document //////////////////////////////////////////////////////////////////////// UpdateData(TRUE); GetIEditor()->GetDocument()->GetLighting()->bTerrainShadows = m_bTerrainShadows; // We modified the document GetIEditor()->SetModifiedFlag(); // Update the preview OnGenerate(); } void CTerrainLighting::OnObjectShadows() { //////////////////////////////////////////////////////////////////////// // Synchronize value in the document //////////////////////////////////////////////////////////////////////// UpdateData(TRUE); GetIEditor()->GetDocument()->GetLighting()->bObjectShadows = m_bObjectShadows; // We modified the document GetIEditor()->SetModifiedFlag(); // Update the preview OnGenerate(); } void CTerrainLighting::OnFileExport() { //////////////////////////////////////////////////////////////////////// // Export the lighting settings //////////////////////////////////////////////////////////////////////// char szFilters[] = "Light Settings (*.lgt)|*.lgt||"; CString fileName; if (CFileUtil::SelectSaveFile( szFilters,"lgt",GetIEditor()->GetLevelFolder(),fileName )) { CLogFile::WriteLine("Exporting light settings..."); // Write the light settings into the archive XmlNodeRef node = new CXmlNode( "LightSettings" ); GetIEditor()->GetDocument()->GetLighting()->Serialize( node,false ); node->saveToFile( fileName ); } } void CTerrainLighting::OnFileImport() { //////////////////////////////////////////////////////////////////////// // Import the lighting settings //////////////////////////////////////////////////////////////////////// char szFilters[] = "Light Settings (*.lgt)|*.lgt||"; CString fileName; if (CFileUtil::SelectFile( szFilters,GetIEditor()->GetLevelFolder(),fileName )) { CLogFile::WriteLine("Importing light settings..."); XmlParser parser; XmlNodeRef node = parser.parse( fileName ); GetIEditor()->GetDocument()->GetLighting()->Serialize( node,true ); // We modified the document GetIEditor()->SetModifiedFlag(); // Update the controls with the settings from the document UpdateControls(); // Update the preview OnGenerate(); } } void CTerrainLighting::UpdateControls() { //////////////////////////////////////////////////////////////////////// // Update the controls with the settings from the document //////////////////////////////////////////////////////////////////////// LightingSettings *ls = GetIEditor()->GetDocument()->GetLighting(); m_sldAmbient = ls->iAmbient; m_bTerrainShadows = ls->bTerrainShadows; m_bObjectShadows = ls->bObjectShadows; m_optLightingAlgo = ls->eAlgo; m_sldSunDirection = ls->iSunRotation; m_sldSunHeight = ls->iSunHeight; m_sldShadowIntensity = ls->iShadowIntensity; m_sldShadowBlur=ls->iShadowBlur; m_sldSkyQuality = ls->iHemiSamplQuality; m_sunMult.SetValue( ls->sunMultiplier ); switch (ls->eAlgo) { case eDP3: GetDlgItem(IDC_HEMISAMPLEQ)->EnableWindow(FALSE); GetDlgItem(IDC_SKY_COLOR)->EnableWindow(FALSE); GetDlgItem(IDC_AMBIENT)->EnableWindow(TRUE); break; case eHemisphere: GetDlgItem(IDC_HEMISAMPLEQ)->EnableWindow(FALSE); GetDlgItem(IDC_SKY_COLOR)->EnableWindow(TRUE); GetDlgItem(IDC_AMBIENT)->EnableWindow(FALSE); break; case ePrecise: GetDlgItem(IDC_HEMISAMPLEQ)->EnableWindow(TRUE); GetDlgItem(IDC_SKY_COLOR)->EnableWindow(TRUE); GetDlgItem(IDC_AMBIENT)->EnableWindow(FALSE); break; default: assert(0); } UpdateData(FALSE); } void CTerrainLighting::OnViewWithTexturing() { //////////////////////////////////////////////////////////////////////// // Show a textured preview //////////////////////////////////////////////////////////////////////// CTerrainTexture cTexture; cTexture.ExportLargePreview(); } void CTerrainLighting::OnSunColor() { //////////////////////////////////////////////////////////////////////// // Let the user choose a new sun color //////////////////////////////////////////////////////////////////////// CCryEditDoc *doc = GetIEditor()->GetDocument(); // Color selection dialog box COLORREF color = doc->GetLighting()->dwSunColor; if (GetIEditor()->SelectColor( color,this )) { // Save the new color value in the document doc->GetLighting()->dwSunColor = color; // We modified the document GetIEditor()->SetModifiedFlag(); // Update the preview OnGenerate(); } } void CTerrainLighting::OnSkyColor() { //////////////////////////////////////////////////////////////////////// // Let the user choose a new sky color //////////////////////////////////////////////////////////////////////// CCryEditDoc *doc = GetIEditor()->GetDocument(); // Color selection dialog box COLORREF color = doc->GetLighting()->dwSkyColor; if (GetIEditor()->SelectColor( color,this )) { // Save the new color value in the document doc->GetLighting()->dwSkyColor = color; // We modified the document GetIEditor()->SetModifiedFlag(); // Update the preview OnGenerate(); } } void CTerrainLighting::OnHemisphere() { GetIEditor()->GetDocument()->GetLighting()->eAlgo = eHemisphere; GetIEditor()->SetModifiedFlag(); UpdateControls(); OnGenerate(); } void CTerrainLighting::OnDp3() { GetIEditor()->GetDocument()->GetLighting()->eAlgo = eDP3; GetIEditor()->SetModifiedFlag(); UpdateControls(); OnGenerate(); } void CTerrainLighting::OnBnClickedPreciselighting2() { GetIEditor()->GetDocument()->GetLighting()->eAlgo = ePrecise; GetIEditor()->SetModifiedFlag(); UpdateControls(); OnGenerate(); } BOOL CTerrainLighting::DestroyWindow() { return CDialog::DestroyWindow(); } ////////////////////////////////////////////////////////////////////////// void CTerrainLighting::OnMouseMove(UINT nFlags, CPoint point) { if (m_bDraggingSunDirection) { LightingSettings *ls = GetIEditor()->GetDocument()->GetLighting(); CRect rcImage(19,24,19+LIGHTING_PREVIEW_RESOLUTION,24+LIGHTING_PREVIEW_RESOLUTION); CPoint center = rcImage.CenterPoint(); Vec3 dir = Vec3(point.x - center.x,point.y-center.y,0 ); dir.Normalize(); Vec3 horizont = Vec3(0,-1,0); float cosa = dir.Dot(horizont); float alpha = RAD2DEG(acos(cosa)); if (point.x > center.x) alpha = 360-alpha; ls->iSunRotation = alpha; UpdateControls(); // Update the preview //::SetRect(&rcUpdate, 10, 10, 20 + LIGHTING_PREVIEW_RESOLUTION, 30 + LIGHTING_PREVIEW_RESOLUTION); InvalidateRect( &rcImage, FALSE); } CDialog::OnMouseMove(nFlags, point); } ////////////////////////////////////////////////////////////////////////// void CTerrainLighting::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CRect rcImage(19,24,19+LIGHTING_PREVIEW_RESOLUTION,24+LIGHTING_PREVIEW_RESOLUTION); if (rcImage.PtInRect(point)) { m_bDraggingSunDirection = true; } CDialog::OnLButtonDown(nFlags, point); } ////////////////////////////////////////////////////////////////////////// void CTerrainLighting::OnLButtonUp(UINT nFlags, CPoint point) { if (m_bDraggingSunDirection) { m_bDraggingSunDirection = false; OnGenerate(); } CDialog::OnLButtonUp(nFlags, point); } ////////////////////////////////////////////////////////////////////////// void CTerrainLighting::OnBnClickedTextured() { UpdateData(TRUE); OnGenerate(); } void CTerrainLighting::OnOK() { CDialog::OnOK(); CWaitCursor wait; // When exiting lighting dialog. GetIEditor()->GetGameEngine()->ReloadEnvironment(); } void CTerrainLighting::OnCancel() { LightingSettings *ls = GetIEditor()->GetDocument()->GetLighting(); *ls = m_originalLightSettings; CDialog::OnCancel(); }