Skip to content

Commit 10fd073

Browse files
committed
🎮 Added videocamera flipping to Tuning UI
The full `addonpart_tweak_videocamera` mechanism wasn't implemented, only the UI override.
1 parent 9d78fec commit 10fd073

File tree

8 files changed

+156
-8
lines changed

8 files changed

+156
-8
lines changed

source/main/ForwardDeclarations.h

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ namespace RoR
7979
typedef int CommandkeyID_t; //!< Index into `Actor::ar_commandkeys` (BEWARE: indexed 1-MAX_COMMANDKEYS, 0 is invalid value, negative subscript of any size is acceptable, see `class CmdKeyArray` ).
8080
static const CommandkeyID_t COMMANDKEYID_INVALID = 0;
8181

82+
typedef int VideoCameraID_t; //!< Index into `GfxActor::m_videocameras`, use `RoR::VIDEOCAMERAID_INVALID` as empty value
83+
static const VideoCameraID_t VIDEOCAMERAID_INVALID = -1;
84+
8285
typedef int ScriptRetCode_t; //!< see enum `RoR::ScriptRetCode` - combines AngelScript codes and RoR internal codes.
8386

8487
typedef int TerrainEditorObjectID_t; //!< Offset into `RoR::TerrainObjectManager::m_editor_objects`, use `RoR::TERRAINEDITOROBJECTID_INVALID` as empty value.

source/main/gfx/GfxData.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,16 @@ struct Prop
220220
/// either in-scene texture or external window.
221221
struct VideoCamera
222222
{
223-
VideoCamRole vcam_role = VCAM_ROLE_INVALID;
223+
VideoCamRole vcam_role = VCAM_ROLE_INVALID; //!< Active role assigned at spawn (i.e. TRACKING if tracking node was set)
224+
VideoCamRole vcam_role_orig = VCAM_ROLE_INVALID; //!< User-defined role from rig-def file, may be different from final active role.
224225
NodeNum_t vcam_node_center = NODENUM_INVALID;
225226
NodeNum_t vcam_node_dir_y = NODENUM_INVALID;
226227
NodeNum_t vcam_node_dir_z = NODENUM_INVALID;
227228
NodeNum_t vcam_node_alt_pos = NODENUM_INVALID;
228229
NodeNum_t vcam_node_lookat = NODENUM_INVALID; //!< Only for VCAM_ROLE_TRACK_CAM
229230
Ogre::Quaternion vcam_rotation;
230231
Ogre::Vector3 vcam_pos_offset = Ogre::Vector3::ZERO;
232+
std::string vcam_mat_name_orig; //!< For display in Tuning UI: Original material name from rig-def file, without per-actor stamping
231233
Ogre::MaterialPtr vcam_material;
232234
std::string vcam_off_tex_name; //!< Used when videocamera is offline
233235
Ogre::Camera* vcam_ogre_camera = nullptr;

source/main/gui/panels/GUI_TopMenubar.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,90 @@ void TopMenubar::Draw(float dt)
19391939
ImGui::PopID(); // material_name.c_str()
19401940
}
19411941
}
1942+
1943+
// Draw videocameras
1944+
size_t total_videocameras = tuning_actor->GetGfxActor()->getVideoCameras().size();
1945+
std::string videocameras_title = fmt::format(_LC("Tuning", "Videocameras ({})"), total_videocameras);
1946+
if (ImGui::CollapsingHeader(videocameras_title.c_str()))
1947+
{
1948+
// Draw all videocameras (those removed by addonparts are also present as placeholders)
1949+
for (VideoCameraID_t videocameraid = 0; videocameraid < (int)total_videocameras; videocameraid++)
1950+
{
1951+
ImGui::PushID(videocameraid);
1952+
ImGui::AlignTextToFramePadding();
1953+
1954+
this->DrawTuningBoxedSubjectIdInline(videocameraid);
1955+
1956+
VideoCamRole current_role_def = tuning_actor->GetGfxActor()->getVideoCameras()[videocameraid].vcam_role_orig;
1957+
if (current_role_def != VCAM_ROLE_MIRROR && current_role_def != VCAM_ROLE_MIRROR_NOFLIP)
1958+
{
1959+
// Tuning menu is limited to only switch MIRROR/MIRROR_NOFLIP, so not-mirrors can be ignored.
1960+
ImGui::TextDisabled("(Not a mirror)");
1961+
}
1962+
else
1963+
{
1964+
// Draw RTT material name
1965+
ImGui::SameLine();
1966+
ImGui::Text("%s", tuning_actor->GetGfxActor()->getVideoCameras()[videocameraid].vcam_mat_name_orig.c_str());
1967+
1968+
// Setup the 'forced' state orange styling
1969+
1970+
VideoCamRole forced_role_def = VCAM_ROLE_INVALID;
1971+
if (tuneup_def && tuneup_def->isVideoCameraRoleForced(videocameraid, /*[out]*/forced_role_def))
1972+
{
1973+
ImGui::PushStyleColor(ImGuiCol_Border, ORANGE_TEXT);
1974+
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
1975+
}
1976+
1977+
// Draw the 'flipped' checkbox
1978+
ImGui::SameLine();
1979+
const bool current_flipped = current_role_def == VCAM_ROLE_MIRROR;
1980+
bool requested_flipped = current_flipped;
1981+
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
1982+
float origCursorY = ImGui::GetCursorPosY();
1983+
ImGui::Checkbox("Flipped", &requested_flipped);
1984+
ImGui::PopStyleVar(1); // ImGuiStyleVar_FramePadding
1985+
1986+
1987+
// Draw reset button and reset the orange styling
1988+
1989+
bool resetPressed = false;
1990+
if (tuneup_def && tuneup_def->isVideoCameraRoleForced(videocameraid, /*[out]*/forced_role_def))
1991+
{
1992+
ImGui::SameLine();
1993+
ImGui::SameLine();
1994+
ImGui::PushStyleColor(ImGuiCol_Text, GRAY_HINT_TEXT);
1995+
resetPressed = ImGui::SmallButton(_LC("Tuning", "Reset"));
1996+
ImGui::PopStyleColor(); //ImGuiCol_Text, GRAY_HINT_TEXT
1997+
ImGui::PopStyleVar(); //ImGuiStyleVar_FrameBorderSize, 1.f
1998+
ImGui::PopStyleColor(); //ImGuiCol_Border, ORANGE_TEXT
1999+
}
2000+
2001+
// modify project if needed
2002+
if (current_flipped != requested_flipped)
2003+
{
2004+
const VideoCamRole desired_role = (requested_flipped) ? VCAM_ROLE_MIRROR : VCAM_ROLE_MIRROR_NOFLIP;
2005+
2006+
ModifyProjectRequest* req = new ModifyProjectRequest();
2007+
req->mpr_type = ModifyProjectRequestType::TUNEUP_FORCED_VCAM_ROLE_SET;
2008+
req->mpr_subject_id = videocameraid;
2009+
req->mpr_value_int = (int)desired_role;
2010+
req->mpr_target_actor = tuning_actor;
2011+
App::GetGameContext()->PushMessage(Message(MSG_EDI_MODIFY_PROJECT_REQUESTED, req));
2012+
}
2013+
else if (resetPressed)
2014+
{
2015+
ModifyProjectRequest* req = new ModifyProjectRequest();
2016+
req->mpr_type = ModifyProjectRequestType::TUNEUP_FORCED_VCAM_ROLE_RESET;
2017+
req->mpr_subject_id = videocameraid;
2018+
req->mpr_target_actor = tuning_actor;
2019+
App::GetGameContext()->PushMessage(Message(MSG_EDI_MODIFY_PROJECT_REQUESTED, req));
2020+
}
2021+
}
2022+
2023+
ImGui::PopID(); // videocameraid
2024+
}
2025+
}
19422026
}
19432027

