doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MaterialTreeView.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 #include "../../idlib/precompiled.h"
29 #pragma hdrstop
30 
31 #include "MaterialTreeView.h"
32 
33 #define IMAGE_FOLDER 0
34 #define IMAGE_FILE 1
35 #define IMAGE_MATERIAL 2
36 #define IMAGE_MATERIAL_FOLDER 3
37 #define IMAGE_FILE_MOD 4
38 #define IMAGE_MATERIAL_MOD 5
39 #define IMAGE_MATERIAL_MOD_APPLY 6
40 
41 #define HOVER_EXPAND_DELAY 500
42 
43 #define MSG_RENAME_FOLDER_COMPLETE (WM_USER + 1000)
44 #define MSG_RENAME_MATERIAL_COMPLETE (WM_USER + 1001)
45 
47 
48 BEGIN_MESSAGE_MAP(MaterialTreeView, CTreeView)
49  ON_WM_CREATE()
50  ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnTvnSelchanged)
51  ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnTvnBeginlabeledit)
52  ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnTvnEndlabeledit)
53  ON_WM_CONTEXTMENU()
54  ON_NOTIFY_REFLECT(NM_RCLICK, OnNMRclick)
55  ON_WM_CHAR()
56  ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnTvnBegindrag)
57  ON_WM_MOUSEMOVE()
58  ON_WM_LBUTTONUP()
59 
60  ON_COMMAND(ID_POPUP_APPLYMATERIAL, OnApplyMaterial)
61  ON_COMMAND(ID_POPUP_APPLYFILE, OnApplyFile)
62  ON_COMMAND(ID_POPUP_APPLYALL, OnApplyAll)
63  ON_COMMAND(ID_POPUP_SAVEMATERIAL, OnSaveMaterial)
64  ON_COMMAND(ID_POPUP_SAVEFILE, OnSaveFile)
65  ON_COMMAND(ID_POPUP_SAVEALL, OnSaveAll)
66  ON_COMMAND(ID_POPUP_RENAMEMATERIAL, OnRenameMaterial)
67  ON_COMMAND(ID_POPUP_ADDMATERIAL, OnAddMaterial)
68  ON_COMMAND(ID_POPUP_ADDFOLDER, OnAddFolder)
69  ON_COMMAND(ID_POPUP_DELETEMATERIAL, OnDeleteMaterial)
70  ON_COMMAND(ID_POPUP_RELOADFILE, OnReloadFile)
71 
72  ON_COMMAND(ID_POPUP_CUT, OnCut)
73  ON_COMMAND(ID_POPUP_COPY, OnCopy)
74  ON_COMMAND(ID_POPUP_PASTE, OnPaste)
75 
76  ON_MESSAGE(MSG_RENAME_FOLDER_COMPLETE, OnRenameFolderComplete)
77  ON_MESSAGE(MSG_RENAME_MATERIAL_COMPLETE, OnRenameMaterialComplete)
78 END_MESSAGE_MAP()
79 
83 MaterialTreeView::MaterialTreeView() {
84  treeWithFile = false;
85  bDragging = false;
86  hoverItem = NULL;
87  internalChange = false;
88 }
89 
94 }
95 
101 void MaterialTreeView::InitializeMaterialList(bool includeFile, const char* filename) {
102 
103  treeWithFile = includeFile;
104 
105  CTreeCtrl& tree = GetTreeCtrl();
106 
107  tree.DeleteAllItems();
108  quickTree.Clear();
110  fileToTree.Clear();
111 
112  BuildMaterialList(includeFile, filename);
113 }
114 
120 void MaterialTreeView::BuildMaterialList(bool includeFile, const char* filename) {
121 
122  CTreeCtrl& tree = GetTreeCtrl();
123 
124  idStrList list(1024);
125 
127  if (count > 0) {
128  for (int i = 0; i < count; i++) {
129  const idMaterial *mat = declManager->MaterialByIndex(i, false);
130 
131  if(filename && strcmp(filename, mat->GetFileName())) {
132  continue;
133  }
134 
135  idStr temp;
136 
137  //Do Not Include Implicit File Definitions
138  idStr filename = mat->GetFileName();
139  if(!filename.Icmp("<implicit file>")) {
140  continue;
141  }
142 
143  if(filename.Find("def") != -1) {
144  int x = 0;
145  }
146 
147  if(includeFile) {
148  filename.StripPath();
149  temp = idStr(mat->GetFileName()) + "/" + idStr(mat->GetName()) + "|" + filename;
150  } else {
151  temp = mat->GetName();
152  }
153 
154  list.Append(temp);
155  }
156  AddStrList(NULL, &list, includeFile);
157  }
158 }
159 
165 
166  CTreeCtrl& tree = GetTreeCtrl();
167 
168  //When a material changes place an asterik next to the material and the file
169  HTREEITEM* materialItem = NULL;
170  materialToTree.Get(pMaterial->name, &materialItem);
171 
172 
173  if(!materialItem)
174  return;
175 
176  tree.SetItemImage(*materialItem, IMAGE_MATERIAL_MOD_APPLY, IMAGE_MATERIAL_MOD_APPLY);
177 
178 
179  if(treeWithFile) {
180  HTREEITEM* fileItem = NULL;
181  idStr file = pMaterial->renderMaterial->GetFileName();
182 
183  //common->Printf("Filename = %s\n", file.c_str());
184 
185  if(fileToTree.Get(file, &fileItem)){
186  //common->Printf("Found: %d\n", *fileItem);
187  tree.SetItemImage(*fileItem, IMAGE_FILE_MOD, IMAGE_FILE_MOD);
188  }
189  }
190 }
191 
197  CTreeCtrl& tree = GetTreeCtrl();
198 
199  //When a material is applied then just change the image to material modified
200  HTREEITEM* materialItem = NULL;
201  materialToTree.Get(pMaterial->name, &materialItem);
202 
203  if(!materialItem)
204  return;
205 
206  tree.SetItemImage(*materialItem, IMAGE_MATERIAL_MOD, IMAGE_MATERIAL_MOD);
207 }
208 
214  CTreeCtrl& tree = GetTreeCtrl();
215 
216  //Remove the asterik
217  HTREEITEM* materialItem = NULL;
218  materialToTree.Get(pMaterial->name, &materialItem);
219 
220  //We will get this message for a delete file so the material will not be in the tree
221  if(materialItem) {
222  tree.SetItemImage(*materialItem, IMAGE_MATERIAL, IMAGE_MATERIAL);
223  }
224 
225  //Check if the file is completely saved
226  if(treeWithFile) {
227 
229 
230  HTREEITEM* fileItem = NULL;
231  idStr file = pMaterial->renderMaterial->GetFileName();
232 
233  if(fileToTree.Get(file, &fileItem)) {
234  tree.SetItemImage(*fileItem, IMAGE_FILE, IMAGE_FILE);
235  }
236  }
237  }
238 }
239 
245 
246  idStrList list(1024);
247 
248  idMaterial *mat = pMaterial->renderMaterial;
249  idStr temp;
250 
251  if(treeWithFile) {
252  idStr filename = mat->GetFileName();
253  filename.StripPath();
254  temp = idStr(mat->GetFileName()) + "/" + idStr(mat->GetName()) + "|" + filename;
255  } else {
256  temp = mat->GetName();
257  }
258 
259  list.Append(temp);
260  AddStrList(NULL, &list, treeWithFile);
261 
262  //Keep the items sorted
263  HTREEITEM* item = NULL;
264  materialToTree.Get(pMaterial->name, &item);
265  if(*item) {
266  CTreeCtrl& tree = GetTreeCtrl();
267  HTREEITEM parent = tree.GetParentItem(*item);
268  tree.SortChildren(parent);
269  }
270 
271  MV_OnMaterialChange(pMaterial);
272 }
273 
279 
280  //Our doc told us a material has been deleted. Lets find and remove the item from our tree
281  HTREEITEM* materialItem = NULL;
282  materialToTree.Get(pMaterial->name, &materialItem);
283 
284  CTreeCtrl& tree = GetTreeCtrl();
285  tree.DeleteItem(*materialItem);
286 
287  //Remove our old quick lookup value
288  materialToTree.Remove(pMaterial->name.c_str());
289 }
290 
296 void MaterialTreeView::MV_OnMaterialNameChanged(MaterialDoc* pMaterial, const char* oldName) {
297 
298  CTreeCtrl& tree = GetTreeCtrl();
299 
300  if(!internalChange) {
301 
302  //Delete the old tree item
303  HTREEITEM* item = NULL;
304  materialToTree.Get(oldName, &item);
305  CTreeCtrl& tree = GetTreeCtrl();
306  HTREEITEM tempItem = *item;
307  CleanLookupTrees(tempItem);
308  tree.DeleteItem(tempItem);
309 
310 
311  //Now add it back
312  idStrList list(1024);
313  idMaterial *mat = pMaterial->renderMaterial;
314  idStr temp;
315 
316  if(treeWithFile) {
317  idStr filename = mat->GetFileName();
318  filename.StripPath();
319  temp = idStr(mat->GetFileName()) + "/" + idStr(mat->GetName()) + "|" + filename;
320  } else {
321  temp = mat->GetName();
322  }
323 
324  list.Append(temp);
325  AddStrList(NULL, &list, treeWithFile);
326 
327  //Keep the items sorted
328  //item = NULL;
329  materialToTree.Get(pMaterial->name.c_str(), &item);
330  if(*item) {
331  CTreeCtrl& tree = GetTreeCtrl();
332  HTREEITEM parent = tree.GetParentItem(*item);
333  tree.SortChildren(parent);
334  }
335 
336  MV_OnMaterialChange(pMaterial);
337 
338  }
339 }
340 
345 void MaterialTreeView::MV_OnFileReload(const char* filename) {
346 
347  HTREEITEM* fileItem = NULL;
348  fileToTree.Get(filename, &fileItem);
349 
350  HTREEITEM item = *fileItem;
351 
352  CTreeCtrl& tree = GetTreeCtrl();
353  CleanLookupTrees(item);
354  tree.DeleteItem(item);
355 
356  BuildMaterialList(treeWithFile, filename);
357 
358  //Resort the parent to make sure the file is back where it was
359  HTREEITEM* newItem = NULL;
360  fileToTree.Get(filename, &newItem);
361  if(*newItem) {
362  CTreeCtrl& tree = GetTreeCtrl();
363  HTREEITEM parent = tree.GetParentItem(*newItem);
364  tree.SortChildren(parent);
365  }
366 }
367 
372 
373  CTreeCtrl& tree = GetTreeCtrl();
374 
375  HTREEITEM item = tree.GetSelectedItem();
376  DWORD itemType = tree.GetItemData(item);
377 
378  if(item && itemType == TYPE_MATERIAL) {
379  return true;
380  } else {
381  return false;
382  }
383 }
384 
390 }
391 
396 
397  CTreeCtrl& tree = GetTreeCtrl();
398 
399  HTREEITEM item = tree.GetSelectedItem();
400  DWORD itemType = tree.GetItemData(item);
401 
402  if(item && itemType == TYPE_MATERIAL) {
403  return true;
404  } else {
405  return false;
406  }
407 }
408 
413 
414  CTreeCtrl& tree = GetTreeCtrl();
415 
416  HTREEITEM item = tree.GetSelectedItem();
417  DWORD itemType = tree.GetItemData(item);
418 
419  if(itemType == TYPE_MATERIAL_FOLDER || itemType == TYPE_MATERIAL) {
420  return true;
421  }
422 
423  return false;
424 }
425 
430 
431  CTreeCtrl& tree = GetTreeCtrl();
432 
433  HTREEITEM item = tree.GetSelectedItem();
434  DWORD itemType = tree.GetItemData(item);
435 
436  if(itemType == TYPE_MATERIAL_FOLDER || itemType == TYPE_MATERIAL) {
437  return true;
438  }
439  return false;
440 }
441 
446 
447  CTreeCtrl& tree = GetTreeCtrl();
448  HTREEITEM item = tree.GetSelectedItem();
449 
450  idStr filename;
451  if(item && GetFileName(item, filename)) {
452  if(materialDocManager->IsFileModified(filename.c_str()))
453  return true;
454  else
455  return false;
456  } else {
457  return false;
458  }
459 }
460 
465 
466  CTreeCtrl& tree = GetTreeCtrl();
467  HTREEITEM item = tree.GetSelectedItem();
468 
469  idStr filename = "";
470  if(item) {
471  if(!GetFileName(item, filename)) {
472  filename = "";
473  }
474  }
475 
476  return filename;
477 }
478 
484 
485  CTreeCtrl& tree = GetTreeCtrl();
486 
487  HTREEITEM selected = tree.GetSelectedItem();
488  if(!selected) {
489  selected = tree.GetRootItem();
490  if(!selected) {
491  return false;
492  }
493  }
494 
495  //Make sure we are in a file
496  if(searchData->searchScope == 0) {
497  DWORD type = tree.GetItemData(selected);
498  if(type == TYPE_FOLDER || type == TYPE_ROOT)
499  return false;
500  }
501 
502  HTREEITEM search =selected;
503 
504  while((search = GetNextSeachItem(search, (searchData->searchScope == 0))) != NULL) {
505  HTREEITEM found = FindNextMaterial(search, searchData);
506  if(found) {
507  tree.SelectItem(found);
508  return true;
509  }
510  }
511  return false;
512 }
513 
520 HTREEITEM MaterialTreeView::FindNextMaterial(HTREEITEM item, MaterialSearchData_t* searchData) {
521 
522  CTreeCtrl& tree = GetTreeCtrl();
523  DWORD type = tree.GetItemData(item);
524 
525  if(type == TYPE_MATERIAL) {
526  //check the tree name first
527  idStr itemName = tree.GetItemText(item);
528  int findPos = itemName.Find(searchData->searchText, false);
529  if(findPos != -1) {
530  //Todo: Include match whole word
531  return item;
532  }
533 
534  if(!searchData->nameOnly) {
535  //Check the material
536  idStr materialName = GetMediaPath(item, TYPE_MATERIAL);
537  if(materialDocManager->FindMaterial(materialName, searchData, false)) {
538  return item;
539  }
540  }
541  } else {
542  //Just check the tree name
543  idStr itemName = tree.GetItemText(item);
544 
545  int findPos = itemName.Find(searchData->searchText, false);
546  if(findPos != -1) {
547  //Todo: Include match whole word
548  return item;
549  }
550  }
551  return NULL;
552 }
553 
559 HTREEITEM MaterialTreeView::GetNextSeachItem(HTREEITEM item, bool stayInFile) {
560  CTreeCtrl& tree = GetTreeCtrl();
561 
562  HTREEITEM nextItem = NULL;
563 
564  //Check our children
565  if(tree.ItemHasChildren(item)) {
566  nextItem = tree.GetChildItem(item);
567  return nextItem;
568  }
569 
570  //Check our siblings
571  nextItem = tree.GetNextSiblingItem(item);
572  if(nextItem) {
573  return nextItem;
574  }
575 
576  //Check our parents next sibiling
577  HTREEITEM parent = item;
578  while((parent = tree.GetParentItem(parent)) != NULL) {
579  DWORD parType = tree.GetItemData(parent);
580  if(stayInFile && parType == TYPE_FILE)
581  break;
582 
583  HTREEITEM sib = tree.GetNextSiblingItem(parent);
584  if(sib) {
585  nextItem = sib;
586  break;
587  }
588  }
589  return nextItem;
590 }
591 
597 void MaterialTreeView::DeleteFolder(HTREEITEM item, bool addUndo) {
598 
599  CTreeCtrl& tree = GetTreeCtrl();
600 
601  idList<MaterialTreeItem_t> materialsToDelete;
602 
603  //Get the complete list of materials to delete
604  GetMaterialPaths(item, &materialsToDelete);
605 
607 
608  //Now delete the materials
609  for(int i = 0; i < materialsToDelete.Num(); i++) {
610 
611  affectedMaterials.Append(materialsToDelete[i].materialName);
612 
613  const idMaterial* material = declManager->FindMaterial(materialsToDelete[i].materialName);
614 
615  MaterialDoc* pMaterial = NULL;
616  pMaterial = materialDocManager->CreateMaterialDoc(const_cast<idMaterial *>(material));
617  materialDocManager->DeleteMaterial(pMaterial, false);
618  }
619 
620  //Make our undo modifier
621  if(addUndo) {
622  DeleteMaterialFolderModifier* mod = new DeleteMaterialFolderModifier(materialDocManager, tree.GetItemText(item), this, tree.GetParentItem(item), &affectedMaterials);
624  }
625 
626 
627  //Now clean up the folders and quicktree
628  CleanLookupTrees(item);
629 
630  //Remove any folders that were there
631  tree.DeleteItem(item);
632 }
633 
639 HTREEITEM MaterialTreeView::AddFolder(const char* name, HTREEITEM parent) {
640 
641  CTreeCtrl& tree = GetTreeCtrl();
642 
643  HTREEITEM newItem = tree.InsertItem(name, parent);
644  tree.SetItemImage(newItem, IMAGE_MATERIAL_FOLDER, IMAGE_MATERIAL_FOLDER);
645  tree.SetItemData(newItem, TYPE_MATERIAL_FOLDER);
646  tree.Expand(newItem, TVE_EXPAND);
647 
648  //Make sure the tree is still sorted
649  tree.SortChildren(parent);
650 
651  //Build the entire path to this item for the quicktree
652  idStr qt = GetQuicktreePath(newItem);
653  quickTree.Set(qt, newItem);
654 
655  return newItem;
656 }
657 
663 void MaterialTreeView::RenameFolder(HTREEITEM item, const char* name) {
664 
665  CTreeCtrl& tree = GetTreeCtrl();
666 
667  //Clean up the quicktree with the current tree before we allow the edit to commit
668  CleanLookupTrees(item);
669 
670  //Store some data so the we can make the appropriate changes after the commit
671  renamedFolder = item;
672 
675 
676  tree.SetItemText(item, name);
677 
678  PostMessage(MSG_RENAME_FOLDER_COMPLETE);
679 }
680 
685 
686  CTreeCtrl& tree = GetTreeCtrl();
687  if (pMsg->hwnd == tree.GetSafeHwnd()) {
688 
689  if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DELETE) {
691  return TRUE;
692  }
693  }
694  return FALSE;
695 }
696 
700 int MaterialTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
701 
702  lpCreateStruct->style |= TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_EDITLABELS | TVS_SHOWSELALWAYS | TVS_INFOTIP;
703  if (CTreeView::OnCreate(lpCreateStruct) == -1)
704  return -1;
705 
706  CTreeCtrl& tree = GetTreeCtrl();
707  m_image.Create(IDB_ME_TREEBITMAP, 16, 1, RGB(255, 255, 255));
708  tree.SetImageList(&m_image, TVSIL_NORMAL);
709 
710  return 0;
711 }
712 
716 void MaterialTreeView::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult) {
717 
718  LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
719 
720  if(pNMTreeView->itemNew.hItem) {
721  CTreeCtrl& tree = GetTreeCtrl();
722 
723  DWORD type = tree.GetItemData(pNMTreeView->itemNew.hItem);
724  if(type == TYPE_MATERIAL) {
725  idStr mediaName = GetMediaPath(pNMTreeView->itemNew.hItem, type);
726  const idMaterial* material = declManager->FindMaterial(mediaName);
727 
728  materialDocManager->SetSelectedMaterial(const_cast<idMaterial*>(material));
729 
730  } else {
731 
733  }
734 
735  } else {
736 
738  }
739 
740  *pResult = 0;
741 }
742 
746 void MaterialTreeView::OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult) {
747 
748  LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
749 
750  CTreeCtrl& tree = GetTreeCtrl();
751  DWORD type = tree.GetItemData(pTVDispInfo->item.hItem);
752 
753  //Only allow renaming of materials and material folders
754  if(type == TYPE_MATERIAL || type == TYPE_MATERIAL_FOLDER) {
755  *pResult = 0;
756  } else {
757  *pResult = 1;
758  }
759 }
760 
765 void MaterialTreeView::OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult) {
766 
767  LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
768 
769  *pResult = 0;
770 
771  if(pTVDispInfo->item.pszText) {
772 
773  //Convert any edited text to lower case to keep the name canonical
774  idStr newLabel = pTVDispInfo->item.pszText;
775  newLabel.ToLower();
776  strncpy( pTVDispInfo->item.pszText, newLabel.c_str(), pTVDispInfo->item.cchTextMax);
777 
778  CTreeCtrl& tree = GetTreeCtrl();
779  DWORD type = tree.GetItemData(pTVDispInfo->item.hItem);
780 
781  if(type == TYPE_MATERIAL) {
782 
784 
785  //Remove our old quick lookup value
786  materialToTree.Remove(pMaterial->name.c_str());
787 
788  //Generate the new name
789  idStr material;
790  HTREEITEM parent = tree.GetParentItem(pTVDispInfo->item.hItem);
791  DWORD parentType = tree.GetItemData(parent);
792  if(parentType == TYPE_MATERIAL_FOLDER) {
793  //Need to include the material folder
794  material = GetMediaPath(parent, TYPE_MATERIAL_FOLDER);
795  material += "/";
796  }
797 
798  material += pTVDispInfo->item.pszText;
799 
800  if(declManager->FindMaterial(material, false)) {
801  //Can't rename because it conflicts with an existing file
802  MessageBox("Unable to rename material because it conflicts with another material", "Error");
803  } else {
804  //Add it to our quick lookup
805  materialToTree.Set(material, pTVDispInfo->item.hItem);
806 
807  //Finally make the change
808  internalChange = true;
809  pMaterial->SetMaterialName(material);
810  internalChange = false;
811 
812  renamedFolder = pTVDispInfo->item.hItem;
813  PostMessage(MSG_RENAME_MATERIAL_COMPLETE);
814 
815  *pResult = 1;
816  }
817 
818  } else if (type == TYPE_MATERIAL_FOLDER) {
819 
820  //Clean up the quicktree with the current tree before we allow the edit to commit
821  CleanLookupTrees(pTVDispInfo->item.hItem);
822 
823  //Store some data so the we can make the appropriate changes after the commit
824  renamedFolder = pTVDispInfo->item.hItem;
825 
828 
829  PostMessage(MSG_RENAME_FOLDER_COMPLETE);
830 
831  RenameMaterialFolderModifier* mod = new RenameMaterialFolderModifier(materialDocManager, pTVDispInfo->item.pszText, this, pTVDispInfo->item.hItem, tree.GetItemText(pTVDispInfo->item.hItem));
833 
834  *pResult = 1;
835  }
836  }
837 }
838 
842 void MaterialTreeView::OnContextMenu(CWnd* pWnd, CPoint point)
843 {
844  ScreenToClient (&point);
845  PopupMenu (&point);
846 }
847 
851 void MaterialTreeView::OnNMRclick(NMHDR *pNMHDR, LRESULT *pResult)
852 {
853  CTreeCtrl& tree = GetTreeCtrl();
854 
855  DWORD dwPos = GetMessagePos();
856 
857  CPoint pt( LOWORD( dwPos ), HIWORD ( dwPos ) );
858 
859  CPoint spt = pt;
860  tree.ScreenToClient( &spt );
861 
862  UINT test;
863  HTREEITEM item = tree.HitTest( spt, &test );
864 
865  if ( item != NULL )
866  {
867  if ( test & TVHT_ONITEM )
868  {
869  //Select the item
870  tree.SelectItem(item);
871  OnContextMenu( this, pt );
872  }
873  }
874 
875  *pResult = 0;
876 }
877 
881 void MaterialTreeView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
882 {
883  if(nChar == 3 && GetKeyState(VK_CONTROL)) {
884  OnCopy();
885  }
886 
887  if(nChar == 22 && GetKeyState(VK_CONTROL)) {
888  OnPaste();
889  }
890 
891  if(nChar == 24 && GetKeyState(VK_CONTROL)) {
892  OnCut();
893  }
894 
895  CTreeView::OnChar(nChar, nRepCnt, nFlags);
896 }
897 
901 void MaterialTreeView::OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
902 {
903  LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
904 
905  CTreeCtrl& tree = GetTreeCtrl();
906 
907  HTREEITEM selecteditem = tree.GetSelectedItem();
908 
909  //Check to see if the are clicking on an item
910  UINT flags;
911  HTREEITEM item = tree.HitTest(pNMTreeView->ptDrag, &flags);
912 
913  if(item && (TVHT_ONITEM & flags)) {
914  if(item != selecteditem) {
915  tree.SelectItem(item);
916  }
917  }
918 
919  DWORD itemType = tree.GetItemData(item);
920 
921  if(itemType == TYPE_MATERIAL) {
922 
923  //Create the drag image
924  dragImage = tree.CreateDragImage(item);
925  dragImage->BeginDrag(0, CPoint (8, 8));
926  dragImage->DragEnter(GetDesktopWindow(), pNMTreeView->ptDrag);
927 
928  //Drag is in progress
929  bDragging = true;
930 
931  dragItem = item;
932 
933  //Capture the messages
934  SetCapture();
935  }
936 
937  *pResult = 0;
938 }
939 
943 void MaterialTreeView::OnMouseMove(UINT nFlags, CPoint point) {
944  if( bDragging ) {
945  CTreeCtrl& tree = GetTreeCtrl();
946 
947  dropPoint = point;
948  ClientToScreen(&dropPoint);
949 
950  //Move the drag image
951  dragImage->DragMove(dropPoint);
952  dragImage->DragShowNolock(FALSE);
953 
954  dragImage->DragShowNolock(TRUE);
955  }
956 
957  if(bDragging) {
958  //Test the hover item
959 
960  CTreeCtrl& tree = GetTreeCtrl();
961 
962  CPoint point;
963  GetCursorPos(&point);
964  ScreenToClient(&point);
965 
966  UINT flags;
967  HTREEITEM item = tree.HitTest(point, &flags);
968  if(item && (TVHT_ONITEM & flags)) {
969  if(item != hoverItem) {
970  hoverItem = item;
971  hoverStartTime = timeGetTime();
972  } else {
973  DWORD currentTime = timeGetTime();
974  if(currentTime - hoverStartTime > HOVER_EXPAND_DELAY) {
975 
976  UINT state = tree.GetItemState(hoverItem, TVIS_EXPANDED);
977  if(state != TVIS_EXPANDED && tree.ItemHasChildren(hoverItem)) {
978  tree.Expand(hoverItem, TVE_EXPAND);
979  }
980 
981  }
982  }
983  }
984  }
985 
986  CTreeView::OnMouseMove(nFlags, point);
987 }
988 
992 void MaterialTreeView::OnLButtonUp(UINT nFlags, CPoint point) {
993  CTreeCtrl& tree = GetTreeCtrl();
994 
995  if( bDragging ) {
996  //Release mouse capture
997  ReleaseCapture();
998 
999  //Delete the drag image
1000  dragImage->DragLeave(GetDesktopWindow());
1001  dragImage->EndDrag();
1002 
1003  bDragging = false;
1004 
1005  delete dragImage;
1006 
1007  UINT flags;
1008  HTREEITEM item = tree.HitTest(point, &flags);
1009  if(item && (TVHT_ONITEM & flags)) {
1010 
1011  DWORD itemType = tree.GetItemData(item);
1012 
1013  if(itemType == TYPE_MATERIAL) //Backup one if a file is selected
1014  item = tree.GetParentItem(item);
1015 
1016  //Make sure we aren't dragging to the same place
1017  HTREEITEM dragItemParent = tree.GetParentItem(dragItem);
1018  if(dragItemParent != item) {
1019 
1020 
1021  idStr dragFile;
1022  GetFileName(dragItem, dragFile);
1023 
1024  idStr filename;
1025  GetFileName(item, filename);
1026 
1027  //Move within a file copy across files
1028  if(!dragFile.Icmp(filename)) {
1030  } else {
1032  }
1033 
1034  //Generate the name
1035 
1036  idStr materialName = GetMediaPath(item, itemType);
1037 
1039  idStr copyMaterialName;
1040  copyName.ExtractFileName(copyMaterialName);
1041  materialName += "/" + copyMaterialName;
1042 
1043  //If the material name already exists add numbers until we don't find it
1044  materialName = materialDocManager->GetUniqueMaterialName(materialName);
1045 
1046  //Paste
1047  materialDocManager->PasteMaterial(materialName, filename);
1048  }
1049  }
1050  }
1051 
1052  CTreeView::OnLButtonUp(nFlags, point);
1053 }
1054 
1060 }
1061 
1066  idStr filename;
1067  HTREEITEM item = GetTreeCtrl().GetSelectedItem();
1068  if(GetFileName(item, filename)) {
1069  materialDocManager->ApplyFile(filename.c_str());
1070  }
1071 }
1072 
1078 }
1079 
1085 }
1086 
1091  idStr filename;
1092  HTREEITEM item = GetTreeCtrl().GetSelectedItem();
1093  if(GetFileName(item, filename)) {
1094  materialDocManager->SaveFile(filename.c_str());
1095  }
1096 }
1097 
1103 }
1104 
1109 
1110  CTreeCtrl& tree = GetTreeCtrl();
1111 
1112  HTREEITEM item = tree.GetSelectedItem();
1113  tree.EditLabel(item);
1114 }
1115 
1120 
1121  CTreeCtrl& tree = GetTreeCtrl();
1122 
1123  HTREEITEM item = tree.GetSelectedItem();
1124  DWORD itemType = tree.GetItemData(item);
1125 
1126  //Determine the file
1127  HTREEITEM parent = NULL;
1128  if(itemType != TYPE_FILE) {
1129 
1130  parent = tree.GetParentItem(item);
1131  while(1) {
1132  if(tree.GetItemData(parent) == TYPE_FILE)
1133  break;
1134  parent = tree.GetParentItem(parent);
1135  }
1136  } else {
1137  parent = item;
1138  }
1139  idStr filename = GetMediaPath(parent, TYPE_FILE);
1140 
1141 
1142  //Determine the material folder
1143  idStr materialFolder = "";
1144  switch(itemType) {
1145  case TYPE_MATERIAL:
1146  {
1147  HTREEITEM parentFolderItem = tree.GetParentItem(item);
1148  if(tree.GetItemData(parentFolderItem) == TYPE_MATERIAL_FOLDER)
1149  materialFolder = GetMediaPath(parentFolderItem, TYPE_MATERIAL_FOLDER);
1150  }
1151  break;
1152  case TYPE_MATERIAL_FOLDER:
1153  materialFolder = GetMediaPath(item, TYPE_MATERIAL_FOLDER);
1154  break;
1155  case TYPE_FILE:
1156  //There is no material folder
1157  break;
1158  }
1159 
1160  idStr name;
1161  int num = 1;
1162  while(1) {
1163  if(materialFolder.Length() > 0) {
1164  name = va("%s/newmaterial%d", materialFolder.c_str(), num);
1165  } else {
1166  name = va("newmaterial%d", num);
1167  }
1168  if(!declManager->FindMaterial(name, false))
1169  break;
1170  num++;
1171  }
1172 
1173  materialDocManager->AddMaterial(name.c_str(), filename.c_str());
1174 
1175 }
1176 
1181 
1182  CTreeCtrl& tree = GetTreeCtrl();
1183 
1184  HTREEITEM item = tree.GetSelectedItem();
1185  DWORD itemType = tree.GetItemData(item);
1186 
1187 
1188  //Backup if the selected item is a material
1189  if(itemType == TYPE_MATERIAL) {
1190  item = tree.GetParentItem(item);
1191  }
1192 
1193  //Pick a unique material name
1194  idStr newFolder;
1195  int num = 1;
1196  while(1) {
1197  newFolder = va("newfolder%d", num);
1198  if(tree.ItemHasChildren(item)) {
1199  HTREEITEM hChildItem = tree.GetChildItem(item);
1200  bool found = false;
1201  while (hChildItem != NULL)
1202  {
1203  if(!newFolder.Icmp(tree.GetItemText(hChildItem))) {
1204  found = true;
1205  break;
1206  }
1207  hChildItem = tree.GetNextSiblingItem(hChildItem);
1208  }
1209  if(!found)
1210  break;
1211  } else {
1212  break;
1213  }
1214  num++;
1215  }
1216 
1217  HTREEITEM newItem = AddFolder(newFolder, item);
1218 
1219  AddMaterialFolderModifier* mod = new AddMaterialFolderModifier(materialDocManager, newFolder, this, newItem, item);
1221 }
1222 
1227 
1228  CTreeCtrl& tree = GetTreeCtrl();
1229 
1230  HTREEITEM item = tree.GetSelectedItem();
1231  DWORD itemType = tree.GetItemData(item);
1232 
1233  if(itemType == TYPE_MATERIAL_FOLDER) {
1234  int result = MessageBox("Are you sure you want to delete this folder?", "Delete?", MB_ICONQUESTION | MB_YESNO);
1235  if(result == IDYES) {
1236  DeleteFolder(item);
1237  }
1238  } else if (itemType == TYPE_MATERIAL) {
1239  int result = MessageBox("Are you sure you want to delete this material?", "Delete?", MB_ICONQUESTION | MB_YESNO);
1240  if(result == IDYES) {
1242  }
1243  }
1244 }
1245 
1250 
1251  CTreeCtrl& tree = GetTreeCtrl();
1252 
1253  HTREEITEM item = tree.GetSelectedItem();
1254  DWORD itemType = tree.GetItemData(item);
1255 
1256  if(itemType == TYPE_MATERIAL || itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER) {
1257  idStr filename;
1258  GetFileName(item, filename);
1259 
1260  if(materialDocManager->IsFileModified(filename)) {
1261  int result = MessageBox("This file has been modified. Are you sure you want to reload this file?", "Reload?", MB_ICONQUESTION | MB_YESNO);
1262  if(result != IDYES) {
1263  return;
1264  }
1265  }
1266  materialDocManager->ReloadFile(filename);
1267  }
1268 }
1269 
1274  CTreeCtrl& tree = GetTreeCtrl();
1275 
1276  HTREEITEM item = tree.GetSelectedItem();
1277  DWORD itemType = tree.GetItemData(item);
1278 
1279  if(item && itemType == TYPE_MATERIAL) {
1281  } else if (itemType == TYPE_MATERIAL_FOLDER) {
1282  }
1283 }
1284 
1289 
1290  CTreeCtrl& tree = GetTreeCtrl();
1291 
1292  HTREEITEM item = tree.GetSelectedItem();
1293  DWORD itemType = tree.GetItemData(item);
1294 
1295  if(itemType == TYPE_MATERIAL) {
1297  } else if (itemType == TYPE_MATERIAL_FOLDER) {
1298  }
1299 }
1300 
1305 
1306  CTreeCtrl& tree = GetTreeCtrl();
1307 
1308  HTREEITEM item = tree.GetSelectedItem();
1309  DWORD itemType = tree.GetItemData(item);
1310 
1311  //Paste a material
1312  if(item && materialDocManager->IsCopyMaterial() && itemType >= TYPE_FILE) {
1313 
1314  //Generate the name
1315  if(itemType == TYPE_MATERIAL) {//Backup one if a file is selected
1316  item = tree.GetParentItem(item);
1317  itemType = tree.GetItemData(item);
1318  }
1319 
1320  idStr materialName = "";
1321  if(itemType != TYPE_FILE) {
1322  materialName = GetMediaPath(item, itemType) + "/";
1323  }
1324 
1326  idStr copyMaterialName;
1327  copyName.ExtractFileName(copyMaterialName);
1328  materialName += copyMaterialName;
1329 
1330  idStr filename;
1331  GetFileName(item, filename);
1332 
1333  //If the material name already exists add numbers until we don't find it
1334  materialName = materialDocManager->GetUniqueMaterialName(materialName);
1335 
1336  //Paste
1337  materialDocManager->PasteMaterial(materialName, filename);
1338 
1339  }
1340 }
1341 
1346 LRESULT MaterialTreeView::OnRenameFolderComplete(WPARAM wParam, LPARAM lParam) {
1347 
1348  //Generate new quick tree info for all material folders
1350 
1351  //Go through the list of affected materials and rename them
1352  for(int i = 0; i < affectedMaterials.Num(); i++) {
1353  RenameMaterial(affectedMaterials[i].treeItem, affectedMaterials[i].materialName);
1354  }
1355 
1356  //Make sure the tree stays sorted
1357  CTreeCtrl& tree = GetTreeCtrl();
1358  HTREEITEM parent = tree.GetParentItem(renamedFolder);
1359  tree.SortChildren(parent);
1360 
1361  return 0;
1362 }
1363 
1367 LRESULT MaterialTreeView::OnRenameMaterialComplete(WPARAM wParam, LPARAM lParam) {
1368 
1369  //Make sure the tree stays sorted
1370  CTreeCtrl& tree = GetTreeCtrl();
1371  HTREEITEM parent = tree.GetParentItem(renamedFolder);
1372  tree.SortChildren(parent);
1373 
1374  return 0;
1375 }
1376 
1380 void MaterialTreeView::RenameMaterial(HTREEITEM item, const char* originalName) {
1381 
1382  CTreeCtrl& tree = GetTreeCtrl();
1383 
1384  const idMaterial* material = declManager->FindMaterial(originalName);
1385 
1386  MaterialDoc* pMaterial;
1387  //pMaterial = materialDocManager->GetInProgressDoc(material);
1388 
1389  //if(!pMaterial) {
1390  pMaterial = materialDocManager->CreateMaterialDoc(const_cast<idMaterial *>(material));
1391  //}
1392 
1393  //Remove our old quick lookup value
1394  materialToTree.Remove(originalName);
1395 
1396  //Generate the new name
1397  idStr materialName;
1398  HTREEITEM parent = tree.GetParentItem(item);
1399  DWORD parentType = tree.GetItemData(parent);
1400  if(parentType == TYPE_MATERIAL_FOLDER) {
1401  //Need to include the material folder
1402  materialName = GetMediaPath(parent, TYPE_MATERIAL_FOLDER);
1403  materialName += "/";
1404  }
1405  materialName += tree.GetItemText(item);
1406 
1407 
1408  //Add it to our quick lookup
1409  materialToTree.Set(materialName, item);
1410 
1411  //Finally make the change
1412  internalChange = true;
1413  pMaterial->SetMaterialName(materialName, false);
1414  internalChange = false;
1415 }
1416 
1422 bool MaterialTreeView::GetFileName(HTREEITEM item, idStr& out) {
1423 
1424  out = "";
1425 
1426  CTreeCtrl& tree = GetTreeCtrl();
1427  DWORD type = tree.GetItemData(item);
1428 
1429  if(type != TYPE_MATERIAL && type != TYPE_MATERIAL_FOLDER && type != TYPE_FILE)
1430  return false;
1431 
1432  if(type == TYPE_FILE) {
1433  out = GetMediaPath(item, TYPE_FILE);
1434  return true;
1435  }
1436 
1437  HTREEITEM parent = tree.GetParentItem( item );
1438  while ( parent != NULL ) {
1439  DWORD parentType = tree.GetItemData(parent);
1440  if(parentType == TYPE_FILE) {
1441  out = GetMediaPath(parent, TYPE_FILE);
1442  return true;
1443  }
1444  parent = tree.GetParentItem( parent );
1445  }
1446 
1447  return false;
1448 }
1449 
1456 
1457  //Determine when to stop building the path
1458  DWORD stopType = TYPE_ROOT;
1459  switch(type) {
1460  case TYPE_MATERIAL:
1461  stopType = TYPE_FILE;
1462  break;
1463  case TYPE_MATERIAL_FOLDER:
1464  stopType = TYPE_FILE;
1465  break;
1466  case TYPE_FILE:
1467  stopType = TYPE_ROOT;
1468  break;
1469  };
1470 
1471  CTreeCtrl& tree = GetTreeCtrl();
1472 
1473  idStr mediaName = tree.GetItemText( item );
1474 
1475  // have to build the name back up
1476  HTREEITEM parent = tree.GetParentItem( item );
1477  while ( parent != NULL ) {
1478 
1479  //stop the iteration once we have found a specific type
1480  DWORD parentType = tree.GetItemData(parent);
1481  if(parentType == stopType) {
1482  break;
1483  }
1484 
1485  idStr strParent = tree.GetItemText( parent );
1486  strParent += "/";
1487  strParent += mediaName;
1488  mediaName = strParent;
1489  parent = tree.GetParentItem( parent );
1490 
1491  }
1492 
1493  return mediaName;
1494 }
1495 
1502 
1503  CTreeCtrl& tree = GetTreeCtrl();
1504  if(tree.ItemHasChildren(item)) {
1505 
1506  HTREEITEM childItem = tree.GetChildItem(item);
1507  while(childItem != NULL) {
1508 
1509  DWORD childType = tree.GetItemData(childItem);
1510  if (childType == TYPE_MATERIAL) {
1511  MaterialTreeItem_t mat;
1512  mat.materialName = GetMediaPath(childItem, TYPE_MATERIAL);
1513  mat.treeItem = childItem;
1514  list->Append(mat);
1515  } else if (childType == TYPE_MATERIAL_FOLDER) {
1516  GetMaterialPaths(childItem, list);
1517  }
1518  childItem = tree.GetNextSiblingItem(childItem);
1519  }
1520  }
1521 }
1522 
1529 void MaterialTreeView::AddStrList(const char *root, idStrList *list, bool includeFile) {
1530 
1531  CTreeCtrl& treeMedia = GetTreeCtrl();
1532 
1533  idStr out, path;
1534  HTREEITEM base = NULL;
1535 
1536  if(root) {
1537  base = treeMedia.GetRootItem();
1538  if (base) {
1539  out = treeMedia.GetItemText(base);
1540  if (stricmp(root, out)) {
1541  base = NULL;
1542  }
1543  }
1544 
1545  if (base == NULL) {
1546  base = treeMedia.InsertItem(root);
1547  treeMedia.SetItemData(base, TYPE_ROOT);
1548  }
1549  }
1550 
1551  HTREEITEM item = base;
1552  HTREEITEM add;
1553 
1554  list->Sort();
1555  int count = list->Num();
1556 
1557  idStr last, qt;
1558  for (int i = 0; i < count; i++) {
1559  idStr *strItem = &(*list)[i];
1560 
1561 
1562  idStr name = strItem->c_str();
1563 
1564  idStr filename;
1565  bool afterFile = true;
1566  if(includeFile) {
1567  int index = name.Find("|");
1568  if(index >= 0) {
1569  afterFile = false;
1570  filename = name.Right(name.Length() - index - 1);
1571  name = name.Left(index);
1572  }
1573  }
1574 
1575  // now break the name down convert to slashes
1576  name.BackSlashesToSlashes();
1577  name.Strip(' ');
1578 
1579  int index;
1580  int len = last.Length();
1581  if (len == 0) {
1582  index = name.Last('/');
1583  if (index >= 0) {
1584  name.Left(index, last);
1585  }
1586  }
1587  else if (idStr::Icmpn(last, name, len) == 0 && name.Last('/') <= len) {
1588  name.Right(name.Length() - len - 1, out);
1589  add = treeMedia.InsertItem(out, item);
1590  qt = root;
1591  qt += "/";
1592  qt += name;
1593  quickTree.Set(qt, add);
1594  treeMedia.SetItemImage(add, IMAGE_MATERIAL, IMAGE_MATERIAL);
1595  treeMedia.SetItemData(add, TYPE_MATERIAL);
1596 
1597  //Add the item to a quick lookup table
1598  idStr material = GetMediaPath(add, TYPE_MATERIAL);
1599  materialToTree.Set(material, add);
1600 
1601  continue;
1602  }
1603  else {
1604  last.Empty();
1605  }
1606 
1607  index = 0;
1608  item = base;
1609  path = "";
1610  while (index >= 0) {
1611  index = name.Find('/');
1612  if (index >= 0) {
1613  HTREEITEM newItem = NULL;
1614  HTREEITEM *check = NULL;
1615  name.Left(index, out);
1616  path += out;
1617  qt = root;
1618  qt += "/";
1619  qt += path;
1620  if (quickTree.Get(qt, &check)) {
1621  newItem = *check;
1622  }
1623 
1624  bool thisisfile = false;
1625  if(out == filename) {
1626  thisisfile = true;
1627  afterFile = true;
1628 
1629  }
1630 
1631  if (newItem == NULL) {
1632  newItem = treeMedia.InsertItem(out, item);
1633  qt = root;
1634  qt += "/";
1635  qt += path;
1636  quickTree.Set(qt, newItem);
1637 
1638 
1639  if(!afterFile || thisisfile) {
1640  if(thisisfile) {
1641  afterFile = true;
1642  treeMedia.SetItemImage(newItem, IMAGE_FILE, IMAGE_FILE);
1643  treeMedia.SetItemData(newItem, TYPE_FILE);
1644 
1645  //Add the item to a quick lookup table
1646  idStr file = GetMediaPath(newItem, TYPE_FILE);
1647  //common->Printf("Adding fileToTree: %s - %d\n", file.c_str(), newItem);
1648  fileToTree.Set(file, newItem);
1649 
1650  } else {
1651  treeMedia.SetItemImage(newItem, IMAGE_FOLDER, IMAGE_FOLDER);
1652  treeMedia.SetItemData(newItem, TYPE_FOLDER);
1653  }
1654  } else {
1655  treeMedia.SetItemImage(newItem, IMAGE_MATERIAL_FOLDER, IMAGE_MATERIAL_FOLDER);
1656  treeMedia.SetItemData(newItem, TYPE_MATERIAL_FOLDER);
1657 
1658  }
1659  }
1660 
1661 
1662  item = newItem;
1663  name.Right(name.Length() - index - 1, out);
1664  name = out;
1665  path += "/";
1666  }
1667  else {
1668  add = treeMedia.InsertItem(name, item);
1669  qt = root;
1670  qt += "/";
1671  qt += path;
1672  qt += name;
1673  quickTree.Set(qt, add);
1674  treeMedia.SetItemImage(add, IMAGE_MATERIAL, IMAGE_MATERIAL);
1675  treeMedia.SetItemData(add, TYPE_MATERIAL);
1676  path = "";
1677 
1678  //Add the item to a quick lookup table
1679  idStr material = GetMediaPath(add, TYPE_MATERIAL);
1680  materialToTree.Set(material, add);
1681  }
1682  }
1683  }
1684 }
1685 
1691 
1692  //Determine the type of object clicked on
1693  CTreeCtrl& tree = GetTreeCtrl();
1694  UINT test;
1695  HTREEITEM item = tree.HitTest( *pt, &test );
1696  if ( item == NULL || !(test & TVHT_ONITEM) )
1697  return;
1698 
1699  ClientToScreen (pt);
1700 
1701  CMenu FloatingMenu;
1702  VERIFY(FloatingMenu.LoadMenu(IDR_ME_MATERIALTREE_POPUP));
1703  CMenu* pPopupMenu = FloatingMenu.GetSubMenu (0);
1704 
1705  DWORD itemType = tree.GetItemData(item);
1706 
1707  //Enable/Disable based on the state
1709 
1710 
1711  //Apply Changes
1712  if(pDoc && pDoc->applyWaiting) {
1713  pPopupMenu->EnableMenuItem(ID_POPUP_APPLYMATERIAL, MF_BYCOMMAND | MF_ENABLED);
1714  } else {
1715  pPopupMenu->EnableMenuItem(ID_POPUP_APPLYMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1716  }
1717 
1718  //Apply File
1719  idStr filename;
1720  if(GetFileName(item, filename)) {
1721  if(materialDocManager->DoesFileNeedApply(filename.c_str()))
1722  pPopupMenu->EnableMenuItem(ID_POPUP_APPLYFILE, MF_BYCOMMAND | MF_ENABLED);
1723  else
1724  pPopupMenu->EnableMenuItem(ID_POPUP_APPLYFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1725  } else {
1726  pPopupMenu->EnableMenuItem(ID_POPUP_APPLYFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1727  }
1728 
1729  //Apply All
1731  pPopupMenu->EnableMenuItem(ID_POPUP_APPLYALL, MF_BYCOMMAND | MF_ENABLED);
1732  } else {
1733  pPopupMenu->EnableMenuItem(ID_POPUP_APPLYALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1734  }
1735 
1736  //Save Material
1737  if(pDoc && pDoc->modified) {
1738  pPopupMenu->EnableMenuItem(ID_POPUP_SAVEMATERIAL, MF_BYCOMMAND | MF_ENABLED);
1739  } else {
1740  pPopupMenu->EnableMenuItem(ID_POPUP_SAVEMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1741  }
1742 
1743  //Save File
1744  if(GetFileName(item, filename)) {
1745  if(materialDocManager->IsFileModified(filename.c_str()))
1746  pPopupMenu->EnableMenuItem(ID_POPUP_SAVEFILE, MF_BYCOMMAND | MF_ENABLED);
1747  else
1748  pPopupMenu->EnableMenuItem(ID_POPUP_SAVEFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1749  } else {
1750  pPopupMenu->EnableMenuItem(ID_POPUP_SAVEFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1751  }
1752 
1753  //Save All
1755  pPopupMenu->EnableMenuItem(ID_POPUP_SAVEALL, MF_BYCOMMAND | MF_ENABLED);
1756  } else {
1757  pPopupMenu->EnableMenuItem(ID_POPUP_SAVEALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1758  }
1759 
1760  if(itemType == TYPE_MATERIAL || itemType == TYPE_MATERIAL_FOLDER) {
1761  pPopupMenu->EnableMenuItem(ID_POPUP_RENAMEMATERIAL, MF_BYCOMMAND | MF_ENABLED);
1762  pPopupMenu->EnableMenuItem(ID_POPUP_DELETEMATERIAL, MF_BYCOMMAND | MF_ENABLED);
1763  } else {
1764  pPopupMenu->EnableMenuItem(ID_POPUP_RENAMEMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1765  pPopupMenu->EnableMenuItem(ID_POPUP_DELETEMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1766  }
1767 
1768  if(itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER || itemType == TYPE_MATERIAL) {
1769  pPopupMenu->EnableMenuItem(ID_POPUP_ADDMATERIAL, MF_BYCOMMAND | MF_ENABLED);
1770  pPopupMenu->EnableMenuItem(ID_POPUP_ADDFOLDER, MF_BYCOMMAND | MF_ENABLED);
1771  } else {
1772  pPopupMenu->EnableMenuItem(ID_POPUP_ADDMATERIAL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1773  pPopupMenu->EnableMenuItem(ID_POPUP_ADDFOLDER, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1774  }
1775 
1776  if(itemType == TYPE_MATERIAL) {
1777  pPopupMenu->EnableMenuItem(ID_POPUP_CUT, MF_BYCOMMAND | MF_ENABLED);
1778  pPopupMenu->EnableMenuItem(ID_POPUP_COPY, MF_BYCOMMAND | MF_ENABLED);
1779  } else {
1780  pPopupMenu->EnableMenuItem(ID_POPUP_CUT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1781  pPopupMenu->EnableMenuItem(ID_POPUP_COPY, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1782  }
1783 
1784  if((itemType == TYPE_MATERIAL || itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER) && materialDocManager->IsCopyMaterial()) {
1785  pPopupMenu->EnableMenuItem(ID_POPUP_PASTE, MF_BYCOMMAND | MF_ENABLED);
1786  } else {
1787  pPopupMenu->EnableMenuItem(ID_POPUP_PASTE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1788  }
1789 
1790  if(itemType == TYPE_MATERIAL || itemType == TYPE_FILE || itemType == TYPE_MATERIAL_FOLDER) {
1791  pPopupMenu->EnableMenuItem(ID_POPUP_RELOADFILE, MF_BYCOMMAND | MF_ENABLED);
1792  } else {
1793  pPopupMenu->EnableMenuItem(ID_POPUP_RELOADFILE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
1794  }
1795 
1796  pPopupMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt->x, pt->y, &GetTreeCtrl());
1797 }
1798 
1806 void MaterialTreeView::SetItemImage(HTREEITEM item, bool mod, bool apply, bool children) {
1807 
1808  CTreeCtrl& tree = GetTreeCtrl();
1809 
1810  int image;
1811 
1812  DWORD itemType = tree.GetItemData(item);
1813  switch(itemType) {
1814  case TYPE_FILE:
1815  if(mod)
1816  image = IMAGE_FILE_MOD;
1817  else
1818  image = IMAGE_FILE;
1819  break;
1820  case TYPE_MATERIAL_FOLDER:
1821  image = IMAGE_MATERIAL_FOLDER;
1822  break;
1823  case TYPE_MATERIAL:
1824  if(mod && apply)
1825  image = IMAGE_MATERIAL_MOD_APPLY;
1826  else if(mod)
1827  image = IMAGE_MATERIAL_MOD;
1828  else
1829  image = IMAGE_MATERIAL;
1830  break;
1831  }
1832 
1833  tree.SetItemImage(item, image, image);
1834 
1835  if(children) {
1836  if(tree.ItemHasChildren(item)) {
1837  HTREEITEM hChildItem = tree.GetChildItem(item);
1838  while (hChildItem != NULL) {
1839  SetItemImage(hChildItem, mod, apply, children);
1840  hChildItem = tree.GetNextSiblingItem(hChildItem);
1841  }
1842  }
1843  }
1844 }
1845 
1851 
1852  idStr qt = GetQuicktreePath(item);
1853  quickTree.Remove(qt);
1854 
1855  CTreeCtrl& tree = GetTreeCtrl();
1856 
1857  //Clean special lookup tables
1858  DWORD type = tree.GetItemData(item);
1859  if(type == TYPE_FILE) {
1860  idStr file = GetMediaPath(item, TYPE_FILE);
1861  fileToTree.Remove(file);
1862  } else if(type == TYPE_MATERIAL) {
1864  materialToTree.Remove(name);
1865  }
1866 
1867  //Clean all my children
1868  if(tree.ItemHasChildren(item)) {
1869  HTREEITEM childItem = tree.GetChildItem(item);
1870  while(childItem != NULL) {
1871  CleanLookupTrees(childItem);
1872  childItem = tree.GetNextSiblingItem(childItem);
1873  }
1874  }
1875 }
1876 
1882 
1883  //Add my quicktree item
1884  idStr qt = GetQuicktreePath(item);
1885  quickTree.Set(qt, item);
1886 
1887  CTreeCtrl& tree = GetTreeCtrl();
1888  if(tree.ItemHasChildren(item)) {
1889  HTREEITEM childItem = tree.GetChildItem(item);
1890  while(childItem != NULL) {
1891  DWORD childType = tree.GetItemData(childItem);
1892  if(childType == TYPE_MATERIAL_FOLDER) {
1893  //Recursively call this method for all my child folders
1894  BuildLookupTrees(childItem);
1895  }
1896  childItem = tree.GetNextSiblingItem(childItem);
1897  }
1898  }
1899 }
1900 
1906  CTreeCtrl& tree = GetTreeCtrl();
1907 
1908  idStr qt = "";
1909  HTREEITEM pathItem = item;
1910  while(pathItem != NULL) {
1911  qt = "/" + idStr(tree.GetItemText(pathItem)) + qt;
1912  pathItem = tree.GetParentItem(pathItem);
1913  }
1914  return qt;
1915 }
1916 
1917 
1918 
1919 
1920 
1921 
1922 
1923 
1924 
1925 
1926 
#define HOVER_EXPAND_DELAY
#define IDR_ME_MATERIALTREE_POPUP
#define strcmp
Definition: Str.h:41
bool IsCopyMaterial()
Returns true if there is a material in the copy buffer.
Undo/Redo operation for adding material folders.
#define stricmp
Definition: Str.h:64
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct)
Called by the MFC framework as the view is being created.
virtual BOOL PreTranslateMessage(MSG *pMsg)
Handles the keyboard shortcut for delete.
void ToLower(void)
Definition: Str.h:817
const char * GetFileName(void) const
Definition: DeclManager.h:171
bool modified
Definition: MaterialDoc.h:75
idStr GetUniqueMaterialName(idStr name)
Returns a unique material name given a base name.
afx_msg LRESULT OnRenameMaterialComplete(WPARAM wParam, LPARAM lParam)
This message is sent after the label edit is complete to ensure that the sorting stays consistent...
void DeleteMaterial(MaterialDoc *material, bool addUndo=true)
Deletes a material.
void ApplyAll()
Applies all materials that have been changed.
virtual void MV_OnFileReload(const char *filename)
Called when a file has been reloaded.
idMaterial * renderMaterial
Definition: MaterialDoc.h:72
idStr GetCopyMaterialName()
Returns the name of the material in the copy buffer.
void SaveAllMaterials()
Saves all materials that have been changed.
CONST PIXELFORMATDESCRIPTOR UINT
Definition: win_qgl.cpp:47
#define MSG_RENAME_MATERIAL_COMPLETE
virtual void MV_OnMaterialDelete(MaterialDoc *pMaterial)
Called when a material is deleted.
afx_msg void OnAddMaterial()
Adds a new material.
virtual void MV_OnMaterialSaved(MaterialDoc *pMaterial)
Called when the material changes have been saved.
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
Handles keyboard shortcut for cut, copy and paste.
int Length(void) const
Definition: Str.h:702
void AddStrList(const char *root, idStrList *list, bool includeFile)
Adds a string list of materials to the tree creating the proper hierarchy.
#define ID_POPUP_ADDMATERIAL
DWORD
Definition: win_qgl.cpp:61
#define ID_POPUP_RENAMEMATERIAL
#define ID_POPUP_SAVEMATERIAL
idHashTable< HTREEITEM > quickTree
afx_msg void OnNMRclick(NMHDR *pNMHDR, LRESULT *pResult)
Displays the popup menu.
#define IMAGE_MATERIAL_MOD
void Strip(const char c)
Definition: Str.h:915
idHashTable< HTREEITEM > fileToTree
const char * GetName(void) const
Definition: DeclManager.h:140
#define ID_POPUP_ADDFOLDER
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glext.h:2855
void InitializeMaterialList(bool includeFile=true, const char *filename=NULL)
Clears the tree and rebuilds it.
afx_msg void OnLButtonUp(UINT nFlags, CPoint point)
Handles the end of a drag copy/move when the user releases the left mouse button. ...
virtual ~MaterialTreeView()
Destructor for MaterialTreeView.
#define ID_POPUP_SAVEALL
afx_msg void OnSaveAll()
Save all materials that have been changed.
const char * Left(int len, idStr &result) const
Definition: Str.h:892
virtual void MV_OnMaterialChange(MaterialDoc *pMaterial)
Called when the material has changed but not applied.
void GetMaterialPaths(HTREEITEM item, idList< MaterialTreeItem_t > *list)
Creates a list of material paths for all materials under the provided item.
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
bool applyWaiting
Definition: MaterialDoc.h:76
GLenum GLsizei len
Definition: glext.h:3472
void BuildLookupTrees(HTREEITEM item)
Build the lookup tree for a given item and all of its children.
HTREEITEM AddFolder(const char *name, HTREEITEM parent)
Adds a new material folder.
GLenum GLint x
Definition: glext.h:2849
int i
Definition: process.py:33
#define BOOL
Definition: mprintf.c:71
GLuint GLuint num
Definition: glext.h:5390
Boolean result
int test(char *url)
Definition: lib500.c:3
int Icmp(const char *text) const
Definition: Str.h:667
afx_msg void OnSaveFile()
Saves all materials in the selected file.
void BuildMaterialList(bool includeFile=true, const char *filename=NULL)
Builds the tree of materials.
idStr & BackSlashesToSlashes(void)
Definition: Str.cpp:727
bool DoesFileNeedApply(const char *filename)
Returns true if the specified file needs to be applied and false otherwise.
#define ID_POPUP_APPLYMATERIAL
idStr & StripPath(void)
Definition: Str.cpp:885
afx_msg void OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
Determines if a tree item's label can be edited.
#define IMAGE_FILE_MOD
int Icmpn(const char *text, int n) const
Definition: Str.h:672
#define IMAGE_FILE
void SetItemImage(HTREEITEM item, bool mod, bool apply, bool children)
Sets the appropriate item image based on the state of the item.
void Set(const char *key, Type &value)
Definition: HashTable.h:186
void Sort(cmp_t *compare=(cmp_t *)&idListSortCompare< type >)
Definition: List.h:898
void ExtractFileName(idStr &dest) const
Definition: Str.cpp:921
afx_msg LRESULT OnRenameFolderComplete(WPARAM wParam, LPARAM lParam)
This message is sent after the label edit is complete to actually perform the rename operation...
#define IMAGE_FOLDER
GLuint GLuint GLsizei count
Definition: glext.h:2845
#define ID_POPUP_COPY
Responsible for managing a single material that is being viewed and/or edited.
Definition: MaterialDoc.h:67
void DeleteFolder(HTREEITEM item, bool addUndo=true)
Deletes a given folder.
#define IMAGE_MATERIAL
bool FindNextMaterial(MaterialSearchData_t *searchData)
Searches for a material given the supplied search parameters.
GLuint index
Definition: glext.h:3476
#define MSG_RENAME_FOLDER_COMPLETE
afx_msg void OnPaste()
Performs a paste operation.
void AddMaterialUndoModifier(MaterialModifier *mod, bool clearRedo=true)
Adds an undo operation to the undo buffer.
virtual void MV_OnMaterialNameChanged(MaterialDoc *pMaterial, const char *oldName)
Called when the material name has changed.
void Empty(void)
Definition: Str.h:714
bool CanPaste()
Returns true if the user can paste an item in the copy buffer.
afx_msg void OnCut()
Performs a cut operation.
void PopupMenu(CPoint *pt)
Displays the popup menu with all of the appropriate menu items enabled.
#define IDB_ME_TREEBITMAP
#define NULL
Definition: Lib.h:88
afx_msg void OnTvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
Begins the process of a drag cut/copy.
idStr name
Definition: MaterialDoc.h:71
void SaveFile(const char *filename)
Saves all materials in the specified file.
void SetMaterialName(const char *materialName, bool addUndo=true)
Sets the material name.
bool CanSaveFile()
Returns true if the currently selected file needs to be saved.
afx_msg void OnAddFolder()
Adds a new folder.
MaterialDoc * CreateMaterialDoc(const char *materialName)
Creates a MaterialDoc object for the specified material name.
const char * path
Definition: sws.c:117
bool CanCut()
Returns true if the user can cut the selected item.
HTREEITEM GetNextSeachItem(HTREEITEM item, bool stayInFile)
Returns the next item to search or NULL if there is nothing else to search.
virtual void MV_OnMaterialApply(MaterialDoc *pMaterial)
Called when the material changes have been applied.
idList< MaterialTreeItem_t > affectedMaterials
const char * Right(int len, idStr &result) const
Definition: Str.h:896
bool Remove(const char *key)
Definition: HashTable.h:277
int Find(const char c, int start=0, int end=-1) const
Definition: Str.h:874
void RenameMaterial(HTREEITEM item, const char *originalName)
Handles all of the little problems associated with renaming a folder.
afx_msg void OnApplyAll()
Applies all materials that need to be applied.
void SaveMaterial(MaterialDoc *material)
Saves a single material.
#define ID_POPUP_APPLYALL
idStr GetSaveFilename()
Returns the filename of currently selected file.
void Clear(void)
Definition: HashTable.h:310
bool CanCopy()
Returns true if the user can copy the selected item.
void ApplyMaterial(MaterialDoc *materialDoc)
Applys changes to a material.
Structure used to store the user defined search parameters.
afx_msg void OnMouseMove(UINT nFlags, CPoint point)
Handles mouse movement as an item is being dragged.
#define ID_POPUP_SAVEFILE
void SetSelectedMaterial(idMaterial *material)
Tells the MaterialDocManager which material has been selected for editing.
idDeclManager * declManager
void PasteMaterial(const char *name, const char *filename)
Performs a material paste operation for a material in the copy buffer.
virtual int GetNumDecls(declType_t type)=0
bool Get(const char *key, Type **value=NULL) const
Definition: HashTable.h:214
afx_msg void OnDeleteMaterial()
Deletes a material or material folder.
int Append(const type &obj)
Definition: List.h:646
A tree view of all the materials that have been defined.
#define ID_POPUP_DELETEMATERIAL
IMPLEMENT_DYNCREATE(CCamWnd, CWnd)
bool GetFileName(HTREEITEM item, idStr &out)
Returns the filename of the provided item.
bool IsFileModified(const char *filename)
Returns true if the specified file has been modified.
Structure used associate a material name with a tree item.
idHashTable< HTREEITEM > materialToTree
int Num(void) const
Definition: List.h:265
MaterialDocManager * materialDocManager
Definition: MaterialView.h:143
virtual const idMaterial * MaterialByIndex(int index, bool forceParse=true)=0
int Last(const char c) const
Definition: Str.cpp:452
const GLcharARB * name
Definition: glext.h:3629
#define ID_POPUP_PASTE
afx_msg void OnCopy()
Performs a copy operation.
Definition: Str.h:116
afx_msg void OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
Changes the selected material when the select tree item changes.
bool DoesAnyNeedApply()
Returns true if any material needs to be applied.
const char * c_str(void) const
Definition: Str.h:487
#define FALSE
Definition: mprintf.c:70
void ReloadFile(const char *filename)
Reloads a specified file.
#define ID_POPUP_RELOADFILE
#define IMAGE_MATERIAL_FOLDER
bool CanDelete()
Returns true if the user can delete the selected item.
Undo/Redo operation for renaming a material folder.
#define ID_POPUP_CUT
#define TRUE
Definition: mprintf.c:69
void ApplyFile(const char *filename)
Applies all materials in the specified filename.
void CleanLookupTrees(HTREEITEM item)
Cleans the lookup tables for the provided item and all children.
afx_msg void OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
Makes sure that a rename operation can be performed after a label edit is complete and performs the f...
#define ID_POPUP_APPLYFILE
void AddMaterial(const char *name, const char *filename, const char *sourceText=NULL, bool addUndo=true)
Adds a material.
idStr GetQuicktreePath(HTREEITEM item)
Returns the quicktree path for a given item.
Undo/Redo operation for deleting a material folder.
void CopyMaterial(MaterialDoc *materialDoc=NULL, bool cut=false)
Prepares a material for a copy/cut and paste operations.
afx_msg void OnContextMenu(CWnd *pWnd, CPoint point)
Displays the popup menu.
char * va(const char *fmt,...)
Definition: Str.cpp:1568
CImageList * dragImage
MaterialDoc * GetCurrentMaterialDoc()
afx_msg void OnReloadFile()
Reloads the selected file.
void RenameFolder(HTREEITEM item, const char *name)
Renames a material folder.
afx_msg void OnApplyFile()
Applies all materials in the currently selected file.
afx_msg void OnSaveMaterial()
Saves the selected material.
virtual void MV_OnMaterialAdd(MaterialDoc *pMaterial)
Called when a material is added.
bool IsAnyModified()
Returns true if any material has been modified.
afx_msg void OnRenameMaterial()
Begins a label edit to rename a material or material folder.
afx_msg void OnApplyMaterial()
Applies the current material.
#define IMAGE_MATERIAL_MOD_APPLY
bool CanRename()
Returns true if the user can rename the selected item.
bool FindMaterial(const char *name, MaterialSearchData_t *searchData, bool checkName)
Searches for a material that matches the specified search data.
void Clear(void)
Definition: List.h:184
idStr GetMediaPath(HTREEITEM item, DWORD type)
Returns the Doom III name for the provided item.