//-----------------------------------------------------------------------------
// File: $$BLANK$$.cpp
//
// Desc: $$BLANK$$ screen saver
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include <windows.h>
#include <d3d8.h>
#include <d3dx8.h>
#include <stdio.h>
#include <commdlg.h>
#include <commctrl.h>
#include "d3dsaver.h"
#include "d3dfont.h"
#include "$$BLANK$$.h"
#include "Resource.h"
#include "dxutil.h"


//-----------------------------------------------------------------------------
// Name: struct MYVERTEX
// Desc: D3D vertex type for this app
//-----------------------------------------------------------------------------
struct MYVERTEX
{
    D3DXVECTOR3 p;     // Position
    FLOAT       tu;    // Vertex texture coordinates
    FLOAT       tv;
    
    MYVERTEX(D3DXVECTOR3 pInit, FLOAT tuInit, FLOAT tvInit)
        { p = pInit; tu = tuInit; tv = tvInit; }
};

#define D3DFVF_MYVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)



C$$BLANK$$Screensaver* g_pMy$$BLANK$$Screensaver = NULL;




//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
//       message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    HRESULT hr;
    C$$BLANK$$Screensaver saver;

    if( FAILED( hr = saver.Create( hInst ) ) )
    {
        saver.DisplayErrorMsg( hr );
        return 0;
    }

    return saver.Run();
}




//-----------------------------------------------------------------------------
// Name: C$$BLANK$$Screensaver()
// Desc: Constructor
//-----------------------------------------------------------------------------
C$$BLANK$$Screensaver::C$$BLANK$$Screensaver( )
    // TODO: screen saver member data initialization
{
    g_pMy$$BLANK$$Screensaver = this;

    InitCommonControls();

    ZeroMemory( m_DeviceObjectsArray, sizeof(m_DeviceObjectsArray) );

    srand(0);

    // TODO: Change Pahvant\\rt_Apprentice to your company name
    lstrcpy( m_strRegPath, TEXT("Software\\Pahvant\\rt_Apprentice\\Screensavers\\$$BLANK$$") );
    LoadString( NULL, IDS_DESCRIPTION, m_strWindowTitle, 200 );

    // TODO: screen saver member data initialization
}




//-----------------------------------------------------------------------------
// Name: SetDevice()
// Desc: 
//-----------------------------------------------------------------------------
VOID C$$BLANK$$Screensaver::SetDevice( UINT iDevice )
{
    m_pDeviceObjects = &m_DeviceObjectsArray[iDevice];
}




//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
//       the scene.
//-----------------------------------------------------------------------------
HRESULT C$$BLANK$$Screensaver::FrameMove()
{
    // TODO: move objects in scene

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
//       rendering. This function sets up render states, clears the
//       viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT C$$BLANK$$Screensaver::Render()
{
    // Clear the viewport
    m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255),
        1.0f, 0L );

    // Begin the scene 
    if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
    {
        // TODO: draw scene

        // Show frame rate
        m_pDeviceObjects->m_pStatsFont->DrawText( 3,  1, D3DCOLOR_ARGB(255,0,0,0), m_strFrameStats );
        m_pDeviceObjects->m_pStatsFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );

        m_pDeviceObjects->m_pStatsFont->DrawText( 3, 21, D3DCOLOR_ARGB(255,0,0,0), m_strDeviceStats );
        m_pDeviceObjects->m_pStatsFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );

        // End the scene.
        m_pd3dDevice->EndScene();
    }

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc: 
//-----------------------------------------------------------------------------
HRESULT C$$BLANK$$Screensaver::RestoreDeviceObjects()
{
    if( m_pd3dDevice == NULL )
        return S_OK;
    
    // Set up sensible projection and view matrices
    D3DXMATRIX  view;
    D3DXMatrixLookAtLH( &view , &D3DXVECTOR3(0,0,-10) , &D3DXVECTOR3(0,0,0) , &D3DXVECTOR3(0,1,0) );
    m_pd3dDevice->SetTransform( D3DTS_VIEW , &view );

    // Set some basic renderstates
    m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE , TRUE );
    m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE , FALSE );

    m_pDeviceObjects->m_pStatsFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
    m_pDeviceObjects->m_pStatsFont->InitDeviceObjects( m_pd3dDevice );
    m_pDeviceObjects->m_pStatsFont->RestoreDeviceObjects();

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc: 
//-----------------------------------------------------------------------------
HRESULT C$$BLANK$$Screensaver::InvalidateDeviceObjects()
{
    m_pDeviceObjects->m_pStatsFont->InvalidateDeviceObjects();
    m_pDeviceObjects->m_pStatsFont->DeleteDeviceObjects();
    SAFE_DELETE( m_pDeviceObjects->m_pStatsFont );

    // TODO: destroy application device objects

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: ReadSettings()
// Desc: 
//-----------------------------------------------------------------------------
VOID C$$BLANK$$Screensaver::ReadSettings()
{
    ReadRegistry();
}




//-----------------------------------------------------------------------------
// Name: ConfigureDialogProcHelper()
// Desc: 
//-----------------------------------------------------------------------------
INT_PTR CALLBACK ConfigureDialogProcHelper( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    return g_pMy$$BLANK$$Screensaver->ConfigureDialogProc( hwndDlg, uMsg, wParam, lParam );
}




//-----------------------------------------------------------------------------
// Name: DoConfig()
// Desc: 
//-----------------------------------------------------------------------------
VOID C$$BLANK$$Screensaver::DoConfig()
{
    DialogBox( NULL, MAKEINTRESOURCE(IDD_CONFIGURE), m_hWndParent, ConfigureDialogProcHelper );
}




//-----------------------------------------------------------------------------
// Name: ConfigureDialogProc()
// Desc: 
//-----------------------------------------------------------------------------
INT_PTR CALLBACK C$$BLANK$$Screensaver::ConfigureDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        WriteRegistry();
        return TRUE;

    case WM_COMMAND:
        switch( LOWORD( wParam ) )
        {
        case IDC_SCREENSETTINGS:
            DoScreenSettingsDialog( hwndDlg );
            break;

        case IDOK:
            WriteRegistry(); // save new settings
            EndDialog(hwndDlg, IDOK);
            break;

        case IDCANCEL:
            ReadRegistry(); // restore previous settings
            EndDialog(hwndDlg, IDCANCEL);
            break;
        }
        return TRUE;
    
    default:
        return FALSE;
    }
}




//-----------------------------------------------------------------------------
// Name: ReadRegistry()
// Desc: 
//-----------------------------------------------------------------------------
HRESULT C$$BLANK$$Screensaver::ReadRegistry()
{
    HKEY hkey;
    DWORD dwType = REG_DWORD;
    DWORD dwLength = sizeof(DWORD);

    if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath, 
        0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
    {
        // TODO: read screensaver specific settings

        ReadScreenSettings( hkey );

        RegCloseKey( hkey );
    }

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: WriteRegistry()
// Desc: 
//-----------------------------------------------------------------------------
HRESULT C$$BLANK$$Screensaver::WriteRegistry()
{
    HKEY hkey;

    if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath, 
        0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
    {
        // TODO: write screensaver specific settings
        WriteScreenSettings( hkey );

        RegCloseKey( hkey );
    }

    return S_OK;
}