19442028
m_open_menu_hoverbox_min = menu_pos - MENU_HOVERBOX_PADDING;

source/main/physics/ActorSpawner.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -6979,15 +6979,19 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def)
69796979
{
69806980
try
69816981
{
6982+
auto videocameraid = (VideoCameraID_t)m_actor->m_gfx_actor->m_videocameras.size();
69826983
RoR::VideoCamera vcam;
69836984

6984-
vcam.vcam_role = def->camera_role;
6985+
const VideoCamRole tweaked_role = TuneupUtil::getTweakedVideoCameraRole(m_actor->getWorkingTuneupDef(), videocameraid, def->camera_role);
6986+
vcam.vcam_role_orig = tweaked_role;
6987+
vcam.vcam_role = vcam.vcam_role_orig;
69856988
if (vcam.vcam_role == VCAM_ROLE_INVALID)
69866989
{
6987-
this->AddMessage(Message::TYPE_ERROR, "VideoCamera (mat: " + def->material_name + ") has invalid 'role': " + TOSTRING(def->camera_role));
6990+
this->AddMessage(Message::TYPE_ERROR, fmt::format("Skipping VideoCamera (mat: {}) with invalid 'role' ({})", def->material_name, (int)vcam.vcam_role_orig));
69886991
return;
69896992
}
69906993

6994+
vcam.vcam_mat_name_orig = def->material_name;
69916995
vcam.vcam_material = this->FindOrCreateCustomizedMaterial(def->material_name, m_custom_resource_group);
69926996
if (vcam.vcam_material.isNull())
69936997
{
@@ -7002,7 +7006,7 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def)
70027006

70037007
//rotate camera picture 180 degrees, skip for mirrors
70047008
float rotation_z = def->rotation.z + 180;
7005-
if (def->camera_role == VCAM_ROLE_MIRROR || def->camera_role == VCAM_ROLE_MIRROR_NOFLIP)
7009+
if (tweaked_role == VCAM_ROLE_MIRROR || tweaked_role == VCAM_ROLE_MIRROR_NOFLIP)
70067010
{
70077011
rotation_z += 180.0f;
70087012
}
@@ -7075,7 +7079,7 @@ void ActorSpawner::CreateVideoCamera(RigDef::VideoCamera* def)
70757079
vcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(vcam.vcam_render_tex->getName());
70767080

70777081
// this is a mirror, flip the image left<>right to have a mirror and not a cameraimage
7078-
if (def->camera_role == VCAM_ROLE_MIRROR)
7082+
if (tweaked_role == VCAM_ROLE_MIRROR)
70797083
vcam.vcam_material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureUScale(-1);
70807084
}
70817085

source/main/resources/CacheSystem.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -2117,6 +2117,16 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request)
21172117
request->mpr_target_actor->getWorkingTuneupDef()->protected_managedmats.erase(request->mpr_subject);
21182118
break;
21192119

