void gr_opengl_recompile_all_shaders(const std::function<void(size_t, size_t)>& progress_callback) { for (auto sdr = GL_shader.begin(); sdr != GL_shader.end(); ++sdr) { if (progress_callback) progress_callback(std::distance(GL_shader.begin(), sdr), GL_shader.size()); sdr->program.reset(); opengl_compile_shader_actual(sdr->shader, sdr->flags, *sdr); } }
void waypoint_add_list(const char *name, SCP_vector<vec3d> &vec_list) { Assert(name != NULL); if (find_matching_waypoint_list(name) != NULL) { Warning(LOCATION, "Waypoint list '%s' already exists in this mission! Not adding the new list...", name); return; } waypoint_list new_list(name); Waypoint_lists.push_back(new_list); waypoint_list *wp_list = &Waypoint_lists.back(); wp_list->get_waypoints().reserve(vec_list.size()); SCP_vector<vec3d>::iterator ii; for (ii = vec_list.begin(); ii != vec_list.end(); ++ii) { waypoint new_waypoint(&(*ii), wp_list); wp_list->get_waypoints().push_back(new_waypoint); } // so that masking in the other function works // though if you actually hit this Assert, you have other problems Assert(wp_list->get_waypoints().size() <= 0xffff); }
int gamesnd_get_by_iface_name(const char* name) { Assert( Snds_iface.size() <= INT_MAX ); Assert( Snds_iface.size() == Snds_iface_handle.size() ); int index = gamesnd_lookup_name(name, Snds_iface); if (index < 0) { int i = 0; for(SCP_vector<game_snd>::iterator snd = Snds_iface.begin(); snd != Snds_iface.end(); ++snd) { char *p = strrchr( snd->filename, '.' ); if(p == NULL) { if(!stricmp(snd->filename, name)) { index = i; break; } } else if(!strnicmp(snd->filename, name, p-snd->filename)) { index = i; break; } i++; } } return index; }
// marks a cutscene as viewable void cutscene_mark_viewable(char *filename) { char cut_file[MAX_FILENAME_LEN]; char file[MAX_FILENAME_LEN]; Assert(filename!=NULL); // strip off extension strcpy_s( file, filename ); char *p = strchr( file, '.' ); if ( p ) { *p = 0; } // change to lower case strlwr(file); int i = 0; for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) { // change the cutscene file name to lower case strcpy_s(cut_file, cut->filename); strlwr(cut_file); // see if the stripped filename matches the cutscene filename if ( strstr(cut_file, file) != NULL ) { cut->viewable = true; return; } i++; } }
/* * Update any uninitialized EnhancedSoundData in Snds * with hardcoded defaults for retail. */ void gamesnd_add_retail_default_enhanced_sound_data() { int i = 0; for (SCP_vector<game_snd>::iterator it = Snds.begin(), end = Snds.end(); it != end; ++it, ++i) { if (it->enhanced_sound_data.priority== SND_ENHANCED_PRIORITY_INVALID) { if (i < NUM_RETAIL_GAMEPLAY_SOUNDS) { it->enhanced_sound_data.priority= Default_sound_priorities[i].priority; } else { it->enhanced_sound_data.priority= default_enhanced_sound_data.priority; } } if (it->enhanced_sound_data.limit < 1) { if (i < NUM_RETAIL_GAMEPLAY_SOUNDS) { it->enhanced_sound_data.limit = Default_sound_priorities[i].limit; } else { it->enhanced_sound_data.limit= default_enhanced_sound_data.limit; } } } }
/** * Call at the close of each level (mission) */ void shockwave_level_close() { if ( !Shockwave_inited ) return; shockwave_delete_all(); size_t i; // unload default shockwave, and erase all others for (i = 0; i < Shockwave_info.size(); i++) { if ( !i ) { if (Shockwave_info[i].bitmap_id >= 0) bm_unload( Shockwave_info[i].bitmap_id ); else if (Shockwave_info[i].model_id >= 0) model_page_out_textures( Shockwave_info[i].model_id ); continue; } if (Shockwave_info[i].bitmap_id >= 0) bm_release( Shockwave_info[i].bitmap_id ); if (Shockwave_info[i].model_id >= 0) model_unload( Shockwave_info[i].model_id ); Shockwave_info.erase( Shockwave_info.begin() + i ); } Shockwave_inited = 0; }
void cutscene_close() { for(SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) if(cut->description != NULL) { vm_free(cut->description); cut->description = NULL; } }
int batch_get_size() { int n_to_render = 0; SCP_vector<batch_item>::iterator bi; for (bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) { n_to_render += bi->batch.need_to_render(); } for (bi = distortion_map.begin(); bi != distortion_map.end(); ++bi) { if ( bi->laser ) continue; n_to_render += bi->batch.need_to_render(); } return n_to_render * 3; }
void cam_close() { //Set Current_camera to nothing Current_camera = camid(); for (auto ii = Cameras.begin(); ii != Cameras.end(); ++ii) { delete * ii; } Cameras.clear(); }
void subtitles_do_frame_post_shaded(float frametime) { SCP_vector<subtitle>::iterator sub; for(sub = Subtitles.begin(); sub != Subtitles.end(); ++sub) { if ( sub->is_post_shaded( ) ) sub->do_frame(frametime); } }
// only call from game_shutdown()!!! void particle_close() { for (SCP_vector<particle*>::iterator p = Particles.begin(); p != Particles.end(); ++p) { (*p)->signature = 0; delete *p; } Particles.clear(); }
/** * Unload the ingame sounds from memory */ void gamesnd_unload_gameplay_sounds() { Assert( Snds.size() <= INT_MAX ); for (SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs) { if ( gs->id != -1 ) { snd_unload( gs->id ); gs->id = -1; } } }
// function to return 0 based index of which CD a particular movie is on // returns -1 on failure. int cutscenes_get_cd_num( char *filename ) { for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut) { if ( !stricmp(cut->filename, filename) ) { return (cut->cd - 1); } } return -1; }
/** * Unload the interface sounds from memory */ void gamesnd_unload_interface_sounds() { Assert( Snds_iface.size() < INT_MAX ); for (SCP_vector<game_snd>::iterator si = Snds_iface.begin(); si != Snds_iface.end(); ++si) { if ( si->id != -1 ) { snd_unload( si->id ); si->id = -1; si->id_sig = -1; } } }
/** * Load the interface sounds into memory */ void gamesnd_load_interface_sounds() { if ( !Sound_enabled ) return; Assert( Snds_iface.size() < INT_MAX ); for (SCP_vector<game_snd>::iterator si = Snds_iface.begin(); si != Snds_iface.end(); ++si) { if ( si->filename[0] != 0 && strnicmp(si->filename, NOX("none.wav"), 4) ) { si->id = snd_load(&(*si)); } } }
static void find_capture_device(OpenALInformation* info) { const char *user_device = os_config_read_string( "Sound", "CaptureDevice", NULL ); const char *default_device = info->default_capture_device.c_str(); // in case they are the same, we only want to test it once if ( (user_device && default_device) && !strcmp(user_device, default_device) ) { user_device = NULL; } for (auto& device : info->capture_devices) { OALdevice new_device(device.c_str()); if (user_device && !strcmp(device.c_str(), user_device)) { new_device.type = OAL_DEVICE_USER; } else if (default_device && !strcmp(device.c_str(), default_device)) { new_device.type = OAL_DEVICE_DEFAULT; } CaptureDevices.push_back( new_device ); } if ( CaptureDevices.empty() ) { return; } std::sort( CaptureDevices.begin(), CaptureDevices.end(), openal_device_sort_func ); // for each device that we have available, try and figure out which to use for (size_t idx = 0; idx < CaptureDevices.size(); idx++) { const ALCchar *device_name = CaptureDevices[idx].device_name.c_str(); ALCdevice *device = alcCaptureOpenDevice(device_name, 22050, AL_FORMAT_MONO8, 22050 * 2); if (device == NULL) { continue; } if (alcGetError(device) != ALC_NO_ERROR) { alcCaptureCloseDevice(device); continue; } // ok, we should be good with this one Capture_device = CaptureDevices[idx].device_name; alcCaptureCloseDevice(device); break; } }
// ============================== IMPLEMENTATIONS ============================= void dc_do_command(SCP_string *cmd_str) { /** * Grab the first word from the cmd_str * If it is not a literal, ignore it "Invalid keyword: %s" * Search for the command... * Compare the word against valid commands * If command not found, ignore it "Invalid or unknown command: %s"\ * Process the command... * Call the function to process the command (the rest of the command line is in the parser) * Function takes care of long_help and status depending on the mode. */ SCP_string command; extern SCP_vector<debug_command*> dc_commands; // z64: I don't like this extern here, at all. Nope nope nope. if (cmd_str->empty()) { return; } dc_parse_init(*cmd_str); dc_stuff_string_white(command); // Grab the first token, presumably this is a command SCP_vector<debug_command*>::iterator it = find_if(dc_commands.begin(), dc_commands.end(), is_dcmd(command.c_str())); if (it == dc_commands.end()) { dc_printf("Command not found: '%s'\n", command.c_str()); return; } // Else, we found our command try { (*it)->func(); // Run the command! } catch (errParseString err) { dc_printf("Require string(s) not found: \n"); for (int i = 0; i < err.expected_tokens.size(); ++i) { dc_printf("%i: %s\n", err.expected_tokens[i].c_str()); } dc_printf("Found '%s' instead\n", err.found_token.c_str()); } catch (errParse err) { dc_printf("Invalid argument. Expected %s, found '%s'\n", token_str[err.expected_type], err.found_token.c_str()); } // dc_maybe_stuff_string is vulnerable to overflow. Once the errParseOverflow throw class (or w/e) gets // implemented, this last command should be put into its own try{} catch{} block. if (dc_maybe_stuff_string(command)) { dc_printf( "Ignoring the unused command line tail '%s'\n", command.c_str() ); } }
// kill all active particles void particle_kill_all() { // kill all active particles Num_particles = 0; Num_particles_hwm = 0; for (SCP_vector<particle*>::iterator p = Particles.begin(); p != Particles.end(); ++p) { (*p)->signature = 0; delete *p; } Particles.clear(); }
void batch_load_buffer_distortion_map_bitmaps(effect_vertex* buffer, int *n_verts) { for (SCP_vector<batch_item>::iterator bi = distortion_map.begin(); bi != distortion_map.end(); ++bi) { if ( bi->laser ) continue; if ( !bi->batch.need_to_render() ) continue; Assert( bi->texture >= 0 ); bi->batch.load_buffer(buffer, n_verts); } }
void os_poll() { // Replay the buffered events auto end = buffered_events.end(); for (auto it = buffered_events.begin(); it != end; ++it) { handle_sdl_event(*it); } buffered_events.clear(); SDL_Event event; while (SDL_PollEvent(&event)) { handle_sdl_event(event); } }
/** * Load the ingame sounds into memory */ void gamesnd_load_gameplay_sounds() { if ( !Sound_enabled ) return; Assert( Snds.size() <= INT_MAX ); for (SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs) { if ( gs->filename[0] != 0 && strnicmp(gs->filename, NOX("none.wav"), 4) ) { if ( !gs->preload ) { // don't try to load anything that's already preloaded game_busy( NOX("** preloading gameplay sounds **") ); // Animate loading cursor... does nothing if loading screen not active. gs->id = snd_load(&(*gs)); } } } }
void cutscenes_screen_init() { int i; ui_button_info *b; Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0); Ui_window.set_mask_bmap(Cutscene_mask_name[gr_screen.res]); for (i=0; i<NUM_BUTTONS; i++) { b = &Buttons[gr_screen.res][i]; b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1); // set up callback for when a mouse first goes over a button b->button.set_highlight_action(common_play_highlight_sound); b->button.set_bmaps(b->filename); b->button.link_hotspot(b->hotspot); } // add xstrs for(i=0; i<NUM_CUTSCENE_TEXT; i++){ Ui_window.add_XSTR(&Cutscene_text[gr_screen.res][i]); } Buttons[gr_screen.res][EXIT_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER); Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(KEY_PAGEUP); Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN); List_region.create(&Ui_window, "", Cutscene_list_coords[gr_screen.res][0], Cutscene_list_coords[gr_screen.res][1], Cutscene_list_coords[gr_screen.res][2], Cutscene_list_coords[gr_screen.res][3], 0, 1); List_region.hide(); // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed Buttons[gr_screen.res][SCROLL_UP_BUTTON].button.set_hotkey(KEY_PAGEUP); Buttons[gr_screen.res][SCROLL_DOWN_BUTTON].button.set_hotkey(KEY_PAGEDOWN); Background_bitmap = bm_load(Cutscene_bitmap_name[gr_screen.res]); Scroll_offset = Selected_line = 0; Description_index = -1; Cutscene_list.clear(); int u = 0; for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut, u++) { if ( (*cut).viewable ) { Cutscene_list.push_back(u); } } }
void batch_render_lasers(bool stream_buffer) { for (SCP_vector<batch_item>::iterator bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) { if ( !bi->laser ) continue; if ( !bi->batch.need_to_render() ) continue; Assert( bi->texture >= 0 ); gr_set_bitmap(bi->texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 0.99999f); if ( stream_buffer ) { bi->batch.render_buffer(TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT); } else { bi->batch.render(TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT | TMAP_HTL_3D_UNLIT | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT); } } }
void batch_render_geometry_map_bitmaps(bool stream_buffer) { for (SCP_vector<batch_item>::iterator bi = geometry_map.begin(); bi != geometry_map.end(); ++bi) { if ( bi->laser ) continue; if ( !bi->batch.need_to_render() ) continue; Assert( bi->texture >= 0 ); gr_set_bitmap(bi->texture, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, bi->alpha); if ( stream_buffer ) { bi->batch.render_buffer(bi->tmap_flags); } else { bi->batch.render( bi->tmap_flags); } } }
/** * Pass a GLSL shader source to OpenGL and compile it into a usable shader object. * Prints compilation errors (if any) to the log. * Note that this will only compile shaders into objects, linking them into executables happens later * * @param shader_source GLSL sourcecode for the shader * @param shader_type OpenGL ID for the type of shader being used, like GL_FRAGMENT_SHADER_ARB, GL_VERTEX_SHADER_ARB * @return OpenGL handle for the compiled shader object */ GLhandleARB opengl_shader_compile_object(const SCP_vector<SCP_string>& shader_source, GLenum shader_type) { GLhandleARB shader_object = 0; GLint status = 0; SCP_vector<const GLcharARB*> sources; sources.reserve(shader_source.size()); for (auto it = shader_source.begin(); it != shader_source.end(); ++it) { sources.push_back(it->c_str()); } shader_object = vglCreateShaderObjectARB(shader_type); vglShaderSourceARB(shader_object, sources.size(), &sources[0], NULL); vglCompileShaderARB(shader_object); // check if the compile was successful vglGetObjectParameterivARB(shader_object, GL_OBJECT_COMPILE_STATUS_ARB, &status); opengl_shader_check_info_log(shader_object); // we failed, bail out now... if (status == 0) { // basic error check mprintf(("%s shader failed to compile:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : ((shader_type == GL_GEOMETRY_SHADER_EXT) ? "Geometry" : "Fragment"), GLshader_info_log)); // this really shouldn't exist, but just in case if (shader_object) { vglDeleteObjectARB(shader_object); } return 0; } // we succeeded, maybe output warnings too if (strlen(GLshader_info_log) > 5) { nprintf(("SHADER-DEBUG", "%s shader compiled with warnings:\n%s\n", (shader_type == GL_VERTEX_SHADER_ARB) ? "Vertex" : ((shader_type == GL_GEOMETRY_SHADER_EXT) ? "Geometry" : "Fragment"), GLshader_info_log)); } return shader_object; }
void dc_init(void) { extern SCP_vector<debug_command*> dc_commands; if (debug_inited) { return; } debug_inited = TRUE; // Sort debug_commands std::sort(dc_commands.begin(), dc_commands.end(), dcmd_less); // Init window settings dc_font = FONT1; row_height = (Current_font->h) * 1.5; // Row/Line height, in pixels col_width = Current_font->w; // Col/Character width, in pixels dc_scroll_x = 0; dc_scroll_y = 0; DCOLS = (gr_screen.max_w / col_width) - 1; // Subtract as needed. Windowed mode has some quirks with the resolution DROWS = (gr_screen.max_h / row_height) - 2; DBCOLS = DCOLS; DBROWS = 2 * DROWS; // Init History dc_history.clear(); dc_history.push_back(""); last_oldcommand = dc_history.begin(); // Init buffers dc_buffer.clear(); dc_buffer.push_back(""); dc_command_buf.reserve(MAX_CLI_LEN); dc_command_buf.clear(); sprintf(dc_title, "FreeSpace Open v%i.%i.%i", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD); dc_printf("Debug console started.\n" ); }
static void process_pending_data() { while (!pending_frame_data.empty()) { auto& frame_data = pending_frame_data.front(); bool finished; if (!do_gpu_queries) { finished = true; } else { // Determine if all queries have passed already finished = true; for (auto& trace_data : frame_data.data) { if (trace_data.gpu_query == -1) { // Event has been processed before continue; } if (gr_query_value_available(trace_data.gpu_query)) { trace_data.gpu_time = gr_get_query_value(trace_data.gpu_query); free_query_object(trace_data.gpu_query); trace_data.gpu_query = -1; } else { // If we are here then a query hasn't finished yet. Try again next time... finished = false; break; } } } if (finished) { std::thread writer_thread(std::bind(write_json_data, frame_data)); writer_thread.detach(); pending_frame_data.erase(pending_frame_data.begin()); } else { // GPU queries always finish in sequence so the later queries can't be finished yet break; } } }
void fs2netd_update_ban_list() { int rc = 0; if ( !Logged_in ) { return; } // destroy the file prior to updating cf_delete( "banlist.cfg", CF_TYPE_DATA ); do_full_packet = true; In_process = true; if (Is_standalone) { do { rc = fs2netd_update_ban_list_do(); } while (!rc); } else { rc = popup_till_condition(fs2netd_update_ban_list_do, XSTR("&Cancel", 779), XSTR("Requesting IP ban list", 1587)); } In_process = false; Local_timeout = -1; if ( !FS2NetD_ban_list.empty() ) { CFILE *banlist_cfg = cfopen("banlist.cfg", "wt", CFILE_NORMAL, CF_TYPE_DATA); if (banlist_cfg != NULL) { for (SCP_vector<SCP_string>::iterator bl = FS2NetD_ban_list.begin(); bl != FS2NetD_ban_list.end(); ++bl) { cfputs( const_cast<char*>(bl->c_str()), banlist_cfg ); } cfclose(banlist_cfg); } } FS2NetD_ban_list.clear(); }
/** * Function to search for a given game_snd with the specified name * in the passed vector * * @param name Name to search for * @param sounds Vector to seach in * */ int gamesnd_lookup_name(const char* name, const SCP_vector<game_snd>& sounds) { // if we get passed -1, don't bother trying to look it up. if (name == NULL || *name == 0 || !strcmp(name, "-1")) { return -1; } Assert( sounds.size() <= INT_MAX ); int i = 0; for(SCP_vector<game_snd>::const_iterator snd = sounds.begin(); snd != sounds.end(); ++snd) { if (!snd->name.compare(name)) { return i; } i++; } return -1; }
static void handle_includes_impl(SCP_vector<SCP_string>& include_stack, SCP_stringstream& output, int& include_counter, const SCP_string& filename, const SCP_string& original) { include_stack.emplace_back(filename); auto current_source_number = include_counter + 1; const char* INCLUDE_STRING = "#include"; SCP_stringstream input(original); int line_num = 1; for (SCP_string line; std::getline(input, line);) { auto include_start = line.find(INCLUDE_STRING); if (include_start != SCP_string::npos) { auto first_quote = line.find('"', include_start + strlen(INCLUDE_STRING)); auto second_quote = line.find('"', first_quote + 1); if (first_quote == SCP_string::npos || second_quote == SCP_string::npos) { Error(LOCATION, "Shader %s:%d: Malformed include line. Could not find both quote charaters.", filename.c_str(), line_num); } auto file_name = line.substr(first_quote + 1, second_quote - first_quote - 1); auto existing_name = std::find_if(include_stack.begin(), include_stack.end(), [&file_name](const SCP_string& str) { return str == file_name; }); if (existing_name != include_stack.end()) { SCP_stringstream stack_string; for (auto& name : include_stack) { stack_string << "\t" << name << "\n"; } Error(LOCATION, "Shader %s:%d: Detected cyclic include! Previous includes (top level file first):\n%s", filename.c_str(), line_num, stack_string.str().c_str()); } ++include_counter; // The second parameter defines which source string we are currently working with. We keep track of how many // excludes have been in the file so far to specify this output << "#line 1 " << include_counter + 1 << "\n"; handle_includes_impl(include_stack, output, include_counter, file_name, opengl_load_shader(file_name.c_str())); // We are done with the include file so now we can return to the original file output << "#line " << line_num + 1 << " " << current_source_number << "\n"; } else { output << line << "\n"; } ++line_num; } include_stack.pop_back(); }