diff --git a/code/missionui/missionscreencommon.cpp b/code/missionui/missionscreencommon.cpp index 07766876504..a9a9923293c 100644 --- a/code/missionui/missionscreencommon.cpp +++ b/code/missionui/missionscreencommon.cpp @@ -1552,15 +1552,14 @@ int restore_wss_data(ubyte *data) return offset; } -void draw_model_icon(int model_id, uint64_t flags, float closeup_zoom, int x, int y, int w, int h, ship_info *sip, int resize_mode, const vec3d *closeup_pos) +void draw_model_icon(int model_id, uint64_t flags, int x, int y, int w, int h, ship_info* sip, weapon_info* wip, float zoom_multiplier, int resize_mode) { lighting_profiles::set_non_mission_profile non_mission_lighting_profile; matrix object_orient = IDENTITY_MATRIX; angles rot_angles = vmd_zero_angles; - float zoom = closeup_zoom * 2.5f; - if(sip == NULL) + if (sip == nullptr) { //Assume it's a weapon rot_angles.h = -(PI_2); @@ -1588,14 +1587,20 @@ void draw_model_icon(int model_id, uint64_t flags, float closeup_zoom, int x, in gr_set_clip(x, y, w, h, resize_mode); g3_start_frame(1); - if(sip != NULL) + if (sip != nullptr) { - g3_set_view_matrix( &sip->closeup_pos, &vmd_identity_matrix, zoom); + const auto& closeup_pos = sip->icon_closeup_pos.value_or(sip->closeup_pos); + const auto closeup_zoom = sip->icon_closeup_zoom.value_or(sip->closeup_zoom); + const auto zoom = closeup_zoom * zoom_multiplier * 2.5f; + + g3_set_view_matrix(&closeup_pos, &vmd_identity_matrix, zoom); gr_set_proj_matrix(Proj_fov * 0.5f, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance); } else { + Assertion(wip != nullptr, "Weapon is null, get a coder!"); + polymodel *pm = model_get(model_id); bsp_info *bs = NULL; //tehe for(int i = 0; i < pm->n_models; i++) @@ -1612,24 +1617,23 @@ void draw_model_icon(int model_id, uint64_t flags, float closeup_zoom, int x, in bs = &pm->submodel[0]; } - vec3d weap_closeup = *closeup_pos; + vec3d weap_closeup = wip->icon_closeup_pos.value_or(wip->closeup_pos); float y_closeup; - float tm_zoom = closeup_zoom; + float tm_zoom = wip->icon_closeup_zoom.value_or(wip->closeup_zoom) * zoom_multiplier; - //Find the center of teh submodel - weap_closeup.xyz.x = -(bs->min.xyz.z + (bs->max.xyz.z - bs->min.xyz.z)/2.0f); - weap_closeup.xyz.y = -(bs->min.xyz.y + (bs->max.xyz.y - bs->min.xyz.y)/2.0f); - //weap_closeup.xyz.z = (weap_closeup.xyz.x/tanf(zoom / 2.0f)); - weap_closeup.xyz.z = -(bs->rad/tanf(tm_zoom/2.0f)); + if (!wip->icon_closeup_pos.has_value()) { + // Find the center of the submodel when no icon-specific position override is defined + weap_closeup.xyz.x = -(bs->min.xyz.z + (bs->max.xyz.z - bs->min.xyz.z) / 2.0f); + weap_closeup.xyz.y = -(bs->min.xyz.y + (bs->max.xyz.y - bs->min.xyz.y) / 2.0f); + weap_closeup.xyz.z = -(bs->rad / tanf(tm_zoom / 2.0f)); - y_closeup = -(weap_closeup.xyz.y/tanf(tm_zoom / 2.0f)); - if(y_closeup < weap_closeup.xyz.z) - { - weap_closeup.xyz.z = y_closeup; - } - if(bs->min.xyz.x < weap_closeup.xyz.z) - { - weap_closeup.xyz.z = bs->min.xyz.x; + y_closeup = -(weap_closeup.xyz.y / tanf(tm_zoom / 2.0f)); + if (y_closeup < weap_closeup.xyz.z) { + weap_closeup.xyz.z = y_closeup; + } + if (bs->min.xyz.x < weap_closeup.xyz.z) { + weap_closeup.xyz.z = bs->min.xyz.x; + } } g3_set_view_matrix( &weap_closeup, &vmd_identity_matrix, tm_zoom); diff --git a/code/missionui/missionscreencommon.h b/code/missionui/missionscreencommon.h index 40029d28d20..cbc5312b790 100644 --- a/code/missionui/missionscreencommon.h +++ b/code/missionui/missionscreencommon.h @@ -234,7 +234,8 @@ int store_wss_data(ubyte *data, const unsigned int max_size, interface_snd_id so int restore_wss_data(ubyte *data); class ship_info; -void draw_model_icon(int model_id, uint64_t flags, float closeup_zoom, int x1, int x2, int y1, int y2, ship_info* sip = NULL, int resize_mode = GR_RESIZE_FULL, const vec3d *closeup_pos = &vmd_zero_vector); +struct weapon_info; +void draw_model_icon(int model_id, uint64_t flags, int x1, int x2, int y1, int y2, ship_info* sip = nullptr, weapon_info* wip = nullptr, float zoom_multiplier = 1.0f, int resize_mode = GR_RESIZE_FULL); void draw_model_rotating(model_render_params *render_info, int ship_class, int model_id, int x1, int y1, int x2, int y2, float *rotation_buffer, const vec3d *closeup_pos=nullptr, float closeup_zoom = .65f, float rev_rate = REVOLUTION_RATE, uint64_t flags = MR_AUTOCENTER | MR_NO_FOGGING, int resize_mode=GR_RESIZE_FULL, select_effect_params effect_params = select_effect_params{}); void common_set_team_pointers(int team); diff --git a/code/missionui/missionshipchoice.cpp b/code/missionui/missionshipchoice.cpp index 48b0b3ea9ea..b7051b043a7 100644 --- a/code/missionui/missionshipchoice.cpp +++ b/code/missionui/missionshipchoice.cpp @@ -1515,7 +1515,7 @@ void ship_select_do(float frametime) if(Ss_icons[Carried_ss_icon.ship_class].model_index != -1) { - draw_model_icon(Ss_icons[Carried_ss_icon.ship_class].model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, sip->closeup_zoom / 1.25f, sx, sy, w, h, sip, GR_RESIZE_MENU); + draw_model_icon(Ss_icons[Carried_ss_icon.ship_class].model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, sx, sy, w, h, sip, nullptr, 0.8f, GR_RESIZE_MENU); } } } @@ -1705,7 +1705,7 @@ void draw_ship_icon_with_number(int screen_offset, int ship_class) if(ss_icon->model_index != -1) { - draw_model_icon(ss_icon->model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, sip->closeup_zoom / 1.25f, Ship_list_coords[gr_screen.res][screen_offset][0],Ship_list_coords[gr_screen.res][screen_offset][1], 32, 28, sip, GR_RESIZE_MENU); + draw_model_icon(ss_icon->model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, Ship_list_coords[gr_screen.res][screen_offset][0],Ship_list_coords[gr_screen.res][screen_offset][1], 32, 28, sip, nullptr, 0.8f, GR_RESIZE_MENU); } } @@ -2307,7 +2307,7 @@ void draw_wing_block(int wb_num, int hot_slot, int selected_slot, int class_sele draw_brackets_square(&line_draw_list, Wing_icon_coords[gr_screen.res][slot_index][0], Wing_icon_coords[gr_screen.res][slot_index][1], Wing_icon_coords[gr_screen.res][slot_index][0] + 32, Wing_icon_coords[gr_screen.res][slot_index][1] + 28, GR_RESIZE_MENU); line_draw_list.flush(); - draw_model_icon(icon->model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, sip->closeup_zoom / 1.25f, Wing_icon_coords[gr_screen.res][slot_index][0], Wing_icon_coords[gr_screen.res][slot_index][1], 32, 28, sip, GR_RESIZE_MENU); + draw_model_icon(icon->model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, Wing_icon_coords[gr_screen.res][slot_index][0], Wing_icon_coords[gr_screen.res][slot_index][1], 32, 28, sip, nullptr, 0.8f, GR_RESIZE_MENU); } } } @@ -2390,7 +2390,7 @@ void ss_blit_ship_icon(int x,int y,int ship_class,int bmap_num) draw_brackets_square(&line_draw_list, x, y, x + 32, y + 28, GR_RESIZE_MENU); line_draw_list.flush(); - draw_model_icon(icon->model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, sip->closeup_zoom / 1.25f, x, y, 32, 28, sip, GR_RESIZE_MENU); + draw_model_icon(icon->model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, x, y, 32, 28, sip, nullptr, 0.8f, GR_RESIZE_MENU); } } } diff --git a/code/missionui/missionweaponchoice.cpp b/code/missionui/missionweaponchoice.cpp index 151222c9306..49d762e935a 100644 --- a/code/missionui/missionweaponchoice.cpp +++ b/code/missionui/missionweaponchoice.cpp @@ -2909,7 +2909,7 @@ void weapon_select_do(float frametime) if(icon->model_index != -1) { //Draw the model - draw_model_icon(icon->model_index, MR_NO_FOGGING | MR_NO_LIGHTING, wip->closeup_zoom / 2.5f, sx, sy, w, h, NULL, GR_RESIZE_MENU, &wip->closeup_pos); + draw_model_icon(icon->model_index, MR_NO_FOGGING | MR_NO_LIGHTING, sx, sy, w, h, nullptr, wip, 0.4f, GR_RESIZE_MENU); } else if(icon->laser_bmap != -1) { @@ -3141,7 +3141,7 @@ void wl_render_icon(int index, int x, int y, int num, int draw_num_flag, int hot if(icon->model_index != -1) { //Draw the model - draw_model_icon(icon->model_index, MR_NO_FOGGING | MR_NO_LIGHTING, Weapon_info[index].closeup_zoom * 0.4f, x, y, 56, 24, NULL, GR_RESIZE_MENU); + draw_model_icon(icon->model_index, MR_NO_FOGGING | MR_NO_LIGHTING, x, y, 56, 24, nullptr, &Weapon_info[index], 0.4f, GR_RESIZE_MENU); } else if(icon->laser_bmap != -1) { diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index a5eb8acb665..92061c3fb62 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -1243,6 +1243,8 @@ void ship_info::clone(const ship_info& other) closeup_pos = other.closeup_pos; closeup_zoom = other.closeup_zoom; + icon_closeup_pos = other.icon_closeup_pos; + icon_closeup_zoom = other.icon_closeup_zoom; closeup_pos_targetbox = other.closeup_pos_targetbox; closeup_zoom_targetbox = other.closeup_zoom_targetbox; @@ -1595,6 +1597,8 @@ void ship_info::move(ship_info&& other) std::swap(closeup_pos, other.closeup_pos); closeup_zoom = other.closeup_zoom; + std::swap(icon_closeup_pos, other.icon_closeup_pos); + icon_closeup_zoom = other.icon_closeup_zoom; std::swap(closeup_pos_targetbox, other.closeup_pos_targetbox); closeup_zoom_targetbox = other.closeup_zoom_targetbox; @@ -1984,6 +1988,8 @@ ship_info::ship_info() vm_vec_zero(&closeup_pos); closeup_zoom = 0.5f; + icon_closeup_pos = std::nullopt; + icon_closeup_zoom = std::nullopt; vm_vec_zero(&closeup_pos_targetbox); closeup_zoom_targetbox = 0.5f; @@ -4773,6 +4779,24 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool } } + if (optional_string("$Icon_closeup_pos:")) { + vec3d icon_pos; + stuff_vec3d(&icon_pos); + sip->icon_closeup_pos = icon_pos; + } + + if (optional_string("$Icon_closeup_zoom:")) { + float icon_zoom; + stuff_float(&icon_zoom); + + if (icon_zoom <= 0.0f) { + mprintf(("Warning! Ship '%s' has a $Icon_closeup_zoom value that is less than or equal to 0 (%f). Ignoring value.\n", sip->name, icon_zoom)); + sip->icon_closeup_zoom = std::nullopt; + } else { + sip->icon_closeup_zoom = icon_zoom; + } + } + if(optional_string("$Closeup_pos_targetbox:")) { stuff_vec3d(&sip->closeup_pos_targetbox); diff --git a/code/ship/ship.h b/code/ship/ship.h index fc25427a6bc..d656d936084 100644 --- a/code/ship/ship.h +++ b/code/ship/ship.h @@ -33,6 +33,7 @@ #include #include +#include #include class object; @@ -1346,6 +1347,8 @@ class ship_info vec3d closeup_pos; // position for camera when using ship in closeup view (eg briefing and techroom) float closeup_zoom; // zoom when using ship in closeup view (eg briefing and techroom) + std::optional icon_closeup_pos; // icon-specific position for camera when using ship in closeup view + std::optional icon_closeup_zoom; // icon-specific zoom when using ship in closeup view vec3d closeup_pos_targetbox; // position for camera when using ship in closeup view for hud target monitor float closeup_zoom_targetbox; // zoom when using ship in closeup view for hud target monitor diff --git a/code/weapon/weapon.h b/code/weapon/weapon.h index 72a550cf3dd..c491d97f200 100644 --- a/code/weapon/weapon.h +++ b/code/weapon/weapon.h @@ -35,6 +35,8 @@ #include "utils/modular_curves.h" +#include + class object; class ship_subsys; @@ -386,6 +388,8 @@ struct weapon_info vec3d closeup_pos; // position for camera to set an offset for viewing the weapon model float closeup_zoom; // zoom when using weapon model in closeup view in loadout selection + std::optional icon_closeup_pos; // icon-specific position for camera for viewing the weapon model + std::optional icon_closeup_zoom; // icon-specific zoom for viewing the weapon model char hud_filename[MAX_FILENAME_LEN]; //Name of image to display on HUD in place of text int hud_image_index; //teh index of the image diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index 839bf7966d5..98040f7044d 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -985,6 +985,24 @@ int parse_weapon(int subtype, bool replace, const char *filename) } } + if (optional_string("+Icon_closeup_pos:")) { + vec3d icon_pos; + stuff_vec3d(&icon_pos); + wip->icon_closeup_pos = icon_pos; + } + + if (optional_string("+Icon_closeup_zoom:")) { + float icon_zoom; + stuff_float(&icon_zoom); + + if (icon_zoom <= 0.0f) { + mprintf(("Warning! Weapon '%s' has a +Icon_closeup_zoom value that is less than or equal to 0 (%f). Ignoring value.\n", wip->name, icon_zoom)); + wip->icon_closeup_zoom = std::nullopt; + } else { + wip->icon_closeup_zoom = icon_zoom; + } + } + // Weapon fadein effect, used when no ani is specified or weapon_select_3d is active if (first_time) { wip->selection_effect = Default_weapon_select_effect; // By default, use the FS2 effect @@ -9396,6 +9414,8 @@ void weapon_info::reset() vm_vec_zero(&this->closeup_pos); this->closeup_zoom = 1.0f; + this->icon_closeup_pos = std::nullopt; + this->icon_closeup_zoom = std::nullopt; memset(this->hud_filename, 0, sizeof(this->hud_filename)); this->hud_image_index = -1;