2120+
case ModifyProjectRequestType::TUNEUP_FORCED_VCAM_ROLE_SET:
2121+
request->mpr_target_actor->ensureWorkingTuneupDef();
2122+
request->mpr_target_actor->getWorkingTuneupDef()->force_video_cam_roles[request->mpr_subject_id] = (VideoCamRole)request->mpr_value_int;
2123+
break;
2124+
2125+
case ModifyProjectRequestType::TUNEUP_FORCED_VCAM_ROLE_RESET:
2126+
request->mpr_target_actor->ensureWorkingTuneupDef();
2127+
request->mpr_target_actor->getWorkingTuneupDef()->force_video_cam_roles.erase(request->mpr_subject_id);
2128+
break;
2129+
21202130
case ModifyProjectRequestType::PROJECT_LOAD_TUNEUP:
21212131
{
21222132
// Instead of loading with the saved tuneup directly, keep the autogenerated and sync it with the save.

source/main/resources/CacheSystem.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ enum class ModifyProjectRequestType
223223
TUNEUP_FORCEREMOVE_PROP_RESET, //!< 'subject_id' is prop ID.
224224
TUNEUP_FORCEREMOVE_FLEXBODY_SET, //!< 'subject_id' is flexbody ID.
225225
TUNEUP_FORCEREMOVE_FLEXBODY_RESET, //!< 'subject_id' is flexbody ID.
226-
TUNEUP_FORCED_WHEEL_SIDE_SET, //!< 'subject_id' is wheel ID, 'value_int' is RoR::WheelSide
226+
TUNEUP_FORCED_WHEEL_SIDE_SET, //!< 'subject_id' is wheel ID, 'value_int' is `RoR::WheelSide`
227227
TUNEUP_FORCED_WHEEL_SIDE_RESET, //!< 'subject_id' is wheel ID.
228228
TUNEUP_FORCEREMOVE_FLARE_SET, //!< 'subject_id' is flare ID.
229229
TUNEUP_FORCEREMOVE_FLARE_RESET, //!< 'subject_id' is flare ID.
@@ -243,6 +243,8 @@ enum class ModifyProjectRequestType
243243
TUNEUP_PROTECTED_EXHAUST_RESET, //!< 'subject_id' is exhaust ID.
244244
TUNEUP_PROTECTED_MANAGEDMAT_SET, //!< 'subject' is managed material name.
245245
TUNEUP_PROTECTED_MANAGEDMAT_RESET, //!< 'subject' is managed material name.
246+
TUNEUP_FORCED_VCAM_ROLE_SET, //!< 'subject_id' is video camera ID, 'value_int' is `RoR::VideoCamRole`
247+
TUNEUP_FORCED_VCAM_ROLE_RESET, //!< 'subject_id' is video camera ID.
246248
PROJECT_LOAD_TUNEUP, //!< 'subject' is tuneup filename. This overwrites the auto-generated tuneup with the save.
247249
PROJECT_RESET_TUNEUP, //!< 'subject' is empty. This resets the auto-generated tuneup to orig. values.
248250
};

source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp

