Here is some of the code that can be re-used if needed. I think I got all the main changes I made. I can dig around some more if needed.
This was my first time using SDL so I just hacked together code pieces for the Texture Selection menu item. It works fine for me, but I may not be doing things correctly.
Code: Select all
// ******************************************************
// Texture Selection
//
// Menu item class that displays the selected texture at
// the bottom right of the screen. It can be configured
// to tint the texture using the supplied RGB values to
// show what the texture would look like on a cycle body,
// wheel, or trail.
//
// Added by k
// ******************************************************
class gMenuItemTextureSelection: public uMenuItemFileSelection
{
protected:
tString& targ_;
tString lastTarget;
int *rgb_;
int oldrgb_[3];
int flag_;
gRealColor color_;
gTextureCycle* texture1;
rTexture* texture2;
public:
gMenuItemTextureSelection(
uMenu *m, char *tit, const char *help, tString& targ,
const char *dir, const char *fileSpec,
const char *defaultFileName, const char *defaultFilePath,
int *RGB, int flag = 0,
int getFilesFlag = 1, bool formatName = true )
:uMenuItemFileSelection( m, tit, help, targ, dir,
fileSpec, defaultFileName, defaultFilePath, getFilesFlag, formatName ),
targ_( targ ), rgb_( RGB ), flag_( flag )
{
m->RequestSpaceBelow( .2 );
oldrgb_[0] = 15;
oldrgb_[1] = 15;
oldrgb_[2] = 15;
color_.r = 1.0;
color_.g = 1.0;
color_.b = 1.0;
texture1 = NULL;
texture2 = NULL;
}
virtual ~gMenuItemTextureSelection()
{
#ifndef DEDICATED
tDESTROY( texture1 );
delete texture1;
tDESTROY( texture2 );
delete texture2;
#endif
};
virtual REAL SpaceRight() { return .2; }
virtual void RenderBackground()
{
#ifndef DEDICATED
if ( !sr_glOut )
return;
uMenuItemFileSelection::RenderBackground();
//const char * p1 = (const char *) lastTarget;
//const char * p2 = (const char *) *target;
bool bTargetChanged = false;
bool bColorChanged = false;
if ( strcmp( (const char *) lastTarget, (const char *) *target ) != 0 )
bTargetChanged = true;
if ( ( oldrgb_[0] != rgb_[0] ) || ( oldrgb_[1] != rgb_[1] ) || ( oldrgb_[2] != rgb_[2] ) )
bColorChanged = true;
// If the target or color changed reload the texture
if ( bTargetChanged || bColorChanged )
{
// Save the target to optimize checking for menu changes
lastTarget = *target;
// Save color to check for external changes
oldrgb_[0] = rgb_[0];
oldrgb_[1] = rgb_[1];
oldrgb_[2] = rgb_[2];
// Convert the color for use by the texture
color_.r = rgb_[0]/15.0;
color_.g = rgb_[1]/15.0;
color_.b = rgb_[2]/15.0;
se_MakeColorValid( color_.r, color_.g, color_.b, 1.0f );
// Create the texture object. The wall texture does not need to be reloaded
// if only the color changed.
if ( flag_ == 0 || flag_ == 1 )
{
// Body and wheel texture
tDESTROY( texture1 );
delete texture1;
texture1 = new gTextureCycle( *target, color_, 1, 0, ( flag_ == 1 ? true : false ) );
}
else if ( bTargetChanged )
{
// Wall texture
tDESTROY( texture2 );
delete texture2;
texture2 = tNEW(rTexture)( rTEX_WALL, *target, 1, 0 );
}
}
// If a texture is loaded draw it
if ( texture1 != NULL || texture2 != NULL )
{
// Select the texture
if ( texture1 != NULL )
{
// Draw a white background behind the texture
REAL r = 1.0;
REAL g = 1.0;
REAL b = 1.0;
se_MakeColorValid( r, g, b, 1.0f );
glColor3f( r, g, b );
glRectf( .8,-.8,.98,-.98 );
texture1->Select();
}
else
{
texture2->Select();
// Color the wall texture
glColor3f( color_.r, color_.g, color_.b );
}
// Draw the texture at the bottom right of the menu
if ( ( texture1 != NULL && texture1->Loaded() ) || ( texture2 != NULL && texture2->Loaded() ) )
{
BeginQuads();
TexCoord(0,0);
Vertex(0.8, -0.8);
TexCoord(0,1);
Vertex(0.8, -0.98);
TexCoord(1,1);
Vertex(0.98, -0.98);
TexCoord(1,0);
Vertex(0.98, -0.8);
RenderEnd();
}
}
#endif
}
};
Here is the code for a simple menu I added somewhere in the System menu for selecting the default textures to use for other players:
Code: Select all
tString sg_CycleBodyTexture = "textures/cycle_body.png";
tString sg_CycleWheelTexture = "textures/cycle_wheel.png";
tString sg_CycleWallTexture = "textures/dir_wall.png";
int sg_CycleWallStretch = 1.0;
static tConfItem<tString> cyclebodytex("CYCLE_BODY_TEXTURE", sg_CycleBodyTexture);
static tConfItem<tString> cyclewheeltex("CYCLE_WHEEL_TEXTURE", sg_CycleWheelTexture);
static tConfItem<tString> cyclewalltex("CYCLE_WALL_TEXTURE", sg_CycleWallTexture);
static tConfItem<int> cyclewallstretch("CYCLE_WALL_STRETCH", sg_CycleWallStretch);
void sg_TextureMenu()
{
int rgb[3] = { 15, 15, 15 };
uMenu textureMenu("$texture_menu");
uMenuItemInt cwlsm( &textureMenu,"$cycle_wall_stretch_text",
"$cycle_wall_stretch_help", sg_CycleWallStretch, 1, 10, 1);
gMenuItemTextureSelection cwltm( &textureMenu,"$cycle_wall_texture_text",
"$cycle_wall_texture_help", sg_CycleWallTexture, "textures/cycle_wall/", "*.png",
"$feature_default_text", "textures/dir_wall.png", rgb, 2 );
gMenuItemTextureSelection cwtm( &textureMenu,"$cycle_wheel_texture_text",
"$cycle_wheel_texture_help", sg_CycleWheelTexture, "textures/cycle_wheel/", "*.png",
"$feature_default_text", "textures/cycle_wheel.png", rgb, 1 );
gMenuItemTextureSelection cbtm( &textureMenu, "$cycle_body_texture_text",
"$cycle_body_texture_help", sg_CycleBodyTexture, "textures/cycle_body/", "*.png",
"$feature_default_text", "textures/cycle_body.png", rgb, 0 );
textureMenu.Enter();
// request network synchronisation
ePlayerNetID::Update();
for (int i=MAX_PLAYERS-1; i>=0; i--)
{
if (ePlayer::PlayerIsInGame(i))
{
ePlayer* p = ePlayer::PlayerConfig(i);
if (p->netPlayer)
p->netPlayer->RequestSync();
}
}
}
Here is the modification to the Player Menu to create a new Cycle Configuration menu. This replaces the color selection code in gMenus.cpp:sg_PlayerMenu(int Player):
Code: Select all
uMenu cycle_menu("$cycle_config_text");
uMenuItemInt playerCWLS( &cycle_menu,"$cycle_wall_stretch_text",
"$cycle_wall_stretch_help", p->cycleWallStretch, 1, 10, 1);
gMenuItemTextureSelection playerCWLT( &cycle_menu,"$cycle_wall_texture_text",
"$cycle_wall_texture_help", p->cycleWallTexture, "textures/cycle_wall/", "*.png",
"$feature_default_text", "textures/dir_wall.png", p->trgb, 2 );
gMenuItemTextureSelection playerCWT( &cycle_menu,"$cycle_wheel_texture_text",
"$cycle_wheel_texture_help", p->cycleWheelTexture, "textures/cycle_wheel/", "*.png",
"$feature_default_text", "textures/cycle_wheel.png", p->rgb, 1 );
gMenuItemTextureSelection playerCBT( &cycle_menu, "$cycle_body_texture_text",
"$cycle_body_texture_help", p->cycleBodyTexture, "textures/cycle_body/", "*.png",
"$feature_default_text", "textures/cycle_body.png", p->rgb, 0 );
ArmageTron_color_menuitem TB(&cycle_menu,"$player_trail_blue_text",
"$player_trail_blue_help",
p->trgb,2);
ArmageTron_color_menuitem TG(&cycle_menu,"$player_trail_green_text",
"$player_trail_green_help",
p->trgb,1);
ArmageTron_color_menuitem TR(&cycle_menu,"$player_trail_red_text",
"$player_trail_red_help",
p->trgb,0);
ArmageTron_color_menuitem B(&cycle_menu,"$player_blue_text",
"$player_blue_help",
p->rgb,2);
ArmageTron_color_menuitem G(&cycle_menu,"$player_green_text",
"$player_green_help",
p->rgb,1);
ArmageTron_color_menuitem R(&cycle_menu,"$player_red_text",
"$player_red_help",
p->rgb,0);
Here is a simple music selection menu item that I never did anything with:
Code: Select all
// Music selection menu item
class gMenuItemMusicSelection: public uMenuItemFileSelection
{
public:
gMenuItemMusicSelection(
uMenu *m, char *tit, const char *help, tString& targ,
const char *defaultFileName, const char *defaultFilePath,
const char *dir = "music/", const char *fileSpec = "*.mod;*.s3m;*.xm;*.it;*.ogg;*.mp3",
int getFilesFlag = 1, bool formatName = false )
:uMenuItemFileSelection( m, tit, help, targ,
dir, fileSpec, defaultFileName, defaultFilePath, getFilesFlag, formatName ) {}
virtual ~gMenuItemMusicSelection() {}
};
Modifications to ePlayer.h for the new textures and trail color:
Code: Select all
class ePlayer: public uPlayerPrototype
int trgb[3]; // our trail color
tString cycleBodyTexture;
tString cycleWheelTexture;
tString cycleWallTexture;
int cycleWallStretch;
Code: Select all
class ePlayerNetID: public nNetObject
unsigned short tr,tg,tb; // our trail color
tString cycleBodyTexture;
tString cycleWheelTexture;
tString cycleWallTexture;
int cycleWallStretch;
Modifications to ePlayer.cpp for the new textures and trail color:
Code: Select all
extern tString sg_CycleBodyTexture; // from gMenu.cpp
extern tString sg_CycleWheelTexture; // from gMenu.cpp
extern tString sg_CycleWallTexture; // from gMenu.cpp
extern int sg_CycleWallStretch; // from gMenu.cpp
Code: Select all
ePlayer::ePlayer() {
...
confname.Clear();
confname << "COLOR_TRAIL_B_"<< id+1;
StoreConfitem(tNEW(tConfItem<int>) (confname,
"$color_trail_b_help",
trgb[2]));
confname.Clear();
confname << "COLOR_TRAIL_G_"<< id+1;
StoreConfitem(tNEW(tConfItem<int>) (confname,
"$color_trail_g_help",
trgb[1]));
confname.Clear();
confname << "COLOR_TRAIL_R_"<< id+1;
StoreConfitem(tNEW(tConfItem<int>) (confname,
"$color_trail_r_help",
trgb[0]));
confname.Clear();
confname << "CYCLE_BODY_TEXTURE_"<< id+1;
StoreConfitem(tNEW(tConfItemLine) (confname,
"$cycle_body_texture_help",
cycleBodyTexture));
confname.Clear();
confname << "CYCLE_WHEEL_TEXTURE_"<< id+1;
StoreConfitem(tNEW(tConfItemLine) (confname,
"$cycle_wheel_texture_help",
cycleWheelTexture));
confname.Clear();
confname << "CYCLE_WALL_TEXTURE_"<< id+1;
StoreConfitem(tNEW(tConfItemLine) (confname,
"$cycle_wall_texture_help",
cycleWallTexture));
confname.Clear();
confname << "CYCLE_WALL_STRETCH_"<< id+1;
StoreConfitem(tNEW(tConfItem<int>) (confname,
"$cycle_wall_stretch_help",
cycleWallStretch));
...
trgb[0]=rgb[0];
trgb[1]=rgb[1];
trgb[2]=rgb[2];
...
}
Code: Select all
ePlayerNetID::ePlayerNetID(int p):nNetObject(),listID(-1), teamListID(-1)
,pID(p), chatSpam_( se_chatSpamSettings ) {
...
if (p>=0){
ePlayer *P = ePlayer::PlayerConfig(p);
if (P){
name=P->Name();
r= P->rgb[0];
g= P->rgb[1];
b= P->rgb[2];
tr= P->trgb[0];
tg= P->trgb[1];
tb= P->trgb[2];
pingCharity=::pingCharity;
cycleBodyTexture = P->cycleBodyTexture;
cycleWheelTexture = P->cycleWheelTexture;
cycleWallTexture = P->cycleWallTexture;
cycleWallStretch = P->cycleWallStretch;
}
}
else{
name="AI";
cycleBodyTexture = sg_CycleBodyTexture;
cycleWheelTexture = sg_CycleWheelTexture;
cycleWallTexture = sg_CycleWallTexture;
cycleWallStretch = sg_CycleWallStretch;
}
...
}
Code: Select all
ePlayerNetID::WriteSync(nMessage &m){
...
// Cycle trail color and textures added by k
m.Write(tr);
m.Write(tg);
m.Write(tb);
m << cycleBodyTexture;
m << cycleWheelTexture;
m << cycleWallTexture;
m << cycleWallStretch;
}
Code: Select all
void ePlayerNetID::ReadSync(nMessage &m){
...
// Cycle trail color and textures added by k
if (!m.End())
{
m.Read(tr);
m.Read(tg);
m.Read(tb);
m >> cycleBodyTexture;
m >> cycleWheelTexture;
m >> cycleWallTexture;
m >> cycleWallStretch;
}
else
{
tr = r;
tg = g;
tb = b;
cycleBodyTexture = sg_CycleBodyTexture;
cycleWheelTexture = sg_CycleWheelTexture;
cycleWallTexture = sg_CycleWallTexture;
cycleWallStretch = sg_CycleWallStretch;
}
// con << "Player info updated.\n";
// make sure we did not accidentally overwrite values
// ePlayer::Update();
// update the team
if ( nSERVER == sn_GetNetState() )
{
if ( nextTeam )
nextTeam->UpdateProperties();
if ( currentTeam )
currentTeam->UpdateProperties();
}
}
Code: Select all
void ePlayerNetID::TrailColor( REAL&a_r, REAL&a_g, REAL&a_b ) const
{
if ( ( static_cast<bool>(currentTeam) ) && ( currentTeam->IsHuman() ) )
{
REAL w = 5;
REAL r_w = 2;
REAL g_w = 1;
REAL b_w = 2;
a_r=(r_w*tr + w*currentTeam->TR())/( 15.0 * ( w + r_w ) );
a_g=(g_w*tg + w*currentTeam->TG())/( 15.0 * ( w + g_w ) );
a_b=(b_w*tb + w*currentTeam->TB())/( 15.0 * ( w + b_w ) );
}
else
{
a_r = tr/15.0;
a_g = tg/15.0;
a_b = tb/15.0;
}
}
Modifications to gCycle.h for the new textures and trail color:
Code: Select all
class gCycle: public eNetGameObject
gTextureCycle *wheelTex,*bodyTex;
gTextureCycle *customTexture;
rTexture *wallTexture;
int wallStretch;
gRealColor trailColor_;
Modifications to gCycle.cpp for the new textures and trail color:
Code: Select all
void gCycle::MyInitAfterCreation(){
...
if (sn_GetNetState()!=nCLIENT){
if(!player)
{ // distribute AI colors
// con << current_ai << ':' << take_ai << ':' << maxmindist << "\n\n\n";
con << "test\n";
color_.r=1;
color_.g=1;
color_.b=1;
trailColor_.r=1;
trailColor_.g=1;
trailColor_.b=1;
}
else
{
player->Color(color_.r,color_.g,color_.b);
player->TrailColor(trailColor_.r,trailColor_.g,trailColor_.b);
}
se_MakeColorValid( color_.r, color_.g, color_.b, 1.0f );
se_MakeColorValid( trailColor_.r, trailColor_.g, trailColor_.b, 1.0f ); // changed floor value - k
}
if (mp)
customTexture=new gTextureCycle("moviepack/bike.png",color_,0,0);
else{
// Make sure selected body texture exists.
tString s = "";
tString bodyTexFile = "textures/cycle_body.png";
if (player)
{
s = tDirectories::Data().GetReadPath( player->cycleBodyTexture );
if(strlen(s) > 0)
bodyTexFile = player->cycleBodyTexture;
}
// Make sure selected wheel texture exists.
tString wheelTexFile = "textures/cycle_wheel.png";
if (player)
{
s = tDirectories::Data().GetReadPath( player->cycleWheelTexture );
if(strlen(s) > 0)
wheelTexFile = player->cycleWheelTexture;
}
// Make sure selected wall texture exists.
tString wallTexFile = "textures/dir_wall.png";
if (player)
{
s = tDirectories::Data().GetReadPath( player->cycleWallTexture );
if(strlen(s) > 0)
wallTexFile = player->cycleWallTexture;
}
wheelTex = new gTextureCycle( wheelTexFile, color_, 0, 0, true );
bodyTex = new gTextureCycle( bodyTexFile, color_, 0, 0 );
wallTexture = new rTexture( rTEX_WALL, wallTexFile, 1, 0 );
wallStretch = player->cycleWallStretch;
}
...
}
Code: Select all
gCycle::gCycle(eGrid *grid, const eCoord &pos,const eCoord &d,ePlayerNetID *p,bool autodelete)
...
wheelTex = NULL;
bodyTex = NULL;
wallTexture = NULL;
wallStretch = 1;
...
}
Other code in gCycle.cpp: The destructor needs to destroy the new textures. The trail color and textures need to be transmitted to the server and other clients.
Other files had some changes as well, but I don't have time to figure out what they are right now. I'm going to keep a backup of this version in case it is ever needed.