// WSpace.cpp // Guy Simmons, 11th August 1998. #include #include #include #include #include #include "resource.h" #include "gi.h" #include "GEdit.h" #include "Mission.h" #include "SubClass.h" #include "WSpace.h" #include "MapView.h" //--------------------------------------------------------------- BOOL workspace_changed = FALSE; CBYTE map_default_dir[_MAX_PATH], map_file_name[_MAX_PATH], map_path_name[_MAX_PATH], mission_name[_MAX_PATH], workspace_dir[_MAX_PATH], workspace_name[_MAX_PATH], workspace_path[_MAX_PATH]; HANDLE image_list; HWND ws_tree,wpt_tree; HTREEITEM last_clicked, selected_mission_doohickey=0; WSElement root_item; extern HINSTANCE GEDIT_hinstance; extern BOOL map_valid; // The camera. extern SLONG cam_x, cam_y, cam_z, cam_yaw, cam_pitch, cam_focus_x, cam_focus_z, cam_focus_dist, cam_matrix[9], cam_forward[3], cam_left[3]; // The mouse. extern SLONG mouse_valid, mouse_over, mouse_world_x, mouse_world_y, mouse_world_z, mouse_waypoint; void calc_camera_pos(void); void remove_children(HTREEITEM parent); //--------------------------------------------------------------- BOOL init_workspace(HWND parent) { TV_INSERTSTRUCT tv_is; // Subclass the tree control windproc. ws_tree = GetDlgItem(parent,IDC_WORKSPACE_TREE); tree_proc = (WNDPROC)SetWindowLong(ws_tree,GWL_WNDPROC,(long)sc_tree_proc); // Set up the trees image list. image_list = ImageList_LoadBitmap( GEDIT_hinstance, MAKEINTRESOURCE(IDB_WORKSPACE), 16, 1, RGB (255, 0, 255) ); /* image_list = ImageList_LoadImage(GEDIT_hinstance,MAKEINTRESOURCE(IDB_WORKSPACE2),16,1, RGB(255,0,255),IMAGE_BITMAP,LR_DEFAULTCOLOR);*/ TreeView_SetImageList(ws_tree,image_list,TVSIL_NORMAL); // Setup working directories. sprintf(workspace_dir,"c:\\Fallen\\Editor"); sprintf(map_default_dir,"c:\\Fallen\\Data"); // Set up the tree root. tv_is.hParent = TVI_ROOT; tv_is.hInsertAfter = TVI_FIRST; tv_is.item.mask = TVIF_TEXT|TVIF_PARAM; tv_is.item.pszText = "Workspace : NONE"; tv_is.item.lParam = (LPARAM)&root_item; root_item.TreeItem = TreeView_InsertItem(ws_tree,&tv_is); root_item.ElementType = ET_NONE; // Set the workspace state & corresponding menus. workspace_changed = FALSE; menu_no_workspace(); return TRUE; } //--------------------------------------------------------------- void fini_workspace(void) { } //--------------------------------------------------------------- BOOL get_element_at_point(POINT *click_point,WSElement **the_element) { HTREEITEM item_handle; TV_HITTESTINFO hit_test; TV_ITEM the_item; // Validate the parameters. if(click_point && the_element) { // Check to see if we clicked on a tree item. hit_test.pt = *click_point; ScreenToClient(ws_tree,&hit_test.pt); item_handle = TreeView_HitTest(ws_tree,&hit_test); if(item_handle && hit_test.flags&TVHT_ONITEM) { // Yes, so get a pointer to its WSElement structure. the_item.hItem = item_handle; the_item.mask = TVIF_PARAM; if(TreeView_GetItem(ws_tree,&the_item)) { *the_element = (WSElement*)the_item.lParam; if(*the_element) { last_clicked=item_handle; return TRUE; } } } } return FALSE; } //--------------------------------------------------------------- void handle_ws_context(POINT *click_point) { HMENU ws_menu; WSElement *the_element; // Validate the parameters. if(ws_tree && click_point) { if(get_element_at_point(click_point,&the_element)) { // Select the item. TreeView_Select(ws_tree,the_element->TreeItem,TVGN_CARET); if (the_element->ElementType==ET_LMAP) return; // Bring up the relevent context menu. ws_menu = GetSubMenu(LoadMenu(GEDIT_hinstance,MAKEINTRESOURCE(IDR_GEDIT_POPUPS)),the_element->ElementType-1); TrackPopupMenu ( ws_menu, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, click_point->x,click_point->y, 0,ws_tree,NULL ); DestroyMenu(ws_menu); } } } //--------------------------------------------------------------- BOOL handle_ws_dblclk(POINT *click_point) { // CBYTE item_text[_MAX_PATH]; // TV_ITEM the_item; WSElement *the_element; HTREEITEM next; // Validate the parameters. if(ws_tree && click_point) { if(get_element_at_point(click_point,&the_element)) { switch(the_element->ElementType) { case ET_NONE: break; case ET_ROOT: break; case ET_MAP: // Expand the workspace TreeView_Expand(ws_tree,last_clicked,TVE_EXPAND); // Set the 'busy' cursor. SetCursor(GEDIT_busy); // Try to open the map. SetCurrentDirectory("c:\\Fallen"); //GI_init(); map_valid = GI_load_map(current_map->MapName); if(map_valid) { // Default setup for map view. cam_focus_x = 64 << 8; cam_focus_z = 64 << 8; cam_focus_dist = 14 << 8; cam_pitch = 1600; cam_yaw = 0; calc_camera_pos(); GI_render_view_into_backbuffer ( cam_x, cam_y, cam_z, cam_yaw, cam_pitch, 0 ); } // Set the 'arrow' cursor. SetCursor(GEDIT_arrow); // Select the first mission (if present) next=TreeView_GetChild(ws_tree,last_clicked); if (next) TreeView_SelectItem(ws_tree,next); return TRUE; case ET_MISSION: break; case ET_LMAP: break; case ET_WAYPOINT: break; case ET_BRIEF: break; } } } return FALSE; } //--------------------------------------------------------------- void handle_ws_select(WSElement *the_element) { switch(the_element->ElementType) { case ET_NONE: break; case ET_ROOT: break; case ET_MAP: current_map = &game_maps[the_element->MapRef]; break; case ET_MISSION: if ( current_map && MAP_NUMBER(current_map)==TO_MISSION(the_element->MissionRef)->MapIndex ) { TVITEM item; // clear old bold item.mask=TVIF_STATE|TVIF_HANDLE; item.stateMask=TVIS_BOLD; if (selected_mission_doohickey) { item.hItem=selected_mission_doohickey; item.state=0; TreeView_SetItem(ws_tree,&item); } // set new bold item.hItem=the_element->TreeItem; item.state=TVIS_BOLD; TreeView_SetItem(ws_tree,&item); current_mission = &mission_pool[the_element->MissionRef]; selected_mission_doohickey = the_element->TreeItem; reset_wptlist(); fill_wptlist(current_mission); } else { // We probably need to prompt here, to open the missions associated map. // current_mission = NULL; current_mission = &mission_pool[the_element->MissionRef]; } break; case ET_LMAP: break; case ET_WAYPOINT: break; case ET_BRIEF: break; } } //--------------------------------------------------------------- void ws_add_map(void) { CBYTE *text_buffer; UWORD item_count, new_map; HTREEITEM map_item; OPENFILENAME open_map; TV_INSERTSTRUCT tv_is; TV_ITEM map_info; WSElement *new_element; // Set up the open file structure. ZeroMemory(&open_map,sizeof(OPENFILENAME)); open_map.lStructSize = sizeof(OPENFILENAME); open_map.hwndOwner = NULL; open_map.lpstrFilter = "Game map files\0*.iam\0\0"; open_map.lpstrFile = map_path_name; open_map.nMaxFile = _MAX_PATH; open_map.lpstrFileTitle = map_file_name; open_map.nMaxFileTitle = _MAX_PATH; open_map.lpstrInitialDir = map_default_dir; open_map.lpstrTitle = "Load a game map"; open_map.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; open_map.lpstrDefExt = "iam"; if(GetOpenFileName(&open_map)) { // Check to see if this map is part of the workspace. text_buffer = (CBYTE*)malloc(_MAX_PATH); map_item = TreeView_GetChild(ws_tree,root_item.TreeItem); while(map_item) { map_info.mask = TVIF_TEXT; map_info.hItem = map_item; map_info.pszText = text_buffer; map_info.cchTextMax = _MAX_PATH; TreeView_GetItem(ws_tree,&map_info); if(!strcmp(map_file_name,text_buffer)) { // Yes, so show a message & get outta here. MessageBox ( NULL, "This map is already part of the workspace", "DOH!!", MB_OK ); free(text_buffer); return; } // Get next sibling. map_item = TreeView_GetNextSibling(ws_tree,map_item); } free(text_buffer); // No, so find a spare map structure. new_map = alloc_map(); if(new_map) { // Set up the new map structure. strcpy(game_maps[new_map].MapName,"Data\\"); strcat(game_maps[new_map].MapName,map_file_name); // Now add it to the workspace root. new_element = new WSElement; if(new_element) { tv_is.hParent = root_item.TreeItem; tv_is.hInsertAfter = TVI_LAST; tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM; tv_is.item.iImage = IM_MAP; tv_is.item.iSelectedImage = IM_MAP; tv_is.item.pszText = map_file_name; tv_is.item.lParam = (LPARAM)new_element; new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_MAP; new_element->MapRef = new_map; // Expand the root if this is the first map to be added. item_count = TreeView_GetCount(ws_tree); if(item_count<=2) TreeView_Expand(ws_tree,root_item.TreeItem,TVE_EXPAND); // Update the window. InvalidateRect(ws_tree, NULL, FALSE); } } else { // Error no more maps. MessageBox ( NULL, "Run out of Map structures.\n\nClick OK, save your work & then tell Guy.", "Oh bugger!!", MB_OK ); } } } //--------------------------------------------------------------- BOOL CALLBACK new_mish_proc ( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch(message) { case WM_INITDIALOG: // Make sure the edit control has the focus. SetFocus(GetDlgItem(hWnd,IDC_EDIT_MNAME)); return FALSE; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: EndDialog(hWnd,TRUE); return TRUE; case IDCANCEL: EndDialog(hWnd,FALSE); return TRUE; case IDC_EDIT_MNAME: if(HIWORD(wParam)==EN_CHANGE) { // The user has changed the text, if there's any // text in the control enable the 'Ok' button else // disable it. if(GetWindowText((HWND)lParam,mission_name,_MAX_PATH)) EnableWindow(GetDlgItem(hWnd,IDOK),TRUE); else EnableWindow(GetDlgItem(hWnd,IDOK),FALSE); return TRUE; } break; } break; } return FALSE; } //--------------------------------------------------------------- void ws_new_mission(void) { UWORD new_mission; HTREEITEM map_handle; TV_INSERTSTRUCT tv_is; TV_ITEM map_item; WSElement *map_element, *new_element; // First get the parent map info. map_handle = TreeView_GetSelection(ws_tree); map_item.hItem = map_handle; map_item.mask = TVIF_PARAM; TreeView_GetItem(ws_tree,&map_item); map_element = (WSElement*)map_item.lParam; // Now find a spare mission structure. new_mission = alloc_mission(map_element->MapRef); if(new_mission) { // Bring up a dialog box for the user to enter the mission name. if ( DialogBox ( GEDIT_hinstance, MAKEINTRESOURCE(IDD_NEWMISSION), ws_tree, (DLGPROC)new_mish_proc ) ) { // Set up the mission structure. init_mission(new_mission,mission_name); // Now create the new mission. new_element = new WSElement; if(new_element) { tv_is.hParent = map_handle; tv_is.hInsertAfter = TVI_LAST; tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM; tv_is.item.iImage = IM_MISSION; tv_is.item.iSelectedImage = IM_MISSION; tv_is.item.pszText = mission_name; tv_is.item.lParam = (LPARAM)new_element; new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_MISSION; new_element->MapRef = map_element->MapRef; new_element->MissionRef = new_mission; // Update the window. InvalidateRect(ws_tree, NULL, FALSE); } } } else { // Error no more missions. MessageBox ( NULL, "Run out of Mission structures.\n\nClick OK, save your work & then tell Guy.", "Oh bugger!!", MB_OK ); } } //--------------------------------------------------------------- void ws_del_mission(void) { HTREEITEM current = TreeView_GetSelection(ws_tree); SLONG c1; for(c1=0;c1EventPoints[c1].Used) free_eventpoint(¤t_mission->EventPoints[c1]); ZeroMemory(current_mission,sizeof(Mission)); current_mission=NULL; // hmm remove_children(current); } //--------------------------------------------------------------- void ws_add_light_map(void) { CBYTE temp[_MAX_PATH]; OPENFILENAME open_map; TV_INSERTSTRUCT tv_is; WSElement *new_element; // Set up the open file structure. sprintf(current_mission->LightMapName,"*.lgt"); ZeroMemory(&open_map,sizeof(OPENFILENAME)); open_map.lStructSize = sizeof(OPENFILENAME); open_map.hwndOwner = NULL; open_map.lpstrFilter = "Light Map files\0*.lgt\0\0"; // open_map.lpstrFile = current_mission->LightMapName; // open_map.nMaxFile = _MAX_PATH; open_map.lpstrFileTitle = temp; open_map.nMaxFileTitle = _MAX_PATH; open_map.lpstrInitialDir = map_default_dir; open_map.lpstrTitle = "Load a light map"; open_map.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; open_map.lpstrDefExt = "lgt"; if(GetOpenFileName(&open_map)) { strcpy(current_mission->LightMapName,"Data\\Lighting\\"); strcat(current_mission->LightMapName,temp); // Add it to the mission root. new_element = new WSElement; if(new_element) { tv_is.hParent = TreeView_GetSelection(ws_tree); tv_is.hInsertAfter = TVI_LAST; tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM; tv_is.item.iImage = IM_LMAP; tv_is.item.iSelectedImage = IM_LMAP; tv_is.item.pszText = temp; tv_is.item.lParam = (LPARAM)new_element; new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_LMAP; // Update the window. InvalidateRect(ws_tree, NULL, FALSE); } } } //--------------------------------------------------------------- void ws_add_citsez_map(void) { CBYTE temp[_MAX_PATH]; OPENFILENAME open_map; TV_INSERTSTRUCT tv_is; WSElement *new_element; // Set up the open file structure. sprintf(current_mission->CitSezMapName,"*.txt"); ZeroMemory(&open_map,sizeof(OPENFILENAME)); open_map.lStructSize = sizeof(OPENFILENAME); open_map.hwndOwner = NULL; open_map.lpstrFilter = "Text files\0*.txt\0\0"; open_map.lpstrFile = current_mission->CitSezMapName; open_map.nMaxFile = _MAX_PATH; open_map.lpstrFileTitle = temp; open_map.nMaxFileTitle = _MAX_PATH; open_map.lpstrInitialDir = "c:\\fallen\\text\\"; open_map.lpstrTitle = "Load a Citizen-Sez text file"; open_map.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; open_map.lpstrDefExt = "txt"; if(GetOpenFileName(&open_map)) { strcpy(current_mission->CitSezMapName,"Text\\"); strcat(current_mission->CitSezMapName,temp); // Add it to the mission root. new_element = new WSElement; if(new_element) { tv_is.hParent = TreeView_GetSelection(ws_tree); tv_is.hInsertAfter = TVI_LAST; tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM; tv_is.item.iImage = IM_SEWER; tv_is.item.iSelectedImage = IM_SEWER; tv_is.item.pszText = temp; tv_is.item.lParam = (LPARAM)new_element; new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_LMAP; // Update the window. InvalidateRect(ws_tree, NULL, FALSE); } } } //--------------------------------------------------------------- BOOL create_workspace(void) { int result; CBYTE temp[_MAX_PATH]; OPENFILENAME save_workspace; TV_ITEM set_item; if(workspace_changed) { // Ask the user to save etc. result = MessageBox ( NULL, "Changes have been made to the current workspace.\nDo you want to save?", "Urban Chaos Mission Editor", MB_ICONQUESTION|MB_YESNOCANCEL ); if(result==IDCANCEL) { return FALSE; } else if(result==IDYES) { // save_workspace(); } } // Set up the default directory & file name. sprintf(workspace_path,"*.ucw"); // Set up the save file structure. ZeroMemory(&save_workspace,sizeof(OPENFILENAME)); save_workspace.lStructSize = sizeof(OPENFILENAME); save_workspace.hwndOwner = NULL; save_workspace.lpstrFilter = "Editor Workspace Files\0*.ucw\0\0"; save_workspace.lpstrFile = workspace_path; save_workspace.nMaxFile = _MAX_PATH; save_workspace.lpstrFileTitle = workspace_name; save_workspace.nMaxFileTitle = _MAX_PATH; save_workspace.lpstrInitialDir = workspace_dir; save_workspace.lpstrTitle = "Create a new Workspace"; save_workspace.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; save_workspace.lpstrDefExt = "ucw"; if(GetOpenFileName(&save_workspace)) { // Change the root item. sprintf(temp,"Workspace : %s",workspace_name); set_item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT; set_item.hItem = root_item.TreeItem; set_item.pszText = temp; set_item.iImage = IM_ROOT; set_item.iSelectedImage = IM_ROOT; root_item.ElementType = ET_ROOT; TreeView_SetItem(ws_tree,&set_item); // Set the workspace state & corresponding menus. workspace_changed = TRUE; menu_has_workspace(); } return TRUE; } //--------------------------------------------------------------- BOOL close_workspace(void) { int result; UWORD c0,c1; Mission *the_mission; TV_ITEM set_item; if(workspace_changed) { // Ask the user to save etc. result = MessageBox ( NULL, "Changes have been made to the workspace.\nDo you want to save?", "Urban Chaos Mission Editor", MB_ICONQUESTION|MB_YESNOCANCEL ); if(result==IDCANCEL) { return FALSE; } else if(result==IDYES) { save_workspace(); } } // Remove eveything from the tree. remove_children(TreeView_GetRoot(ws_tree)); // Go thru' the missions & clear out ep data. for(c0=0;c0EventPoints[c1].Used) free_eventpoint(&the_mission->EventPoints[c1]); } } MISSION_init(); // Reset the root item. set_item.mask = TVIF_TEXT; set_item.hItem = root_item.TreeItem; set_item.pszText = "Workspace : NONE"; root_item.ElementType = ET_NONE; TreeView_SetItem(ws_tree,&set_item); // Setup the workspace state & corresponding menus. workspace_changed = FALSE; menu_no_workspace(); return TRUE; } //--------------------------------------------------------------- BOOL load_workspace(BOOL try_loading_default) { int result; CBYTE temp[_MAX_PATH]; UBYTE gm_vers; UWORD item_count; ULONG c0,c1, count, ep_count, size; FILE *file_handle; HTREEITEM current_item, map_handle, mission_handle; OPENFILENAME load_workspace; TV_INSERTSTRUCT tv_is; TV_ITEM set_item; WSElement *map_element, *new_element; if(workspace_changed) { // Ask the user to save etc. result = MessageBox ( NULL, "Changes have been made to the current workspace.\nDo you want to save?", "Urban Chaos Mission Editor", MB_ICONQUESTION|MB_YESNOCANCEL ); if(result==IDCANCEL) { return FALSE; } else if(result==IDYES) { save_workspace(); } } // Clean up. close_workspace(); workspace_path[0] = '\000'; CBYTE curr_directory[_MAX_PATH]; GetCurrentDirectory(_MAX_PATH, curr_directory); if (try_loading_default) { FILE *handle = fopen("last_workspace.ini", "rb"); if (handle) { fread(workspace_path, 1, _MAX_PATH, handle); fclose(handle); } } if (workspace_path[0] == '\000') { // Set up the default directory & file name. sprintf(workspace_path,"*.ucw"); // Set up the save file structure. ZeroMemory(&load_workspace,sizeof(OPENFILENAME)); load_workspace.lStructSize = sizeof(OPENFILENAME); load_workspace.hwndOwner = NULL; load_workspace.lpstrFilter = "Editor Workspace Files\0*.ucw\0\0"; load_workspace.lpstrFile = workspace_path; load_workspace.nMaxFile = _MAX_PATH; load_workspace.lpstrFileTitle = workspace_name; load_workspace.nMaxFileTitle = _MAX_PATH; load_workspace.lpstrInitialDir = workspace_dir; load_workspace.lpstrTitle = "Open a Workspace"; load_workspace.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; load_workspace.lpstrDefExt = "ucw"; if (!GetOpenFileName(&load_workspace)) { return FALSE; } } // Load the workspace. SetCurrentDirectory(curr_directory); { file_handle = fopen(workspace_path,"rb"); if(file_handle) { { // // Make this the default workspace to load next time. // FILE *handle = fopen("last_workspace.ini", "wb"); if (handle) { fwrite(workspace_path, 1, _MAX_PATH, handle); fclose(handle); } } // Read the file version. fread(&gm_vers,sizeof(gm_vers),1,file_handle); // Read the number of game maps & the structure size. fread(&count,sizeof(count),1,file_handle); fread(&size,sizeof(size),1,file_handle); // Read in the maps. for(c0=0;c0TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_MAP; new_element->MapRef = (UWORD)c0; // Expand the root if this is the first map to be added. item_count = TreeView_GetCount(ws_tree); if(item_count<=2) TreeView_Expand(ws_tree,root_item.TreeItem,TVE_EXPAND); } } } // Read the number of missions, number of event points & the structure size. fread(&count,sizeof(count),1,file_handle); fread(&ep_count,sizeof(ep_count),1,file_handle); fread(&size,sizeof(size),1,file_handle); // Read the missions. for(c0=0;c0WaypointType==WPT_CREATE_ENEMIES) { ep->Data[0]=MAKELONG(ep->Data[0],ep->Data[1]); ep->Data[1]=0; } } } // if (gm_vers<10) mission_pool[c0].BoredomRate=4; if (!mission_pool[c0].BoredomRate) mission_pool[c0].BoredomRate=4; // Set up eventpoint data areas. for(c1=0;c1MapRef) { map_handle = current_item; break; } current_item = TreeView_GetNextSibling(ws_tree,current_item); } // Now add it to the tree. if(map_element && map_handle) { new_element = new WSElement; if(new_element) { tv_is.hParent = map_handle; tv_is.hInsertAfter = TVI_LAST; tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM; tv_is.item.iImage = IM_MISSION; tv_is.item.iSelectedImage = IM_MISSION; tv_is.item.pszText = mission_pool[c0].MissionName; tv_is.item.lParam = (LPARAM)new_element; new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_MISSION; new_element->MapRef = map_element->MapRef; new_element->MissionRef = (UWORD)c0; mission_handle = new_element->TreeItem; } // Add the light map. if(mission_pool[c0].LightMapName[0]) { new_element = new WSElement; if(new_element) { tv_is.hParent = mission_handle; tv_is.hInsertAfter = TVI_LAST; tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM; tv_is.item.iImage = IM_LMAP; tv_is.item.iSelectedImage = IM_LMAP; tv_is.item.pszText = &mission_pool[c0].LightMapName[5]; // Assumes name always has 'Data\' preceding it. tv_is.item.lParam = (LPARAM)new_element; new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_LMAP; } } // Add the sewer map. if(mission_pool[c0].CitSezMapName[0]) { new_element = new WSElement; if(new_element) { tv_is.hParent = mission_handle; tv_is.hInsertAfter = TVI_LAST; tv_is.item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT|TVIF_PARAM; tv_is.item.iImage = IM_SEWER; tv_is.item.iSelectedImage = IM_SEWER; tv_is.item.pszText = &mission_pool[c0].CitSezMapName[5]; tv_is.item.lParam = (LPARAM)new_element; new_element->TreeItem = TreeView_InsertItem(ws_tree,&tv_is); new_element->ElementType = ET_LMAP; } } } } if (gm_vers>=3) { // includes zoning info fread(MissionZones[c0],128*128,1,file_handle); } } // Force a redraw on the workspace tree. InvalidateRect(ws_tree, NULL, FALSE); // Change the root item. sprintf(temp,"Workspace : %s",workspace_name); set_item.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT; set_item.hItem = root_item.TreeItem; set_item.pszText = temp; set_item.iImage = IM_ROOT; set_item.iSelectedImage = IM_ROOT; root_item.ElementType = ET_ROOT; TreeView_SetItem(ws_tree,&set_item); // Set the workspace state & corresponding menus. workspace_changed = FALSE; menu_has_workspace(); fclose(file_handle); return TRUE; } } return FALSE; } //--------------------------------------------------------------- #define GM_VERSION 8 BOOL save_workspace(void) { UBYTE gm_vers; ULONG c0,c1, data; FILE *file_handle; // EventPoint *ep_base; // Set the 'busy' cursor. SetCursor(GEDIT_busy); // Save the workspace. file_handle = fopen(workspace_path,"wb"); if(file_handle) { // Save the file version. gm_vers = GM_VERSION; fwrite(&gm_vers,sizeof(gm_vers),1,file_handle); // Save the number of game maps & the structure size. data = MAX_MAPS; fwrite(&data,sizeof(data),1,file_handle); data = sizeof(GameMap); fwrite(&data,sizeof(data),1,file_handle); // Save the maps. fwrite(&game_maps,sizeof(GameMap),MAX_MAPS,file_handle); // Save the number of missions, the number of event points & the structure size. data = MAX_MISSIONS; fwrite(&data,sizeof(data),1,file_handle); data = MAX_EVENTPOINTS; fwrite(&data,sizeof(data),1,file_handle); data = sizeof(Mission); fwrite(&data,sizeof(data),1,file_handle); // Save the missions. for(c0=0;c0UsedEPoints; EventPoint *ep_base = mish->EventPoints; EventPoint *ep; while(ndx) { ep = TO_EVENTPOINT(ep_base,ndx); ws_add_waypoint(ep); ndx= ep->Next; } } void fini_wptlist(void) { } //--------------------------------------------------------------- HTREEITEM ws_root_waypoint(CBYTE *msg, SLONG type, LPARAM param) { TV_INSERTSTRUCT tv_is; if (msg[0]==0) { switch(param) { case 0: strcpy(msg,"Create Player"); type=IM_PLAYER; break; case 1: strcpy(msg,"Enemies"); type=IM_COP; break; case 2: strcpy(msg,"Items"); type=IM_ITEM; break; case 3: strcpy(msg,"Traps"); type=IM_TRAP; break; case 4: strcpy(msg,"Cameras"); type=IM_CAMERA; break; case 5: strcpy(msg,"Misc"); type=IM_WAYPOINT; break; case 6: strcpy(msg,"Map exits"); type=IM_MAPEXIT; break; case 7: strcpy(msg,"Text messages"); type=IM_MESSAGE; break; } } tv_is.hParent = TVI_ROOT; tv_is.hInsertAfter = TVI_SORT; tv_is.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE; tv_is.item.stateMask = TVIS_STATEIMAGEMASK; tv_is.item.state = 0; tv_is.item.pszText = msg; tv_is.item.lParam = param; tv_is.item.iImage = tv_is.item.iSelectedImage = type; return TreeView_InsertItem(wpt_tree,&tv_is); } HTREEITEM ws_find_child(HTREEITEM parent, LPARAM param) { HTREEITEM kid; TVITEM item; if (parent) kid=TreeView_GetChild(wpt_tree,parent); else kid=TreeView_GetRoot(wpt_tree); while (kid) { item.mask=TVIF_HANDLE; item.hItem=kid; TreeView_GetItem(wpt_tree,&item); if (item.lParam==param) return kid; kid=TreeView_GetNextSibling(wpt_tree,kid); } return 0; } SLONG ws_image_from_type(EventPoint *ep) { switch(ep->WaypointType) { case WPT_NONE: case WPT_SIMPLE: case WPT_CREATE_VEHICLE: case WPT_VISUAL_EFFECT: case WPT_END_GAME_LOSE: case WPT_END_GAME_WIN: case WPT_SHOUT: case WPT_NAV_BEACON: case WPT_CUT_SCENE: case WPT_TELEPORT: case WPT_TELEPORT_TARGET: case WPT_ACTIVATE_PRIM: case WPT_LINK_PLATFORM: case WPT_BURN_PRIM: case WPT_SPOT_EFFECT: case WPT_INTERESTING: case WPT_MAKE_SEARCHABLE: case WPT_LOCK_VEHICLE: case WPT_STALL_CAR: case WPT_EXTEND: case WPT_MOVE_THING: case WPT_CONE_PENALTIES: case WPT_SIGN: case WPT_NO_FLOOR: case WPT_SHAKE_CAMERA: return IM_WAYPOINT; case WPT_CREATE_PLAYER: return IM_PLAYER; case WPT_CREATE_ENEMIES: case WPT_ADJUST_ENEMY: case WPT_CREATE_CREATURE: return IM_COP; case WPT_MESSAGE: case WPT_CONVERSATION: return IM_MESSAGE; case WPT_CREATE_ITEM: case WPT_CREATE_BARREL: return IM_ITEM; case WPT_CREATE_CAMERA: case WPT_CREATE_TARGET: case WPT_CAMERA_WAYPOINT: case WPT_TARGET_WAYPOINT: return IM_CAMERA; case WPT_CREATE_MAP_EXIT: return IM_MAPEXIT; case WPT_SOUND_EFFECT: case WPT_WAREFX: return IM_SOUND; case WPT_CREATE_TRAP: case WPT_KILL_WAYPOINT: return IM_TRAP; case WPT_CREATE_BOMB: return IM_BOMB; default: return IM_WAYPOINT; } return -1; } SLONG ws_category_from_type(EventPoint *ep) { switch(ep->WaypointType) { // misc case WPT_NONE: case WPT_SIMPLE: case WPT_CREATE_VEHICLE: case WPT_VISUAL_EFFECT: case WPT_END_GAME_WIN: case WPT_END_GAME_LOSE: case WPT_SHOUT: case WPT_CUT_SCENE: case WPT_TELEPORT: case WPT_TELEPORT_TARGET: case WPT_ACTIVATE_PRIM: case WPT_SOUND_EFFECT: case WPT_SPOT_EFFECT: case WPT_DYNAMIC_LIGHT: case WPT_LINK_PLATFORM: case WPT_NAV_BEACON: case WPT_BURN_PRIM: case WPT_KILL_WAYPOINT: case WPT_GROUP_LIFE: case WPT_GROUP_DEATH: case WPT_INTERESTING: case WPT_GOTHERE_DOTHIS: case WPT_MAKE_SEARCHABLE: case WPT_LOCK_VEHICLE: case WPT_GROUP_RESET: case WPT_COUNT_UP_TIMER: case WPT_CREATE_MIST: case WPT_STALL_CAR: case WPT_MOVE_THING: case WPT_EXTEND: case WPT_CONE_PENALTIES: case WPT_SIGN: case WPT_WAREFX: case WPT_SHAKE_CAMERA: case WPT_NO_FLOOR: return 5; // texty things case WPT_MESSAGE: case WPT_CONVERSATION: return 7; // player case WPT_CREATE_PLAYER: case WPT_AUTOSAVE: return 0; // enemies case WPT_CREATE_ENEMIES: case WPT_ADJUST_ENEMY: case WPT_CREATE_CREATURE: case WPT_ENEMY_FLAGS: return 1; // items case WPT_CREATE_ITEM: case WPT_CREATE_BARREL: case WPT_CREATE_TREASURE: case WPT_BONUS_POINTS: return 2; // cam stuff case WPT_CREATE_CAMERA: case WPT_CREATE_TARGET: case WPT_CAMERA_WAYPOINT: case WPT_TARGET_WAYPOINT: return 4; // exits case WPT_CREATE_MAP_EXIT: return 6; // traps case WPT_CREATE_TRAP: case WPT_CREATE_BOMB: return 3; default: return 5; // misc } return -1; } void ws_add_waypoint(EventPoint *ep) { HTREEITEM parent; SLONG code; TV_INSERTSTRUCT tv_is; CBYTE msg[800]; if (!ep->Used) return; msg[0]=0; parent=ws_find_child(0,code=ws_category_from_type(ep)); if (code==-1) return; if (!parent) parent=ws_root_waypoint(msg, 0, code); tv_is.hParent = parent; tv_is.hInsertAfter = TVI_SORT; tv_is.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_STATE; tv_is.item.stateMask = TVIS_STATEIMAGEMASK; if (ep->Flags&WPT_FLAGS_SUCKS) tv_is.item.state = INDEXTOSTATEIMAGEMASK(IM_BROKEN); else tv_is.item.state = 0; tv_is.item.pszText = WaypointTitle(ep, msg); tv_is.item.lParam = (LPARAM)ep; tv_is.item.iImage = tv_is.item.iSelectedImage = ws_image_from_type(ep); TreeView_InsertItem(wpt_tree,&tv_is); // double check -- if this one sucks, it's parent sucks too, to help find suckage. if (ep->Flags&WPT_FLAGS_SUCKS) { tv_is.item.hItem = parent; tv_is.item.mask = TVIF_HANDLE|TVIF_STATE; tv_is.item.stateMask = TVIS_STATEIMAGEMASK; tv_is.item.state = INDEXTOSTATEIMAGEMASK(IM_BROKEN); TreeView_SetItem(wpt_tree,&tv_is.item); } } void ws_set_waypoint(EventPoint *ep, CBYTE ndx) { // HTREEITEM item; // item=ws_find_child(0,ws_category_from_type(ep)); if (ep->WaypointType!=ndx) { ws_del_waypoint(ep); ep->WaypointType=ndx; ws_add_waypoint(ep); } /* if (item) { item=ws_find_child(item,(LPARAM)ep); if (ep->WaypointType!=ndx) { ep->WaypointType=ndx; TreeView_DeleteItem(wpt_tree,item); ws_add_waypoint(ep); } }*/ } void ws_sel_waypoint(EventPoint *ep) { HTREEITEM item; if (!ep) { TreeView_SelectItem(wpt_tree,0); return; } item=ws_find_child(0,ws_category_from_type(ep)); if (item) { item=ws_find_child(item,(LPARAM)ep); TreeView_SelectItem(wpt_tree,item); } } void ws_del_waypoint(EventPoint *ep) { HTREEITEM parent,item; parent=ws_find_child(0,ws_category_from_type(ep)); if (parent) { item=ws_find_child(parent,(LPARAM)ep); if (item) TreeView_DeleteItem(wpt_tree,item); item=TreeView_GetChild(wpt_tree,parent); if (!item) TreeView_DeleteItem(wpt_tree,parent); } }