+38-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ TuneupDefPtr TuneupDef::clone()
7272
// nodes
7373
ret->protected_nodes = this->protected_nodes;
7474
ret->node_tweaks = this->node_tweaks;
75-
75+
76+
// video cameras
77+
ret->force_video_cam_roles = this->force_video_cam_roles;
78+
7679
// flares
7780
ret->protected_flares = this->protected_flares;
7881

@@ -110,7 +113,10 @@ void TuneupDef::reset()
110113
// nodes
111114
this->protected_nodes.clear();
112115
this->node_tweaks.clear();
113-
116+
117+
// video cameras
118+
this->force_video_cam_roles.clear();
119+
114120
// flares
115121
this->protected_flares.clear();
116122

@@ -135,6 +141,20 @@ bool TuneupDef::isWheelSideForced(WheelID_t wheelid, WheelSide& out_val) const
135141
}
136142
}
137143

144+
bool TuneupDef::isVideoCameraRoleForced(VideoCameraID_t camera_id, VideoCamRole& out_val) const
145+
{
146+
auto itor = force_video_cam_roles.find(camera_id);
147+
if (itor != force_video_cam_roles.end())
148+
{
149+
out_val = itor->second;
150+
return true;
151+
}
152+
else
153+
{
154+
return false;
155+
}
156+
}
157+
138158
// Tweaking helpers
139159

140160
float RoR::TuneupUtil::getTweakedWheelTireRadius(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, float orig_val)
@@ -233,6 +253,22 @@ WheelSide RoR::TuneupUtil::getTweakedWheelSide(TuneupDefPtr& tuneup_def, WheelID
233253
return orig_val;
234254
}
235255

256+
VideoCamRole RoR::TuneupUtil::getTweakedVideoCameraRole(TuneupDefPtr& tuneup_def, VideoCameraID_t camera_id, VideoCamRole orig_val)
257+
{
258+
if (tuneup_def)
259+
{
260+
VideoCamRole forced_role = VCAM_ROLE_INVALID;
261+
if (tuneup_def->isVideoCameraRoleForced(camera_id, forced_role))
262+
{
263+
return forced_role;
264+
}
265+
266+
// STUB: actual tweaking isn't implemented yet
267+
}
268+
269+
return orig_val;
270+
}
271+
236272
bool RoR::TuneupUtil::isWheelTweaked(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, TuneupWheelTweak*& out_tweak)
237273
{
238274

source/main/resources/tuneup_fileformat/TuneupFileFormat.h

+7
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct TuneupDef: public RefCountingObject<TuneupDef>
125125
std::set<PropID_t> force_remove_props; //!< UI overrides
126126
std::set<FlexbodyID_t> force_remove_flexbodies; //!< UI overrides
127127
std::map<WheelID_t, WheelSide> force_wheel_sides; //!< UI overrides
128+
std::map<VideoCameraID_t, VideoCamRole> force_video_cam_roles; //!< UI overrides
128129
std::set<FlareID_t> force_remove_flares; //!< User unticked an UI checkbox in Tuning menu, section Flares.
129130
std::set<ExhaustID_t> force_remove_exhausts; //!< User unticked an UI checkbox in Tuning menu, section Exhausts.
130131
std::set<std::string> force_remove_managedmats;//!< User unticked an UI checkbox in Tuning menu, section Managed Materials.
@@ -172,6 +173,7 @@ struct TuneupDef: public RefCountingObject<TuneupDef>
172173
bool isFlareForceRemoved(FlareID_t flareid) { return force_remove_flares.find(flareid) != force_remove_flares.end(); }
173174
bool isExhaustForceRemoved(ExhaustID_t exhaustid) { return force_remove_exhausts.find(exhaustid) != force_remove_exhausts.end(); }
174175
bool isManagedMatForceRemoved(const std::string& matname) { return force_remove_managedmats.find(matname) != force_remove_managedmats.end(); }
176+
bool isVideoCameraRoleForced(VideoCameraID_t camera_id, VideoCamRole& out_val) const;
175177
/// @}
176178
};
177179

@@ -242,6 +244,11 @@ class TuneupUtil
242244
static bool isManagedMatTweaked(TuneupDefPtr& tuneup_def, const std::string& matname, TuneupManagedMatTweak*& out_tweak);
243245
/// @}
244246

247+
/// @name VideoCamera helpers
248+
/// @{
249+
static VideoCamRole getTweakedVideoCameraRole(TuneupDefPtr& tuneup_def, VideoCameraID_t camera_id, VideoCamRole orig_val);
250+
/// @}
251+
245252
private:
246253

247254
static void ParseTuneupAttribute(const std::string& line, TuneupDefPtr& tuneup_def);

0 commit comments

Comments
 (0)