Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c133c0b
First draft of prop object type
MjnMixael Jun 2, 2025
af73ad5
Add prop editor dialog in FRED
MjnMixael Jun 11, 2025
90f449a
prop sexps
MjnMixael Jun 12, 2025
8026eaa
lua table prop support
MjnMixael Jun 12, 2025
21685f3
lab support
MjnMixael Jun 12, 2025
b7e182a
lua mission access to props
MjnMixael Jun 13, 2025
8c5a23f
prop collision support
Baezon Jun 14, 2025
2debeae
use std::optional so the object->instance id is always valid
MjnMixael Jun 14, 2025
a0908dd
allow props to block suns
MjnMixael Jun 15, 2025
faa0beb
minor cleanup and remove arbitrary limit. Still limited to 500 objects.
MjnMixael Jun 15, 2025
f7fb8c8
Sort props by category
MjnMixael Jun 16, 2025
282bf55
cleanup
MjnMixael Jun 16, 2025
ca56b86
implement collision hooks
MjnMixael Jun 16, 2025
78c607c
parse prop flags and further ensure props are inited and closed corre…
MjnMixael Jun 17, 2025
1f7d2ad
Add Cyborg's multi suggestions
MjnMixael Jun 17, 2025
9a024fa
fix missing header
MjnMixael Jun 17, 2025
bfb8dba
add props to empty slots if available
MjnMixael Jun 17, 2025
4aa9ed3
add multi signature
MjnMixael Jun 18, 2025
3053e66
fix rebase issues and match collisions to the new multithread style
MjnMixael Jul 14, 2025
2d0b820
appease Clang the Conquerer
MjnMixael Jul 14, 2025
6b0a1bc
save/parse mission prop classes by name
MjnMixael Jul 30, 2025
718152d
Clean up comments and finish TODOs
MjnMixael Jul 30, 2025
07b9c21
fix string errors
MjnMixael Jul 30, 2025
6223688
clang wants this to be static now
MjnMixael Jul 30, 2025
2a0a78a
address feedback
MjnMixael Oct 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/graphics/shadows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ void shadows_render_all(fov_t fov, matrix *eye_orient, vec3d *eye_pos)
switch(objp->type)
{
case OBJ_RAW_POF:
case OBJ_PROP:
case OBJ_SHIP:
{
obj_queue_render(objp, &scene);
Expand Down
68 changes: 66 additions & 2 deletions code/lab/dialogs/lab_ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "ship/shiphit.h"
#include "weapon/weapon.h"
#include "mission/missionload.h"
#include "prop/prop.h"

using namespace ImGui;

Expand Down Expand Up @@ -92,6 +93,32 @@ void LabUi::build_weapon_subtype_list() const
}
}

void LabUi::build_prop_subtype_list()
{
for (auto& propc : Prop_categories) {
with_TreeNode(propc.name.c_str())
{
int prop_idx = 0;

for (auto const& class_def : Prop_info) {
if (lcase_equal(class_def.category, propc.name)) {
SCP_string node_label;
sprintf(node_label, "##PropClassIndex%i", prop_idx);
TreeNodeEx(node_label.c_str(),
ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen,
"%s",
class_def.name.c_str());

if (IsItemClicked() && !IsItemToggledOpen()) {
getLabManager()->changeDisplayedObject(LabMode::Prop, prop_idx);
}
}
prop_idx++;
}
}
}
}

void LabUi::build_asteroid_list()
{
with_TreeNode("Asteroids")
Expand Down Expand Up @@ -171,7 +198,15 @@ void LabUi::build_object_list()
}
}

void LabUi::build_background_list() const
void LabUi::build_prop_list()
{
with_TreeNode("Prop Classes")
{
build_prop_subtype_list();
}
}

