// ShaderEditorDlg.cpp : implementation file // #include "stdafx.h" #include "ShaderEditor.h" #include "ShaderEditorDlg.h" #include "ShaderEditorToolbarDlg.h" #include "MultiParamEditDlg.h" #include "VIGDIManager.h" #include "resvis.h" #include "VIFindReplaceDlg.h" #include "ShaderEditorFileDialog.h" #include "CKHideContentManager.h" #define IDI_FILEBEHAVIOR 538 using namespace CKControl; #ifdef _MFCDEBUGNEW #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #endif //------------------------------- //DIALOG CREATION FUNC FOR EXPORT DllEditorDlg* fCreateEditorDlg(HWND parent/*, CKContext* ctx*/) { ShaderEditorDlg* dlg; HRESULT r = CreateDllDialog(parent,IDD_SHADEREDITOR,&dlg); return (DllEditorDlg*)dlg; } //DIALOG CREATION FUNC FOR EXPORT //------------------------------- #include "shlwapi.h" void OnCannotOpenFile(XString filePath) { CString f = filePath.CStr(); if (PathFileExists(f)) { XString text; XString title; title = "Virtools Dev"; text.Format("Cannot create the %s file\nMake sure that the path and filename are correct.",(LPCTSTR)f); VIMessageDlg dlg(text.Str(),title.Str(),VIMessageDlg::VIMM_OK,VIMessageDlg::VIMI_ERROR); dlg.DoModal(); } else { char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath( LPCSTR(f), drive, dir, fname, ext ); XString text; XString title; title = "Open"; text.Format("%s\nFileNotFound\nPlease verify the correct file name was given.",fname); VIMessageDlg dlg(text.Str(),title.Str(),VIMessageDlg::VIMM_OK,VIMessageDlg::VIMI_ERROR); dlg.DoModal(); //dlg.SetCustomButtons("Close"); //dlg.ShowCustomButtons(TRUE,FALSE,FALSE); } } ///////////////////////////////////////////////////////////////////////////// // ShaderEditorDlg dialog ShaderEditorDlg::ShaderEditorDlg(CWnd* pParent /*=NULL*/) : DllEditorDlg(ShaderEditorDlg::IDD, pParent), m_CurrOutput(0), m_SplitMain(3, 1), m_SplitEditorError(1, 2), m_SplitTechsParams(1, 2), m_SplitEditorTitle(2, 2), m_currentShaderListed(-1), m_ShaderManager(NULL) { //{{AFX_DATA_INIT(ShaderEditorDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT m_ImageList=NULL; } void ShaderEditorDlg::DoDataExchange(CDataExchange* pDX) { DllEditorDlg::DoDataExchange(pDX); //{{AFX_DATA_MAP(ShaderEditorDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(ShaderEditorDlg, DllEditorDlg) //{{AFX_MSG_MAP(ShaderEditorDlg) ON_NOTIFY(TVN_SELCHANGED, IDC_SHADER_TREE, OnSelchangedShaderTree) ON_LBN_SELCHANGE(IDC_ERROR_LIST, OnSelchangeErrorList) ON_NOTIFY(TVN_ENDLABELEDIT, IDC_SHADER_TREE, OnEndlabeleditShaderTree) ON_NOTIFY(NM_DBLCLK, IDC_SHADER_TREE, OnDblclkShaderTree) ON_NOTIFY(NM_RCLICK, IDC_SHADER_TREE, OnRightClkShaderTree) ON_NOTIFY(NM_KEYDOWN, IDC_SHADER_TREE, OnKeydownShaderTree) ON_NOTIFY(WM_KEYDOWN, IDC_EDITOR, OnKeydownEditor) ON_WM_SIZE() ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // ShaderEditorDlg message handlers //----------------------------------------------------------------------------- char* ShaderEditorDlg::_Newstrdup(const XString& s) const { char* text = new char[s.Length() + 1]; return strcpy(text, s.CStr()); } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnInterfaceInit() { m_ShaderManager = (CKShaderManager*)GetCKContext()->GetManagerByGuid(ShaderManagerGUID); if( !m_ShaderManager ) return; //--- Create Default Shader Fx when the Shader Fx editor opens for the first time ///// and if there was no Default Shader Fx created yet. ///// note GetDefaultShader() automatically creates Default Shader Fx if needed. m_ShaderManager->GetDefaultShader(); // Idem for built-in shadows // TMP TMP //m_ShaderManager->GetShadowShader(); m_Toolbar = (ShaderEditorToolbarDlg*)m_ToolbarDlg; m_Shader = NULL; m_ShaderType = m_ShaderManager->GetCurrentShaderManagerType(); m_PreviousShaderType = m_ShaderType ; if (m_ShaderType == CKSM_HLSL) m_Toolbar->m_StaticTextShaderCplMode.SetWindowText("HLSL"); else m_Toolbar->m_StaticTextShaderCplMode.SetWindowText("CgFX"); _SetupSplitters(); _SetupEditor(); _SetupCompiledOutput(); _SetupOutput(); _SetupShaderTree(); _SetupTechniqueTree(); _SetupParameterTree(); // General configuration UpdateShaderManager(); // Register notifications ObserveNotification(CUIK_NOTIFICATION_PRESAVELEVEL); ObserveNotification(CUIK_NOTIFICATION_PRECLEARALL); ObserveNotification(CUIK_NOTIFICATION_POSTCLEARALL); ObserveNotification(CUIK_NOTIFICATION_LEVEL_LOADED); ObserveNotification(CUIK_NOTIFICATION_CKFILELOADED); ObserveNotification(CUIK_NOTIFICATION_RENDERDEVICECHANGED); ObserveNotification(CUIK_NOTIFICATION_WANTTOSEESHADER); ObserveNotification(CUIK_NOTIFICATION_SEQUENCEADDEDTOSCENE); ObserveNotification(CUIK_NOTIFICATION_REWIND); } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnInterfaceEnd() { m_Editor.SetMarkImageList(NULL); if(m_ImageList) { m_ImageList->DeleteImageList(); delete m_ImageList; } m_ShaderTree.DestroyWindow(); m_ParameterTree.DestroyWindow(); m_TechniqueTree.DestroyWindow(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::UpdateWindowText(const char* shaderSrc) { if(m_Editor) { if(strstr(shaderSrc, CKHideContentManager::GetTag())) { m_Editor.SetWindowText("Please contact the Author if you want to get full access to this shader."); } else { m_Editor.SetWindowText(shaderSrc); } } } HRESULT ShaderEditorDlg::ReceiveNotification(UINT MsgID,DWORD Param1/* =0 */,DWORD Param2/* =0 */,CKScene* Context/* =NULL */) { switch( MsgID ){ case CUIK_NOTIFICATION_PRESAVELEVEL: UpdateShaderText(); break; case CUIK_NOTIFICATION_PRECLEARALL: { SetCurrentShader(NULL); m_esiHash.Clear(); } break; case CUIK_NOTIFICATION_POSTCLEARALL: //--- Create Default Shader Fx when the Shader Fx editor opens for the first time ///// and if there was no Default Shader Fx created yet. ///// note GetDefaultShader() automatically creates Default Shader Fx if needed. m_ShaderManager->GetDefaultShader(); UpdateShaderManager(); m_currentShaderListed = -1; break; case CUIK_NOTIFICATION_CKFILELOADED: //--- called on merging //--- Compare text in current rich edit with text inside shader ///// If it has changed due to loading, then force rich edit update { if( !m_Shader ) break; //--- Retrieve rich edit text VxScratchString buffer; int strlen = m_Editor.GetWindowTextLength()+1; buffer->Reserve(strlen); char *bufferStr = buffer->Str(); m_Editor.GetWindowText(bufferStr, strlen); if( m_Shader->GetText().Compare( *buffer ) ){ m_Editor.ClearUndo(); UpdateWindowText(m_Shader->GetText().CStr()); _UpdateTechniqueTree(); _UpdateParameterTree(); //--- Tells application composition has been modified GetInterface()->SetProjectModified( TRUE ); } } case CUIK_NOTIFICATION_LEVEL_LOADED: //--- called after clear all case CUIK_NOTIFICATION_SEQUENCEADDEDTOSCENE: case CUIK_NOTIFICATION_REWIND: UpdateShaderList(); break; case CUIK_NOTIFICATION_RENDERDEVICECHANGED: if( !m_Shader ) break; SetCurrentShader( m_Shader ); UpdateShaderList(); EnableWindowTextIfShaderShadersIsSupported(); if ( m_ShaderType != m_PreviousShaderType ) { if (m_ShaderType == CKSM_HLSL) { _RegisterCgGLRenderstates(TRUE); _RegisterRenderstates(); } else { _RegisterRenderstates(TRUE); _RegisterCgGLRenderstates(); } m_PreviousShaderType = m_ShaderType ; } m_Toolbar->m_StaticTextShaderCplMode.SetWindowText(m_ShaderManager->GetCurrentShaderManagerType() == CKSM_HLSL ? "HLSL" : "CgFX" ); break; case CUIK_NOTIFICATION_WANTTOSEESHADER: //--- Ask to Create New Shader if( !Param1 ){ OnNewShader(); break; } //--- Ask to see another Shader CKShader* selectedShader = (CKShader*)Param1; if( selectedShader && selectedShader!=m_Shader ){ //--- Set the current shader SetCurrentShader( selectedShader ); UpdateShaderList(); m_Editor.SetFocus(); } if ((BOOL)Param2) CompileShader(NULL); break; } return S_OK; } //----------------------------------------------------------------------------- BOOL ShaderEditorDlg::SaveData(CKInterfaceObjectManager* iom) { if( !iom ) return FALSE; CKStateChunk* chunk = CreateCKStateChunk( SHADERSETUP_CHUNKID ); if( !chunk ) return FALSE; chunk->StartWrite(); //--- Start chunk->WriteIdentifier( SHADERSETUP_CHUNKID ); chunk->WriteInt( SHADERSETUP_VERSION ); //--- Write the index of the currently selected shader int currentShaderIndex = 0; HNTVITEM selectedItem = m_ShaderTree.GetSelectedItem(0); if( selectedItem ){ HNTVITEM item = m_ShaderTree.GetRoot(); int a=0; while( item ){ if( selectedItem == item ){ currentShaderIndex = a; break; } item = m_ShaderTree.GetNextItem( item ); ++a; } } chunk->WriteInt( currentShaderIndex ); //--- End chunk->CloseChunk(); iom->AddStateChunk( chunk ); return TRUE; } //----------------------------------------------------------------------------- BOOL ShaderEditorDlg::LoadData(CKInterfaceObjectManager* iom) { if( !iom ) return FALSE; const int chunkCount = iom->GetChunkCount(); CKStateChunk* chunk = iom->GetChunk( 0 ); if( !chunk ) return FALSE; chunk->StartRead(); //--- Start if( chunk->SeekIdentifier( SHADERSETUP_CHUNKID ) ){ int version = chunk->ReadInt(); //--- Read current selected shader on the Shader tree int currentShaderIndex = chunk->ReadInt(); HNTVITEM item = m_ShaderTree.GetRoot(); int a=0; for( ; aCloseChunk(); return TRUE; } //----------------------------------------------------------------------------- void ShaderEditorDlg::_SplitterLoadState(VISplitterWnd &splitter, int statebuf[], int num) const { XArray state; for (int i = 0; i < num; ++i) state.PushBack(statebuf[i]); splitter.LoadState(state); } //----------------------------------------------------------------------------- #define LAYOUT_STYLE (WS_CHILD|WS_VISIBLE) #define LAYOUT_ShaderREE 130 #define LAYOUT_TECHPARAM 220 #define LAYOUT_ERROR 62 #define LAYOUT_EDITORTITLE 24 #define LAYOUT_EDITOR_COUTPUT 650 //----------------------------------------------------------------------------- void ShaderEditorDlg::_SetupSplitters() { RECT rect; GetClientRect(&rect); int width = 1140; int height = 381; // int : column count // int : row count // int : width of window RECT at saving time // int : height of window RECT at saving time // array of int (column count-1) : SplitBars X positions (in pixel or percentage if percent==TRUE) // array of int (row count-1) : SplitBars Y positions (in pixel or percentage if percent==TRUE) int SplitMainState[] = { 3, 1, width, height, LAYOUT_ShaderREE, width - LAYOUT_TECHPARAM}; _SplitterLoadState(m_SplitMain, SplitMainState, sizeof(SplitMainState) / sizeof(int)); m_SplitMain.Create(-1, rect, this, IDC_SPLIT_MAIN); int SplitEditorErrorState[] = { 1, 2, width, height, height - LAYOUT_ERROR}; m_SplitEditorError.Create(-1, rect, &m_SplitMain, IDC_SPLIT_EDITOR_ERROR); _SplitterLoadState(m_SplitEditorError, SplitEditorErrorState, sizeof(SplitEditorErrorState) / sizeof(int)); m_SplitMain.SetWindowToPane(1, 0, &m_SplitEditorError); int SplitTechsParamsState[] = { 1, 2, LAYOUT_TECHPARAM, height, (int)(height * 0.35f) }; m_SplitTechsParams.Create(-1, rect, &m_SplitMain, IDC_SPLIT_TECHS_PARAMS); _SplitterLoadState(m_SplitTechsParams, SplitTechsParamsState, sizeof(SplitTechsParamsState) / sizeof(int)); m_SplitMain.SetWindowToPane(2, 0, &m_SplitTechsParams); int SplitEditorTitleState[] = { 2, 2, width, height, LAYOUT_EDITOR_COUTPUT, LAYOUT_EDITORTITLE}; m_SplitEditorTitle.Create(-1, rect, &m_SplitEditorError, IDC_SPLIT_EDITOR_TITLE); _SplitterLoadState(m_SplitEditorTitle, SplitEditorTitleState, sizeof(SplitEditorTitleState) / sizeof(int)); m_SplitEditorError.SetWindowToPane(0, 0, &m_SplitEditorTitle); } //----------------------------------------------------------------------------- void ShaderEditorDlg::_SetupEditor() { long editstyle = LAYOUT_STYLE | ES_LEFT | ES_NOHIDESEL | ES_DISABLENOSCROLL | ES_WANTRETURN | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP; m_Editor.ModifyFlags(VI_CTRL_RICHEDIT_CREATE_CONTROLS_AFTER_CREATE,0); m_Editor.Create(editstyle, _GetNullRect(), &m_SplitEditorTitle, IDC_EDITOR); m_Editor.SetBackColor(0x00ffffff); m_Editor.SetFlags(m_Editor.GetFlags() | VI_CTRL_RICHEDIT_FRAMERECT); long emask = m_Editor.GetEventMask(); m_Editor.SetEventMask(ENM_KEYEVENTS|ENM_MOUSEEVENTS|ENM_SCROLLEVENTS); m_Editor.LimitText(16777216); // Set Editor font CFont font; font.CreateFont(10,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET, OUT_TT_PRECIS,CLIP_TT_ALWAYS,DEFAULT_QUALITY,FF_DONTCARE|DEFAULT_PITCH,"Courier"); m_Editor.SetControlFont(&font); m_Editor.SetSel(0,0); m_Editor.ShowCaret(); m_Editor.SetFocus(); m_SplitEditorTitle.SetWindowToPane(0, 1, &m_Editor); // Set Editor title m_EditorTitle.Create("", LAYOUT_STYLE | SS_CENTER | WS_BORDER, _GetNullRect(), &m_SplitEditorTitle, IDC_EDITOR_TITLE); m_EditorTitle.SetControlFont(GetVIFont(VIFONT_BOLD)); m_EditorTitle.SetWindowText("Editor Title"); m_SplitEditorTitle.SetWindowToPane(0, 0, &m_EditorTitle); // Set Margin images m_ImageList = new CImageList; m_ImageList->Create(11, 11, ILC_COLOR|ILC_MASK, 0, 5); m_ImageList->Add(_GetCUIKIcon(IDI_NULL)); m_ImageList->Add(_GetCUIKIcon(IDI_EXPAND)); m_ImageList->Add(_GetCUIKIcon(IDI_MARK)); m_Editor.SetMarkImageList(m_ImageList); m_Editor.UpdateSizeForMarks(); // Scopes for comment and strings. _RegisterScopes(); // Keywords of the language. _RegisterKeywords(); // Creates basic types and corresponding vector and matrices. _RegisterBasicDataTypes(); // Creates signatures for intrinsics. _RegisterIntrinsics(); // Register asm keywords _RegisterASM(); // Register specific semantices _RegisterSemantics(); // Enums for renderstates. if (m_ShaderType == CKSM_HLSL) _RegisterRenderstates(); else _RegisterCgGLRenderstates(); m_Editor.UpdateColors(); // On compilation, register parameters. // Parse function prototype. } //----------------------------------------------------------------------------- void ShaderEditorDlg::_SetupCompiledOutput() { // An editor with a terminal font if possible. and ES_READONLY // with a static label on top with the title of the window. long editstyle = LAYOUT_STYLE | ES_READONLY | ES_LEFT | ES_NOHIDESEL | ES_DISABLENOSCROLL | ES_WANTRETURN | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_VSCROLL | WS_HSCROLL | SS_NOTIFY | WS_TABSTOP; m_CompiledOutput.ModifyFlags(VI_CTRL_RICHEDIT_CREATE_CONTROLS_AFTER_CREATE,0); m_CompiledOutput.Create(editstyle, _GetNullRect(), &m_SplitEditorTitle, IDC_COMPILED_OUTPUT); m_CompiledOutput.SetBackColor(0x00EEEEEE); m_CompiledOutput.SetFlags(m_CompiledOutput.GetFlags() | VI_CTRL_RICHEDIT_FRAMERECT); // Set Editor font CFont font; font.CreateFont(10,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET, OUT_TT_PRECIS,CLIP_TT_ALWAYS,DEFAULT_QUALITY,FF_DONTCARE|DEFAULT_PITCH,"Courier"); m_CompiledOutput.SetControlFont(&font); m_CompiledOutput.SetSel(0, 0); m_CompiledOutput.ShowCaret(); m_CompiledOutput.SetFocus(); m_SplitEditorTitle.SetWindowToPane(1, 1, &m_CompiledOutput); // Set Editor title m_CompiledOutputTitle.Create("", LAYOUT_STYLE | SS_CENTER | WS_BORDER | SS_NOTIFY, _GetNullRect(), &m_SplitEditorTitle, IDC_COMPILED_OUTPUT_TITLE); m_CompiledOutputTitle.SetControlFont(GetVIFont(VIFONT_BOLD)); m_CompiledOutputTitle.SetWindowText("Compiled Output Title"); m_SplitEditorTitle.SetWindowToPane(1, 0, &m_CompiledOutputTitle); // Hides editor and title HideCompiledOutput(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::_SetupOutput() { m_ErrorList.Create(WS_VSCROLL | LAYOUT_STYLE | LBS_NOTIFY | LBS_NOSEL | LBS_NOINTEGRALHEIGHT, _GetNullRect(), &m_SplitEditorError, IDC_ERROR_LIST); m_ErrorList.SetFont(GetVIFont(VIFONT_NORMAL),FALSE); m_ErrorList.SetFocus(); m_SplitEditorError.SetWindowToPane(0, 1, &m_ErrorList); } //----------------------------------------------------------------------------- HICON ShaderEditorDlg::_GetCUIKIcon(int ID) const { HICON icon = NULL; char filename[512]; GetModuleFileName(NULL, filename, 512); HINSTANCE nomoexe = GetModuleHandle("resvis.dll"/*filename*/); icon = LoadIcon(nomoexe, MAKEINTRESOURCE(ID)); assert(icon != NULL); return icon; } //----------------------------------------------------------------------------- CImageList* ShaderEditorDlg::_CreateTreeIcons() const { CImageList* treeil = new CImageList(); // Load images treeil->Create(11, 11, 1, 3, 1); treeil->Add(_GetCUIKIcon(IDI_NULL)); treeil->Add(_GetCUIKIcon(IDI_TREEEXPAND)); treeil->Add(_GetCUIKIcon(IDI_TREEEXPANDED)); return treeil; } //----------------------------------------------------------------------------- int SortShaderByName (const void* it1,const void* it2) { CKControl::HNTVITEM const item1 = *((CKControl::HNTVITEM*) it1); CKControl::HNTVITEM const item2 = *((CKControl::HNTVITEM*) it2); const char* const str1 = (char*) LPCSTR(item1->Text); const char* const str2 = (char*) LPCSTR(item2->Text); return stricmp(str1,str2); } //----------------------------------------------------------------------------- void ShaderEditorDlg::_SetupShaderTree() { m_ShaderTree.Create(LAYOUT_STYLE, _GetNullRect(), &m_SplitMain, IDC_SHADER_TREE); m_ShaderTree.SetColors(CZC_176,CZC_BLACK,CZC_176,CZC_WHITE,CZC_128,CZC_200); m_ShaderTree.SetFont(GetVIFont(VIFONT_NORMAL),FALSE); m_ShaderTree.SetItemHeight(18); m_ShaderTree.SetWindowText("Shader Tree"); m_ShaderTree.SetStyle(NTVS_DRAWHSEPARATOR); m_ShaderTree.SetPreAllocSize(20); // Create columns m_ShaderTree.SetColumnCount(1); m_ShaderTree.SetColumn(0, "Shader", 0, LAYOUT_ShaderREE-15); m_ShaderTree.SetCurrentSortFct(SortShaderByName ); // Set Icons m_ShaderTree.SetButtonImageList(_CreateTreeIcons()); m_ShaderTree.SetFocus(); m_SplitMain.SetWindowToPane(0, 0, &m_ShaderTree); } //----------------------------------------------------------------------------- void ShaderEditorDlg::_SetupTechniqueTree() { m_TechniqueTree.Create(LAYOUT_STYLE, _GetNullRect(), &m_SplitTechsParams, IDC_TECHNIQUE_TREE); m_TechniqueTree.SetColors(CZC_176,CZC_BLACK,CZC_176,CZC_WHITE,CZC_128,CZC_200); m_TechniqueTree.SetFont(GetVIFont(VIFONT_NORMAL),FALSE); m_TechniqueTree.SetItemHeight(18); m_TechniqueTree.SetWindowText("Technique Tree"); m_TechniqueTree.SetStyle(NTVS_DRAWHSEPARATOR); m_TechniqueTree.SetPreAllocSize(20); m_TechniqueTree.SetCKContext(GetCKContext()); // Create columns m_TechniqueTree.SetColumnCount(2); m_TechniqueTree.SetColumn(0, "Technique / Pass", 0, 135); m_TechniqueTree.SetColumn(1, "Desc", 0, 40); // Set Icons m_TechniqueTree.SetButtonImageList(_CreateTreeIcons()); m_TechniqueTree.SetFocus(); m_SplitTechsParams.SetWindowToPane(0, 0, &m_TechniqueTree); } //----------------------------------------------------------------------------- void ShaderEditorDlg::_SetupParameterTree() { m_ParameterTree.Create(LAYOUT_STYLE, _GetNullRect(), &m_SplitTechsParams, IDC_PARAMETER_TREE); m_ParameterTree.SetColors(CZC_176,CZC_BLACK,CZC_176,CZC_WHITE,CZC_128,CZC_200); m_ParameterTree.SetFont(GetVIFont(VIFONT_NORMAL),FALSE); m_ParameterTree.SetItemHeight(18); m_ParameterTree.SetWindowText("Exposed Parameter Tree"); m_ParameterTree.SetStyle(NTVS_DRAWHSEPARATOR); m_ParameterTree.SetPreAllocSize(20); m_ParameterTree.SetCKContext(GetCKContext()); // Create columns m_ParameterTree.SetColumnCount(2); m_ParameterTree.SetColumn(0, "Exposed Parameter", 0, 135); m_ParameterTree.SetColumn(1, "Type", 0, 40); // Set Icons m_ParameterTree.SetButtonImageList(_CreateTreeIcons()); m_ParameterTree.SetFocus(); m_SplitTechsParams.SetWindowToPane(0, 1, &m_ParameterTree); } //----------------------------------------------------------------------------- void ShaderEditorDlg::UpdateShaderManager() { if (m_ShaderManager != NULL) { EnableWindowTextIfShaderShadersIsSupported(); CKBOOL found = FALSE; for (int shaderIndex = 0; shaderIndex < m_ShaderManager->m_AllShaders.Size(); ++shaderIndex) { if (m_ShaderManager->m_AllShaders[shaderIndex]->GetListInEditorFlag()) { SetCurrentShader(m_ShaderManager->m_AllShaders[shaderIndex]); found = TRUE; } } if (!found) { SetCurrentShader(NULL); } UpdateShaderList(); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::UpdateShaderList() { int shaderCount = 0; for (int shaderIndex = 0; shaderIndex < m_ShaderManager->m_AllShaders.Size(); ++shaderIndex) { if (m_ShaderManager->m_AllShaders[shaderIndex]->GetListInEditorFlag()) ++shaderCount; } //--- If shaderCount is the same then it should mean that we do not need ///// to update the shader tree. This is because for the moment shader can only ///// be remove manually so there's no chance that one shader gets removed and ///// another added in the same time without calling UpdateShaderList() function. if( m_currentShaderListed != shaderCount ){ m_currentShaderListed = shaderCount; m_ShaderTree.DeleteAllItem(); for( int i=0; i < m_ShaderManager->m_AllShaders.Size() ; ++i ) { //--- Add item to shader list CKShader* Shader = m_ShaderManager->m_AllShaders[i]; if (!Shader->GetListInEditorFlag()) continue; HNTVITEM newItem; newItem = m_ShaderTree.InsertItem(Shader->GetName().CStr(), (HNTVITEM)NULL, FALSE); newItem->Flags = NTVI_EDITABLE; newItem->Data = Shader; //--- Add edit shader info to hash table if it was not (no overide) EditedShaderInfo esi; m_esiHash.Insert( Shader->GetName(), esi, FALSE ); //--- Set Selection if( Shader == m_Shader ){ m_ShaderTree.Select(newItem, NTVS_SELECT, FALSE); } } m_ShaderTree.Sort(); TellMaterialSetupShaderListHasChanged(); } //--- At least update currently selected shader item HNTVITEM previousSelectedItem = m_ShaderTree.GetSelectedItem(0); HNTVITEM item = m_ShaderTree.GetRoot(); while( item ){ if( previousSelectedItem!=item && m_Shader==item->Data ){ m_ShaderTree.Select( item, NTVS_SELECT, FALSE ); m_ShaderTree.Invalidate(); break; } item = m_ShaderTree.GetNextItem( item ); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::SetCurrentShader( CKShader* fx ) { UpdateShaderText(); //--- Don't need to continue if it's useless if( m_Shader==fx && fx && m_ShaderType==fx->GetCurrentShaderType() ) return; //--- Store previous shader's line if( m_Shader ){ EditedShaderInfo esi; esi.currentLine = m_Editor.GetFirstVisibleLine(); m_Editor.GetSel( esi.startSelChar, esi.endSelChar ); m_esiHash.Insert( m_Shader->GetName(), esi, TRUE ); } //--- Store previous shader's undo information DWORD UndoKey = (DWORD)m_Shader*(m_ShaderType+1); XUndoStorage* storage = m_UndoDatas.FindPtr(UndoKey); if (storage) m_Editor.SaveUndoData(*storage); else { XUndoStorage tempStorage; m_Editor.SaveUndoData(tempStorage); m_UndoDatas.InsertUnique(UndoKey,tempStorage); } m_Shader = fx; m_ShaderType = fx ? fx->GetCurrentShaderType() : CKSM_HLSL; //--------------------------------------------------- // Restore undo information for this script if available UndoKey = (DWORD)m_Shader*(m_ShaderType+1); storage = m_UndoDatas.FindPtr(UndoKey); if (storage) { m_Editor.LoadUndoData(*storage); } else { m_Editor.ClearUndo(); } if (fx) { m_EditorTitle.SetWindowText(fx->GetName().CStr()); UpdateWindowText(fx->GetText().CStr()); LoadShaderMarks(); if( m_Shader == m_ShaderManager->GetDefaultShader() ) { m_Editor.SetReadOnly( TRUE ); m_Editor.SetBackColor( RGB(210,210,210) ); } else { m_Editor.SetReadOnly( FALSE ); m_Editor.SetBackColor( RGB(255,255,255) ); } _UpdateTechniqueTree(); _UpdateParameterTree(); EnableWindowTextIfShaderShadersIsSupported( FALSE ); //--- Go to memorized line for this shader if( fx ){ EditedShaderInfo* esiPtr = m_esiHash.FindPtr( fx->GetName() ); if( esiPtr ){ m_Editor.LineScroll( -1000000, 0 ); m_Editor.LineScroll( esiPtr->currentLine, 0 ); m_Editor.SetSel( esiPtr->startSelChar, esiPtr->endSelChar ); } } } else { m_EditorTitle.SetWindowText(""); m_EditorTitle.EnableWindow(FALSE); UpdateWindowText(""); m_Editor.EnableWindow(FALSE); m_TechniqueTree.DeleteAllItem(); m_ParameterTree.DeleteAllItem(); SetErrorList(XClassArray()); } HideCompiledOutput(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::EnableWindowTextIfShaderShadersIsSupported( BOOL UpdateTrees ) { m_ShaderManager->m_Output.Clear(); if (m_ShaderManager->IsSupportedAndWarnIfNot()) { m_EditorTitle.EnableWindow(TRUE); m_Editor.EnableWindow(TRUE); m_Editor.SetFocus(); if( m_Shader && UpdateTrees ){ _UpdateTechniqueTree(); _UpdateParameterTree(); } } else { m_EditorTitle.EnableWindow(FALSE); m_Editor.EnableWindow(FALSE); m_TechniqueTree.DeleteAllItem(); m_ParameterTree.DeleteAllItem(); } SetErrorList(m_ShaderManager->m_Output); } //----------------------------------------------------------------------------- CKShader* ShaderEditorDlg::GetCurrentShader() { return m_Shader; } //----------------------------------------------------------------------------- CKShaderManager* ShaderEditorDlg::GetShaderManager() { return m_ShaderManager; } //----------------------------------------------------------------------------- void ShaderEditorDlg::UpdateShaderText() { if (m_Shader != NULL) { VxScratchString buffer; int strlen = m_Editor.GetWindowTextLength()+1; buffer->Reserve(strlen); char *bufferStr = buffer->Str(); m_Editor.GetWindowText(bufferStr, strlen); if ( m_ShaderType == m_Shader->GetCurrentShaderType() ) { if(!m_Shader->GetHideFlag()) { m_Shader->SetText(bufferStr); } } else { if(!m_Shader->GetHideFlag()) { m_Shader->SetText(bufferStr, m_ShaderType); } } } } //----------------------------------------------------------------------------- void ShaderEditorDlg::_UpdateTechniqueTree() { assert(m_Shader != 0); //--- Rescan techniques and pass m_TechniqueTree.DeleteAllItem(); const int techCount = m_Shader->GetTechniquesCount(); for ( int t=0 ; tGetTechniqueInfo( t, techInfo ); HNTVITEM parent = m_TechniqueTree.InsertItem( techInfo.name.CStr(), NULL ); parent->Font = VIFONT_BOLD; VITVSUBITEM *psh = new VITVSUBITEM; psh->Text = _Newstrdup( techInfo.desc.CStr() ); psh->Flags = NTVSI_TEXT | NTVSI_VCENTER; psh->UpdateCB = NULL; m_TechniqueTree.AddSubItem(parent, 0, psh); const int passCount = m_Shader->GetPassCount( t ); //--- Passes for ( int p=0 ; pGetPassInfo( t, p, passInfo ); HNTVITEM it = m_TechniqueTree.InsertItem( passInfo.name.CStr(), parent ); // Add var value. VITVSUBITEM *sh = new VITVSUBITEM; sh->Text = _Newstrdup( passInfo.desc ); sh->Flags = NTVSI_TEXT | NTVSI_VCENTER; sh->UpdateCB = NULL; m_TechniqueTree.AddSubItem(it, 0, sh); } } // Open all branches m_TechniqueTree.ExpandAll(m_TechniqueTree.GetRoot(), NTVE_EXPAND); } //----------------------------------------------------------------------------- void ShaderEditorDlg::_AddParameterToSubTree( CKControl::HNTVITEM cat, CKShader::ParamInfo& paramInfo ) { //--- Param's name (main item) HNTVITEM it = m_ParameterTree.InsertItem( paramInfo.name.CStr(), cat ); //--- Param's type (sub item) VITVSUBITEM* sh = new VITVSUBITEM; CKParameterManager* pm = GetCKContext()->GetParameterManager(); sh->Text = _Newstrdup( pm->ParameterGuidToName(paramInfo.guid) ); sh->Flags = NTVSI_TEXT | NTVSI_VCENTER; sh->UpdateCB = NULL; m_ParameterTree.AddSubItem( it, 0, sh ); } //----------------------------------------------------------------------------- BOOL ShaderEditorDlg::_IsCategoryOpened( int index ) { int parsedCatIndex = 0; HNTVITEM item = m_ParameterTree.GetRoot(); while( item ){ int depth = m_ParameterTree.GetItemDepth(item); if( depth == 0 ){ if( parsedCatIndex == index ){ if( !(item->Flags & NTVI_EXPANDED) ) return FALSE; return TRUE; } ++parsedCatIndex; } item = m_ShaderTree.GetNextItem( item ); } return TRUE; } //----------------------------------------------------------------------------- void ShaderEditorDlg::_UpdateParameterTree() { assert(m_Shader != 0); //--- Some information on categories static struct { char* name; DWORD expandFlag; CKControl::HNTVITEM cat; } catInfo[2] = { { "Automatic", NTVE_EXPAND, NULL }, { "Manual", NTVE_EXPAND, NULL }, }; enum { catInfoCount = sizeof(catInfo)/sizeof(*catInfo) }; int a; //--- Memorize old category tree state ///// So if it was opened, it stays opened for( a=0 ; aFont = VIFONT_BOLD; } //--- Insert compiled parameters CKShader::ParamInfo paramInfo; CKRenderManager* rm = m_ShaderManager->m_Context->GetRenderManager(); CKRenderContext* rc = rm->GetRenderContext(0); ///// Auto Parameters const int autoParamCount = m_Shader->GetAutoParameterCount(rc); for( a=0 ; aGetAutoParameterInfo( a, paramInfo, rc ); _AddParameterToSubTree( catInfo[0].cat, paramInfo ); } ///// Exposed Parameters const int exposedParamCount = m_Shader->GetExposedParameterCount(rc); for( a=0 ; aGetExposedParameterInfo( a, paramInfo, rc ); _AddParameterToSubTree( catInfo[1].cat, paramInfo ); } //--- Expand (or not) categories for( a=0 ; a 1) { m_SplitEditorTitle.SetColumnCount(1); m_SplitEditorTitle.RefreshPane(); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::ShowCompiledOutput() { if (m_SplitEditorTitle.GetColumnCount() < 2) { m_SplitEditorTitle.SetColumnCount(2); int width = 1140; int height = 381; int SplitEditorTitleState[] = { 2, 2, width, height, LAYOUT_EDITOR_COUTPUT, LAYOUT_EDITORTITLE}; _SplitterLoadState(m_SplitEditorTitle, SplitEditorTitleState, sizeof(SplitEditorTitleState) / sizeof(int)); m_SplitEditorTitle.SetWindowToPane(1, 0, &m_CompiledOutputTitle); m_SplitEditorTitle.SetWindowToPane(1, 1, &m_CompiledOutput); m_SplitEditorTitle.RefreshSplitBar(); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::_UpdateCompiledOuput(const XArray& text, const XString& title) { ShowCompiledOutput(); m_CompiledOutput.SetWindowText(text.Begin()); m_CompiledOutputTitle.SetWindowText(title.CStr()); } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnTimer(UINT nIDEvent) { switch( nIDEvent ){ case 1: //--- Want to blink m_ErrorList.SetBackColor( GetVIColor(m_errorListBlinkerColor) ); CBrush* newBrush = ::GetVIBrush( m_errorListBlinkerColor ); m_prevBrush = m_ErrorList.GetControlBrush(); m_ErrorList.SetControlBrush( newBrush ); m_ErrorList.Invalidate(); if( --m_errorListBlinkerColor < VICOLOR_176 ){ m_ErrorList.SetControlBrush( m_prevBrush ); m_ErrorList.SetBackColor( GetVIColor(VICOLOR_200) ); KillTimer( nIDEvent ); } break; } } //----------------------------------------------------------------------------- void ShaderEditorDlg::SetErrorList(const XClassArray& errors) { m_CurrOutput = 0; m_ErrorList.ResetContent(); for (int i = 0; i < errors.Size(); ++i){ m_ErrorList.AddString(errors[i].Str()); } if( errors.Size() ) FlashErrorList(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::PrintError( char* errorMsg, BOOL addToList ) { if( !addToList ) m_ErrorList.ResetContent(); m_ErrorList.AddString( errorMsg ); FlashErrorList(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::FlashErrorList() { m_errorListBlinkerColor = VICOLOR_WHITE; SetTimer( 1, 50, 0 ); } //----------------------------------------------------------------------------- void ShaderEditorDlg::CompileShader(CKShader* fx) { if (fx) SetCurrentShader(fx); else UpdateShaderText(); if (!m_Shader) return; m_ShaderManager->m_Output.Clear(); if (m_ShaderManager->CompileShader(m_Shader, m_ShaderManager->m_Output)) { _UpdateTechniqueTree(); _UpdateParameterTree(); } SetErrorList( m_ShaderManager->m_Output ); TellMaterialSetupShaderCompile(); //--- Force 2 rendering to be done because some modification may appear only on the second rendering. ///// Ex: Correct Tangent Space if the technique use the "NeedTangentSpace" annotation. GetInterface()->DoOneRenderNow(); GetInterface()->DoOneRender(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::CompileAllShaders() { UpdateShaderText(); m_ShaderManager->m_Output.Clear(); for (int i = 0; i < m_ShaderManager->m_AllShaders.Size(); ++i) { CKShader* fx = m_ShaderManager->m_AllShaders[i]; if (!m_ShaderManager->CompileShader(fx, m_ShaderManager->m_Output)) break; } SetErrorList( m_ShaderManager->m_Output ); //--- Force 2 rendering to be done because some modification may appear only on the second rendering. ///// Ex: Correct Tangent Space if the technique use the "NeedTangentSpace" annotation. GetInterface()->DoOneRenderNow(); GetInterface()->DoOneRender(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::ShowCompiledOutput(CompilationShaderType cv) { CString sname = m_Editor.GetSelText(); if (!sname.GetLength() && (cv < CST_FX_2_0)) return; if (!m_Shader) return; if (cv == CST_NONE) return; XClassArray output; if (m_ShaderManager->CompileShader(m_Shader, output)) { _UpdateTechniqueTree(); _UpdateParameterTree(); char *cst[] = { "none", "vs_1_1", "vs_2_0", "vs_3_0", "ps_1_1", "ps_1_2", "ps_1_3", "ps_1_4", "ps_2_0", "ps_3_0", "fx_2_0", "fx_2_0 No PreShader", "arbvp1", "vp20", "vp30", "vp40", "arbfp1", "fp20", "fp30", "fp40" }; XArray text; if (m_ShaderManager->CompileShaderOutput((CKShader*)m_Shader, const_cast((LPCSTR)sname), cst[cv], output, text)) _UpdateCompiledOuput(text, m_Shader->GetName() + "::" + sname); } SetErrorList(output); GetInterface()->DoOneRender(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::ShowMaterialShaderParameters(CKMaterialShader* mfx) { assert(!"Should not be called."); assert(mfx); if (mfx->m_Params.Size()) { MultiParamEditDlg pedit(GetCKContext(), this); for (int i = 0; i < mfx->m_Params.Size(); ++i) pedit.AddParameter(mfx->m_Params[i]); pedit.SetTitle("Material Shader Fx Params"); pedit.DoModal(); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnSelchangedShaderTree(NMHDR* pNMHDR, LRESULT* pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; if( pResult ) *pResult = 0; HNTVITEM item = m_ShaderTree.GetSelectedItem(0); if (item != NULL) { CKShader* fx = (CKShader*)item->Data; if( fx!=NULL ) SetCurrentShader(fx); m_ShaderTree.SetFocus(); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::TellMaterialShaderHasBeenRemoved( CKShader* fx ) { // Remove any undo data we may have stored along with this // shader for (int i = 1 ; i <= CKSM_ENUM_SIZE ; i++) { DWORD UndoKey = (DWORD)fx*(CKSM_HLSL+i); m_UndoDatas.Remove(UndoKey); } SendNotification( CUIK_NOTIFICATION_SHADERREMOVED, (DWORD)fx ); } void ShaderEditorDlg::TellMaterialSetupShaderListHasChanged() { SendNotification( CUIK_NOTIFICATION_SHADERLISTCHANGED ); } void ShaderEditorDlg::TellMaterialSetupShaderCompile() { SendNotification( CUIK_NOTIFICATION_SHADERCOMPILED, (DWORD)GetCurrentShader() ); } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnNewShader() { //--- Tells application composition has been modified GetInterface()->SetProjectModified( TRUE ); //--- Create New Shader, and do related updates CKShader* fx = m_ShaderManager->CreateShader(); CompileShader(fx); UpdateShaderList(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnImportShader() { XString filter; if (m_ShaderManager->GetCurrentShaderManagerType() == CKSM_HLSL) { filter = "Direct X 9 Shader (*.fx)|*.fx|"; } else { filter = "Cg Shader (.cg;.cgfx)|*.cg;*.cgfx|"; } filter += "All Files (*.*)|*.*||"; //--- Custom save dialog box AFX_MANAGE_STATE(AfxGetStaticModuleState()); ShaderEditorFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter.CStr(), this); if (dlg.DoModal() == IDOK) { CKShader* fx = NULL; XString fname = (LPCSTR)dlg.GetFileName(); //--- Update only the current shader text if option checked if (dlg.UpdateTextOnly()) { if (m_Shader != m_ShaderManager->GetDefaultShader()) { VxFile f; if (f.Open(fname.CStr(), VxFile::READONLY)) { int size = f.Size(); XString s; s.Resize( size ); int readCount = f.Read( s.Str(), size ); fx = m_Shader; fx->SetText(s); UpdateWindowText(s.CStr()); } } } //--- else create a new shader from this file if (!fx) fx = m_ShaderManager->CreateShaderFromFile(fname.Str()); if (fx) { CompileShader(fx); UpdateShaderList(); } else OnCannotOpenFile(fname); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnExportShader() { if (!m_Shader) return; if(m_Shader->GetHideFlag()) { CKDWORD ret = m_ShaderManager->m_Context->SendInterfaceMessage(CKUIM_MESSAGEBOX, (CKDWORD)"You can not save a protected shader to a *.fx *.cg or *.cgfx file.\n\n The save won't be done, unprotect your shader first if you want to save it in such a format.\n\n", (CKDWORD)"Warning!", 0); return; } CK_SHADER_MANAGER_TYPE shaderType = m_Shader->GetCurrentShaderType(); XString filter; XString fileExt; if (shaderType == CKSM_HLSL) { filter = "Direct X 9 Shader (*.fx)|*.fx|"; fileExt= ".fx"; } else { filter = "Cg Shader (.cg;.cgfx)|*.cg;*.cgfx|"; fileExt= ".cgfx"; } filter += "All Files (*.*)|*.*||"; XString filename = m_Shader->GetName() + fileExt; // Save dialog box CFileDialog dlg(FALSE, NULL, filename.CStr(), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, filter.CStr(), this); if (dlg.DoModal() == IDOK) { UpdateShaderText(); XString fname = (LPCSTR)dlg.GetFileName(); //--- Add ".fx" at the end of Filename int fNameLen = fname.Length(); if( fNameLen<=3 || (fname.Substring( fNameLen-fileExt.Length(),fileExt.Length())!=fileExt.CStr() && fname.Substring( fNameLen-3,3)!= ".cg")){ fname += fileExt; } if (!m_ShaderManager->SaveShaderToFile(fname, m_Shader)) OnCannotOpenFile(fname); } } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnSelchangeErrorList() { VxScratchString str; XString& s = (*str); s.Reserve(1024); m_ErrorList.GetText(m_ErrorList.GetCurSel(), s.Str()); s.Resize(strlen(s.Str() + 1)); for (int i = 0; i < s.Length(); ++i) if (s[i] == '(') { int line = atoi(&s[i + 1]); if (line == 0) continue; m_Editor.SelectRow(line - 1); break; } } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnEndlabeleditShaderTree(NMHDR* pNMHDR, LRESULT* pResult) { HNTVITEM it = m_ShaderTree.GetEditedEntity(); if (!it) return; //--- Get new name char str[512]; m_ShaderTree.GetEdit()->GetWindowText(str, 512); //--- If name is the same as another shader, then block modification CKShader* fx = (CKShader*)it->Data; assert(fx != NULL); const int shaderCount = m_ShaderManager->GetNumShaders(); int a; for( a=0 ; aGetShader(a); if( !otherFx ) continue; if( otherFx->GetName().Compare( str ) || otherFx==fx ) continue; break; } if( a==shaderCount ){ //--- Ok there's no other shader with the same name, so we can change it fx->SetName(str); it->Text = str; m_ShaderTree.RedrawItems(); m_EditorTitle.SetWindowText(fx->GetName().CStr()); m_ShaderTree.Sort(); TellMaterialSetupShaderListHasChanged(); _UpdateAllShaderParamsName( str ); } else { //--- Otherwise do not allowed name changing PrintError( "A Shader with the same name already exists." ); } } void ShaderEditorDlg::_UpdateAllShaderParamsName( const XString& iNewName ) { const int valueSize = iNewName.Length()+1; XArray modifiedParamsIDs; //--- Parse all parameters... CKContext* ctx = GetCKContext(); CKParameterManager* pm = ctx->GetParameterManager(); CKParameterType shaderType = pm->ParameterGuidToType( CKPGUID_SHADER ); const XObjectPointerArray& params = ctx->GetObjectListByType( CKCID_PARAMETER, TRUE ); const int paramsCount = params.Size(); for( int a=0 ; aGetType() == shaderType ){ const char* shaderName = (char*)p->GetReadDataPtr(); if( !shaderName ) continue; //--- If shader name is the same... if( m_PreviousRenamedShaderName == shaderName ){ p->SetValue( iNewName.CStr(), valueSize ); modifiedParamsIDs.PushBack( p->GetID() ); } } } //--- Ensure interface gets updated if( modifiedParamsIDs.Size() ){ GetInterface()->SendNotification( this, CUIK_NOTIFICATION_PARAMETERSEQUENCEMODIFIED, (DWORD)&modifiedParamsIDs[0], modifiedParamsIDs.Size() ); } } void ShaderEditorDlg::_GetMaterialStrUsingSelectedShader( XArray& oMatName ) { const int matCount = GetCKContext()->GetObjectsCountByClassID(CKCID_MATERIAL); CK_ID* mats = GetCKContext()->GetObjectsListByClassID(CKCID_MATERIAL); const int selectedItemCount = m_ShaderTree.GetSelectedItemsCount(); HNTVITEM it = m_ShaderTree.GetSelectedItem(0); if( !it ) return; CKShader* const fx = (CKShader*)it->Data; if( !fx ) return; //--- Parse All Materials for( int a=0 ; aGetObject( mats[a] ); CKMaterialShader* mfx = mat->GetMaterialShader(); if( mfx && mfx->m_Shader==fx ){ char* str = mat->GetName(); if( !str ) continue; oMatName.PushBack( str ); } } } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnRightClkShaderTree(NMHDR* pNMHDR, LRESULT* pResult) { //--- Create Popup Menu containing all materials used by all items of the selection VIPopupMenu popup; popup.Attach(this); popup.Empty(); if( m_SplitEditorTitle.GetColumnCount() >= 2 ){ //--- Output window is already visible, close it. popup.AddItem("Close secondary window", IDC_SECONDARY_EDITOR_BEGIN ); } else { if (m_ShaderType == CKSM_HLSL) { popup.AddItem( "Open \"CgFX\" version", IDC_SECONDARY_EDITOR_BEGIN+CKSM_CGFX ); } else { popup.AddItem( "Open \"HLSL\" version", IDC_SECONDARY_EDITOR_BEGIN+CKSM_HLSL ); } } popup.AddSeparator(); popup.AddItem( "Used By: ", 0 ); popup.AddSeparator(); XArray matName; _GetMaterialStrUsingSelectedShader( matName ); const int matNameCount = matName.Size(); for( int a=0 ; aData; assert(fx != NULL); BOOL warnDefaultShaderFx = FALSE; switch(pTVKeyDown->wVKey) { case VK_F2: { if( fx==m_ShaderManager->GetDefaultShader() ){ warnDefaultShaderFx = TRUE; break; } m_PreviousRenamedShaderName = fx->GetName(); m_ShaderTree.EditItemText(it); } break; case VK_DELETE: { const int selectedItemCount = m_ShaderTree.GetSelectedItemsCount(); for( int a=0 ; aData; if( !fx ) continue; if( fx==m_ShaderManager->GetDefaultShader() ){ warnDefaultShaderFx = TRUE; } else { if( fx == m_Shader ) SetCurrentShader(NULL); m_ShaderManager->DeleteShader(fx); m_ShaderTree.DeleteItem(it); _FixMaterialShaders(fx); TellMaterialShaderHasBeenRemoved( fx ); m_currentShaderListed--; } } } break; } //--- Output Warning concerning Default Shader Fx modifications if( warnDefaultShaderFx ){ PrintError( "Default Shader can't be renamed nor deleted" ); return; } } //----------------------------------------------------------------------------- void ShaderEditorDlg::_FixMaterialShaders(CKShader *fx) { int num_mats = GetCKContext()->GetObjectsCountByClassID(CKCID_MATERIAL); CK_ID* mats = GetCKContext()->GetObjectsListByClassID(CKCID_MATERIAL); BOOL needToRedraw = FALSE; for (int i = 0; i < num_mats; ++i) { CKMaterial* mat = (CKMaterial*)GetCKContext()->GetObject(mats[i]); CKMaterialShader* mfx = mat->GetMaterialShader(); if (mfx && mfx->m_Shader == fx) { for (int p = 0; p < mfx->m_Params.Size(); ++p) GetCKContext()->DestroyObject(mfx->m_Params[p]); delete mfx; mat->SetMaterialShader(NULL); needToRedraw = TRUE; } } if( needToRedraw ) GetInterface()->DoOneRender(); } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnKeydownEditor(NMHDR* pNMHDR, LRESULT* pResult) { //--- This methode is not called... don't know why... NMKEY* pKeyDown = (NMKEY*)pNMHDR; int toto=0; /* case VK_F2: if (kCtrl) AddF2Mark(); else GoToF2Mark(kShift); return 1; */ } //----------------------------------------------------------------------------- LRESULT ShaderEditorDlg::WindowProc( UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ){ case WM_FIND_ALLDOC_CMD: FindInScripts(); break; case WM_REPLACE_ALLDOC_CMD: ReplaceInScripts(); break; case VI_CTRL_MSG_SYNCED: case VI_CTRL_MSG_OUTOFSYNC: { //--- Tells application composition has been modified GetInterface()->SetProjectModified( TRUE ); } break; } return DllEditorDlg::WindowProc( message, wParam, lParam ); } //----------------------------------------------------------------------------- BOOL ShaderEditorDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { MSGFILTER* filter = (MSGFILTER*)lParam; if ((filter->nmhdr.idFrom==IDC_EDITOR) || m_Editor.IsFullScreen()) { if( filter->nmhdr.code == EN_MSGFILTER ){ switch( filter->msg ){ case WM_KEYDOWN: switch( filter->wParam ){ case VK_F7: //--- Compile CompileShader(NULL); m_ShaderManager->MakeParamsUpToDateForAllConcernedMaterials(m_Shader); break; case VK_F4: //--- Go to first error m_ErrorList.SetCurSel(m_CurrOutput++); OnSelchangeErrorList(); break; } break; case WM_CHAR: if( m_Shader == m_ShaderManager->GetDefaultShader() ){ if( filter->wParam < 32 && //--- If hit some special filter->wParam != 0x16 ){ //--- But not the Ctrl+V break; } //--- Warn about Default Shader Fx modification PrintError( "Default Shader cannot be modified." ); } //--- Tells application composition has been modified GetInterface()->SetProjectModified( TRUE ); break; } } } return DllEditorDlg::OnNotify(wParam, lParam, pResult); } //----------------------------------------------------------------------------- void ShaderEditorDlg::OnSize(UINT nType, int cx, int cy) { if (m_SplitMain.m_hWnd) { RECT rect; GetClientRect(&rect); m_SplitMain.MoveWindow(&rect); m_SplitEditorTitle.SetHorizontalSplitbarPosition(0, LAYOUT_EDITORTITLE-5); } DllEditorDlg::OnSize(nType, cx, cy); } //----------------------------------------------------------------------------- BOOL ShaderEditorDlg::OnCommand(WPARAM wParam, LPARAM lParam) { WORD w1 = LOWORD(wParam); WORD w2 = HIWORD(wParam); //--- Cloase Output Title if double click on it if( w1 == IDC_COMPILED_OUTPUT_TITLE && w2 == STN_DBLCLK ){ OnDblclkCompiledOutputTitle(); } //--- Show Material Setup (Context Menu on shader) if( w1 >= IDC_SHADER_USEDBY_MATERIAL_BEGIN && w1 < IDC_SHADER_USEDBY_MATERIAL_END ){ //--- Get Corresponding material XArray matName; _GetMaterialStrUsingSelectedShader( matName ); CKMaterial* mat = (CKMaterial*)GetCKContext()->GetObjectByNameAndClass( matName[w1-IDC_SHADER_USEDBY_MATERIAL_BEGIN], CKCID_MATERIAL ); if( !mat ) DllEditorDlg::OnCommand(wParam, lParam); //--- Open Material Editor GetInterface()->LaunchObjectSetup( mat ); } if ( w1 >= IDC_SECONDARY_EDITOR_BEGIN && w1 < IDC_SECONDARY_EDITOR_END ) { if( m_SplitEditorTitle.GetColumnCount() >= 2 ){ //--- Output window is already visible, close it. OnDblclkCompiledOutputTitle(); } else { //--- Open Secondary editor window and set the shader text CK_SHADER_MANAGER_TYPE type = (CK_SHADER_MANAGER_TYPE)(w1 - IDC_SECONDARY_EDITOR_BEGIN); const XString& buffer = m_Shader->GetText(type); ShowCompiledOutput(); m_CompiledOutput.SetWindowText(buffer.CStr()); XString name = m_Shader->GetName() + "::" + ((type == CKSM_HLSL) ? "HLSL" : "CgFX"); m_CompiledOutputTitle.SetWindowText(name.CStr()); } } return DllEditorDlg::OnCommand(wParam, lParam); } //----------------------------------------------------------------------------- void ShaderEditorDlg::FindInScripts() { if (!m_Editor.m_FindReplaceDlg) return; XArray shs; BOOL up = m_Editor.m_FindReplaceDlg->m_searchUp; GetShadersFromCurrent(shs,up); XString findstr = (LPCTSTR)(m_Editor.m_FindReplaceDlg->m_findStr); XArray::Iterator it1 = shs.Begin(); XArray::Iterator it2 = shs.End(); while (it1!=it2) { CKShader* sh = *it1++; if (!sh) continue; const XString& buffer = sh->GetText(); XDWORD res = buffer.IFind(findstr); if (res!=XString::NOTFOUND) { SetCurrentShader(sh); if (up) { int l = m_Editor.GetTextLength(); m_Editor.SetSel(l,l); } else m_Editor.SetSel(0,0); //select in tree HNTVITEM previousSelectedItem = m_ShaderTree.GetSelectedItem(0); HNTVITEM item = m_ShaderTree.GetRoot(); while( item ){ if( previousSelectedItem!=item && m_Shader==item->Data ){ m_ShaderTree.Select( item, NTVS_SELECT, FALSE ); m_ShaderTree.Invalidate(); break; } item = m_ShaderTree.GetNextItem( item ); } CHARRANGE range; BOOL ok = m_Editor.FindNext(range,!up,TRUE); if (ok) break; } } } //----------------------------------------------------------------------------- void ShaderEditorDlg::ReplaceInScripts() { if (!m_Editor.m_FindReplaceDlg) return; XArray shs; BOOL up = m_Editor.m_FindReplaceDlg->m_searchUp; GetShadersFromCurrent(shs,up); XString findstr = (LPCTSTR)(m_Editor.m_FindReplaceDlg->m_findStr); XArray::Iterator it1 = shs.Begin(); XArray::Iterator it2 = shs.End(); while (it1!=it2) { CKShader* sh = *it1++; if (!sh) continue; const XString& buffer= sh->GetText(); XDWORD res = buffer.IFind(findstr); if (res!=XString::NOTFOUND) { SetCurrentShader(sh); m_Editor.ReplaceAll(); } } } //----------------------------------------------------------------------------- void ShaderEditorDlg::GetShadersFromCurrent(XArray& shs,BOOL up) { int i,count = m_ShaderManager->GetNumShaders(); //1st phase : from current shader BOOL currentFound=FALSE; for (i=0;iGetShader(i); if (currentFound) { if (up) shs.PushBack(shader); else shs.PushFront(shader); } else if (shader==m_Shader) { currentFound=TRUE; } } //2nd phase : to current script for (i=0;iGetShader(i); if (shader==m_Shader) break; if (up) shs.PushBack(shader); else shs.PushFront(shader); } } //------------------------------------------------------------------------------------------------ void ShaderEditorDlg::AddF2Mark() { int line = m_Editor.LineFromChar(m_Editor.LineIndex())+1; if (m_Editor.HasMarkInLine(MARK_MARK,line-1)) { m_Editor.RemoveMarkFromLine(MARK_MARK,line-1); m_Shader->GetF2Marks()->Remove(line-1); } else { m_Editor.AddMarkToLine(MARK_MARK,line-1); m_Shader->GetF2Marks()->PushBack(line-1); } m_Editor.DoOnPaint(); } //------------------------------------------------------------------------------------------------ void ShaderEditorDlg::GoToF2Mark(BOOL up) { int currentLine = m_Editor.LineFromChar(m_Editor.LineIndex())+1; XArray markedLines; m_Editor.GetMarkLines(MARK_MARK,markedLines); if (!markedLines.Size()) return; markedLines.Sort(); int line,charpos=0; if (up) { currentLine--; XArray::Iterator it1 = markedLines.Begin(); XArray::Iterator it2 = markedLines.End(); while (it2!=it1) { line = *--it2; if (line::Iterator it1 = markedLines.Begin(); XArray::Iterator it2 = markedLines.End(); while (it1!=it2) { line = *it1++; if (line>currentLine) break; } if (line>currentLine) charpos = m_Editor.LineIndex(line); else charpos = m_Editor.LineIndex(markedLines[0]); } m_Editor.SetSel(charpos,charpos); } BOOL ShaderEditorDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message==WM_KEYDOWN && pMsg->hwnd==m_Editor.GetSafeHwnd()) { if (LOWORD(pMsg->wParam)==VK_F2) { if (GetAsyncKeyState(VK_CONTROL) & 0x08000) AddF2Mark(); else GoToF2Mark((GetAsyncKeyState(VK_SHIFT) & 0x08000)?TRUE:FALSE); } } return DllEditorDlg::PreTranslateMessage(pMsg); } void ShaderEditorDlg::LoadShaderMarks() { m_Editor.RemoveMarkFromAllLine(MARK_MARK); if (m_Shader && m_Shader->GetF2Marks()->Size()) { XArray::Iterator it1 = m_Shader->GetF2Marks()->Begin(); XArray::Iterator it2 = m_Shader->GetF2Marks()->End(); while (it1!=it2) { int line = *it1++; m_Editor.AddMarkToLine(MARK_MARK,line); } } }