void LabUi::build_background_list()
{
SCP_vector<SCP_string> t_missions;

Expand Down Expand Up @@ -272,6 +307,8 @@ void LabUi::show_object_selector() const

build_weapon_list();

build_prop_list();

build_object_list();
}
}
Expand Down Expand Up @@ -418,7 +455,8 @@ void LabUi::show_render_options()
Checkbox("Rotate/Translate Subsystems", &animate_subsystems);
}
Checkbox("Show full detail", &show_full_detail);
if (getLabManager()->CurrentMode != LabMode::Asteroid) {
if (getLabManager()->CurrentMode == LabMode::Ship ||
getLabManager()->CurrentMode == LabMode::Weapon) {
Checkbox("Show thrusters", &show_thrusters);
if (getLabManager()->CurrentMode == LabMode::Ship) {
Checkbox("Show afterburners", &show_afterburners);
Expand Down Expand Up @@ -1482,6 +1520,32 @@ void LabUi::show_object_options() const
}
}
}
} else if (getLabManager()->CurrentMode == LabMode::Prop && getLabManager()->CurrentClass >= 0) {
const auto& info = Prop_info[getLabManager()->CurrentClass];

with_CollapsingHeader("Object Info")
{
static SCP_string table_text;
static int old_class = -1;

if (table_text.empty() || old_class != getLabManager()->CurrentClass) {
table_text = get_prop_table_text(&info);
old_class = getLabManager()->CurrentClass;
}

InputTextMultiline("##prop_table_text",
const_cast<char*>(table_text.c_str()),
table_text.length(),
ImVec2(-FLT_MIN, GetTextLineHeight() * 16),
ImGuiInputTextFlags_ReadOnly);
}

with_CollapsingHeader("Object actions")
{
if (getLabManager()->isSafeForProps()) {
// No actions yet
}
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion code/lab/dialogs/lab_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ class LabUi {
static void build_object_list();
static void build_asteroid_list();
static void build_debris_list();
void build_background_list() const;
static void build_prop_list();
static void build_prop_subtype_list();
static void build_background_list();
void show_render_options();
void show_object_options() const;
void show_object_selector() const;
Expand Down
122 changes: 122 additions & 0 deletions code/lab/dialogs/lab_ui_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,128 @@ SCP_string get_asteroid_table_text(const asteroid_info* aip)
return result;
}

SCP_string get_prop_table_text(const prop_info* pip)
{
char line[256], line2[256], file_text[82];
int i, j, n, found = 0, comment = 0, num_files = 0;
SCP_vector<SCP_string> tbl_file_names;
SCP_string result;

auto fp = cfopen("props.tbl", "r");
if (!fp)
return "No props.tbl found.\r\n";

while (cfgets(line, 255, fp)) {
while (line[strlen(line) - 1] == '\n')
line[strlen(line) - 1] = 0;

for (i = j = 0; line[i]; i++) {
if (line[i] == '/' && line[i + 1] == '/')
break;
if (line[i] == '/' && line[i + 1] == '*') {
comment = 1;
i++;
continue;
}
if (line[i] == '*' && line[i + 1] == '/') {
comment = 0;
i++;
continue;
}
if (!comment)
line2[j++] = line[i];
}

line2[j] = 0;
if (!strnicmp(line2, "$Name:", 6)) {
drop_trailing_white_space(line2);
found = 0;
i = 6;

while (line2[i] == ' ' || line2[i] == '\t' || line2[i] == '@')
i++;

if (!stricmp(line2 + i, pip->name.c_str())) {
result += "-- props.tbl -------------------------------\r\n";
found = 1;
}
}

if (found) {
result += line;
result += "\r\n";
}
}

cfclose(fp);

num_files = cf_get_file_list(tbl_file_names, CF_TYPE_TABLES, NOX("*-prp.tbm"), CF_SORT_REVERSE);

for (n = 0; n < num_files; n++) {
tbl_file_names[n] += ".tbm";

fp = cfopen(tbl_file_names[n].c_str(), "r");
if (!fp)
continue;

memset(line, 0, sizeof(line));
memset(line2, 0, sizeof(line2));
found = 0;
comment = 0;

while (cfgets(line, 255, fp)) {
while (line[strlen(line) - 1] == '\n')
line[strlen(line) - 1] = 0;

for (i = j = 0; line[i]; i++) {
if (line[i] == '/' && line[i + 1] == '/')
break;
if (line[i] == '/' && line[i + 1] == '*') {
comment = 1;
i++;
continue;
}
if (line[i] == '*' && line[i + 1] == '/') {
comment = 0;
i++;
continue;
}
if (!comment)
line2[j++] = line[i];
}

line2[j] = 0;
if (!strnicmp(line2, "$Name:", 6)) {
drop_trailing_white_space(line2);
found = 0;
i = 6;

while (line2[i] == ' ' || line2[i] == '\t' || line2[i] == '@')
i++;

if (!stricmp(line2 + i, pip->name.c_str())) {
memset(file_text, 0, sizeof(file_text));
snprintf(file_text,
sizeof(file_text) - 1,
"-- %s -------------------------------\r\n",
tbl_file_names[n].c_str());
result += file_text;
found = 1;
}
}

if (found) {
result += line;
result += "\r\n";
}
}

cfclose(fp);
}

return result;
}

SCP_string get_directory_or_vp(const char* path)
{
SCP_string result(path);
Expand Down
3 changes: 3 additions & 0 deletions code/lab/dialogs/lab_ui_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "asteroid/asteroid.h"
#include "ship/ship.h"
#include "prop/prop.h"

SCP_map<int, SCP_string> get_docking_point_map(int model_index);

Expand All @@ -13,6 +14,8 @@ SCP_string get_weapon_table_text(weapon_info* wip);

SCP_string get_asteroid_table_text(const asteroid_info* aip);

SCP_string get_prop_table_text(const prop_info* pip);

SCP_string get_directory_or_vp(const char* path);

bool graphics_options_changed();
1 change: 1 addition & 0 deletions code/lab/labv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ enum class LabMode {
Asteroid,
Ship,
Weapon,
Prop,
None
};

Expand Down
8 changes: 8 additions & 0 deletions code/lab/manager/lab_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "ship/ship.h"
#include "ship/shipfx.h"
#include "particle/particle.h"
#include "prop/prop.h"
#include "weapon/muzzleflash.h"
#include "weapon/beam.h"
#include "ai/aigoals.h"
Expand Down Expand Up @@ -45,6 +46,7 @@ LabManager::LabManager() {
debris_init();
extern void debris_page_in();
debris_page_in();
props_level_init();
asteroid_level_init();
shockwave_level_init();
ship_level_init();
Expand Down Expand Up @@ -748,6 +750,12 @@ void LabManager::changeDisplayedObject(LabMode mode, int info_index, int subtype
ai_add_ship_goal_scripting(AI_GOAL_PLAY_DEAD_PERSISTENT, -1, 100, nullptr, &Ai_info[Player_ship->ai_index], 0, 0);
}
break;
case LabMode::Prop:
CurrentObject = prop_create(&CurrentOrientation, &CurrentPosition, CurrentClass);
if (isSafeForProps()) {
ModelFilename = Prop_info[CurrentClass].pof_file;
}
break;
case LabMode::Weapon:
if (ShowingTechModel && VALID_FNAME(Weapon_info[CurrentClass].tech_model)) {
ModelFilename = Weapon_info[CurrentClass].tech_model;
Expand Down
12 changes: 10 additions & 2 deletions code/lab/manager/lab_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "asteroid/asteroid.h"
#include "ship/ship.h"
#include "weapon/weapon.h"
#include "prop/prop.h"


enum class LabRotationMode { Both, Yaw, Pitch, Roll };
Expand Down Expand Up @@ -72,6 +73,9 @@ class LabManager {
// Unload any asteroids that were loaded
asteroid_level_close();

// Unload any props that were loaded
props_level_close();

// Lab can only be entered from the Mainhall so this should be safe
model_free_all();

Expand Down Expand Up @@ -103,11 +107,15 @@ class LabManager {

int Saved_cmdline_collisions_value;

bool isSafeForShips() {
bool isSafeForShips() const {
return CurrentMode == LabMode::Ship && CurrentObject != -1 && Objects[CurrentObject].type == OBJ_SHIP;
}

bool isSafeForWeapons() {
bool isSafeForProps() const {
return CurrentMode == LabMode::Prop && CurrentObject != -1 && Objects[CurrentObject].type == OBJ_PROP;
}

bool isSafeForWeapons() const {
bool valid = CurrentObject != -1 && (Objects[CurrentObject].type == OBJ_WEAPON || Objects[CurrentObject].type == OBJ_BEAM);
return CurrentMode == LabMode::Weapon && valid;
}
Expand Down
16 changes: 16 additions & 0 deletions code/lab/renderer/lab_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "particle/particle.h"
#include "starfield/starfield.h"
#include "starfield/nebula.h"
#include "prop/prop.h"

#include "missionui/missionscreencommon.h"
#include "tracing/tracing.h"
Expand Down Expand Up @@ -114,6 +115,21 @@ void LabRenderer::renderModel(float frametime) {
}
}

if (obj->type == OBJ_PROP) {
prop* propp = prop_id_lookup(obj->instance);
propp->flags.set(Prop::Prop_Flags::Draw_as_wireframe, renderFlags[LabRenderFlag::ShowWireframe]);
propp->flags.set(Prop::Prop_Flags::Render_full_detail, renderFlags[LabRenderFlag::ShowFullDetail]);
propp->flags.set(Prop::Prop_Flags::Render_without_light,
renderFlags[LabRenderFlag::NoLighting] || currentMissionBackground == LAB_MISSION_NONE_STRING);
propp->flags.set(Prop::Prop_Flags::Render_without_diffuse, renderFlags[LabRenderFlag::NoDiffuseMap]);
propp->flags.set(Prop::Prop_Flags::Render_without_glowmap, renderFlags[LabRenderFlag::NoGlowMap]);
propp->flags.set(Prop::Prop_Flags::Render_without_normalmap, renderFlags[LabRenderFlag::NoNormalMap]);
propp->flags.set(Prop::Prop_Flags::Render_without_specmap, renderFlags[LabRenderFlag::NoSpecularMap]);
propp->flags.set(Prop::Prop_Flags::Render_without_reflectmap, renderFlags[LabRenderFlag::NoReflectMap]);
propp->flags.set(Prop::Prop_Flags::Render_without_heightmap, renderFlags[LabRenderFlag::NoHeightMap]);
propp->flags.set(Prop::Prop_Flags::Render_without_ambientmap, renderFlags[LabRenderFlag::NoAOMap]);
}

if (obj->type == OBJ_WEAPON) {
Weapons[obj->instance].weapon_flags.set(Weapon::Weapon_Flags::Draw_as_wireframe, renderFlags[LabRenderFlag::ShowWireframe]);
Weapons[obj->instance].weapon_flags.set(Weapon::Weapon_Flags::Render_full_detail, renderFlags[LabRenderFlag::ShowFullDetail]);
Expand Down
Loading
Loading