ObjectRev.cpp #1

  • //
  • guest/
  • andrew_mcdonald/
  • p4hl/
  • src/
  • dlls/
  • ObjectRev.cpp
  • View
  • Commits
  • Open Download .zip Download (6 KB)
// ObjectRev.cpp: implementation of the CObjectRev class.
//
//////////////////////////////////////////////////////////////////////

#include "clientapi.h"
#include "listnode.h"
#include "clientdepotuser.h"
#include "clientdiruser.h"
#include "clientfileuser.h"
#include "clientluser.h"
#include "filehead.h"
#include "changesorter.h"
#include "filelogcache.h"
#include "ObjectRev.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

LINK_ENTITY_TO_CLASS ( object_rev, CObjectRev);

CObjectRev::CObjectRev()
{
	fromarrows = NULL;
}

void CObjectRev::AddArrow(CObjectRev* aptr, ArrowType atype, Contrib acontrib)
{
	CObjectRevArrow* na = new CObjectRevArrow;
	na->ptr = aptr;
	na->type = atype;
	na->contrib = acontrib;
	na->next = fromarrows;
	fromarrows = na;
}

void CObjectRev::Spawn()
{
	Precache( );
	char* thismodel;
	switch (type)
	{
	default:
	case EDIT: thismodel = "models/rev/w_edit.mdl"; break;
	case ADD: thismodel = "models/rev/w_add.mdl"; break;
	case DEL: thismodel = "models/rev/w_delete.mdl"; break;
	case INTEG: thismodel = "models/rev/w_integ.mdl"; break;
	case BRANCH: thismodel = "models/rev/w_add.mdl"; break;
	}

	from = NULL;

	SET_MODEL( ENT(pev), thismodel);
	
	UTIL_SetOrigin( pev, pev->origin );
	target = (Vector)pev->origin;  //by default, we're already where we want to be.

	UTIL_SetSize( pev, Vector(-2.5, -2.5, -2.5), Vector( 2.5, 2.5, 2.5) );  //collision box!

	pev->movetype = MOVETYPE_FLY;
	pev->solid = SOLID_BBOX; 

	SetThink( Think );
	SetTouch( Touch );

	pev->nextthink = gpGlobals->time + 0.5;
}

void CObjectRev::Precache()
{
	PRECACHE_MODEL( "models/rev/w_edit.mdl" );
	PRECACHE_MODEL( "models/rev/w_add.mdl" );
	PRECACHE_MODEL( "models/rev/w_delete.mdl" );
	PRECACHE_MODEL( "models/rev/w_integ.mdl" );
	BeamSprite = PRECACHE_MODEL( "sprites/smoke.spr" ); 
}

void CObjectRev :: Think( void )
{
/*
	if (!IsInWorld())
	{
		parent->disown( this );
		UTIL_Remove( this );
		return;
	}
	Commenting this out because there might be "from" records pointing to this.  Screw it.  Generating
	"object fell out of level" errors is better than segfaulting.  If it ever needs to be fixed, then it can
	be done by making the "from" relationship doubly-linked, but I don't have the energy right now.
*/  
	if (UTIL_VecUpdate( &(pev->origin), target )) {
		pev->nextthink = gpGlobals->time + 0.05;
		UTIL_SetSize( pev, Vector(-2.5, -2.5, -2.5), Vector( 2.5, 2.5, 2.5) );  //collision box!
	}
	else 
	{
		CObjectRevArrow* arrow = fromarrows;
		short int red, green, blue, bright, width;
		pev->nextthink = gpGlobals->time + 0.5;
		while (arrow != NULL && arrow->ptr->target == arrow->ptr->pev->origin)
		{
			switch(arrow->contrib)
			{
			case all:
				width = 6; bright = 255; break;
			case some:
				width = 4; bright = 200; break;
			case none:
				width = 2; bright = 128; break;
			}
			// edit, branch, copy, ignore, impure, merge
			switch(arrow->type)
			{
			case edit:
				red = 200; green = 200; blue = 200; break;
			case branch:
				red = 255; green = 255; blue = 0; break;
			case copy:
				red = 0; green = 255; blue = 0; break;
			case ignore:
				red = 150; green = 0; blue = 255; break;
			case impure:
				red = 255; green = 0; blue = 0; break;
			case merge:
				red = 0; green = 0; blue = 255; break;
			}
			MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, arrow->ptr->pev->origin);

			WRITE_BYTE( TE_BEAMENTPOINT ); 
			WRITE_SHORT( entindex() ); 
			WRITE_COORD( arrow->ptr->pev->origin.x ); 
			WRITE_COORD( arrow->ptr->pev->origin.y ); 
			WRITE_COORD( arrow->ptr->pev->origin.z ); 
			WRITE_SHORT( BeamSprite ); // Beam sprite index. 
			WRITE_BYTE( 0 ); // Starting frame 
			WRITE_BYTE( 0 ); // Framerate 
			WRITE_BYTE( 5 ); // How long the beam stays on. 
			WRITE_BYTE( width ); //width
			WRITE_BYTE( 0 ); // Noise 
			WRITE_BYTE( red ); //red
			WRITE_BYTE( green ); 
			WRITE_BYTE( blue ); 
			WRITE_BYTE( bright ); 
			WRITE_BYTE( 0 ); // Speed, sort of.

			MESSAGE_END( );

			arrow = arrow->next;
		}
	}
}

void CObjectRev :: Touch( CBaseEntity* Thing )
{ 
	CBasePlayer *pl;
	CBaseEntity *be = CBaseEntity::Instance(Thing->pev->owner);

	if (Thing->IsPlayer()) pl = (CBasePlayer*) Thing;
	else if (be->IsPlayer()) pl = (CBasePlayer*) be;
	else return;

	if (Thing->IsLong()) {
		Long( pl );
		pl->m_flNextP4Time = gpGlobals->time + 0.5;
		return;
	}

	if (Thing->IsExpand()) {
		Expand( pl );
		pl->m_flNextP4Time = gpGlobals->time + 0.5;
		return;
	}

	if (pl->m_flNextP4Time > gpGlobals->time) return;
	pl->m_flNextP4Time = gpGlobals->time + 0.2;
	UTIL_PrintHud(pl, filerev.Text());
}

void CObjectRev::Long( CBasePlayer* pl )
{
	ClientLuser ui;
	ClientApi client;
	if (P4PORT.Length()) client.SetPort(P4PORT.Text());
	Error e;
	StrBuf msg = StrBuf();

	client.Init( &e );
	if (e.GetSeverity()) {
		e.Fmt(&msg);
		UTIL_FatalHud(pl, msg.Text());
		pl->m_flNextP4Time = gpGlobals->time + 20.0; //20 second delay on connect error
		return;
	}
	
	char* args[1];
	args[0] = filerev.Text();

	client.SetArgv(1, args);
	client.Run( "filelog", &ui );

	client.Final( &e );
	if (e.GetSeverity()) {
		e.Fmt(&msg);
		UTIL_WarningHud(pl, msg.Text());
	}

	UTIL_PrintHud( pl, ui.message.Text());
}

void CObjectRev::Expand( CBasePlayer* pl )
{
	if (!istext)
	{
		UTIL_PrintHud(pl, "===non-text file===\n");
		return;
	}

	ClientLuser ui;
	ClientApi client;
	if (P4PORT.Length()) client.SetPort(P4PORT.Text());
	Error e;
	StrBuf msg = StrBuf();

	client.Init( &e );
	if (e.GetSeverity()) {
		e.Fmt(&msg);
		UTIL_FatalHud(pl, msg.Text());
		pl->m_flNextP4Time = gpGlobals->time + 20.0; //20 second delay on connect error
		return;
	}
	
	char* args[2];
	args[0] = "-q";
	args[1] = filerev.Text();

	client.SetArgv(2, args);
	client.Run( "print", &ui );

	client.Final( &e );
	if (e.GetSeverity()) {
		e.Fmt(&msg);
		UTIL_WarningHud(pl, msg.Text());
	}

	UTIL_PrintHud( pl, ui.message.Text());
}
# Change User Description Committed
#1 7292 Andrew McDonald initial submittal
//guest/sam_stafford/p4hl/src/dlls/ObjectRev.cpp
#9 1689 Sam Stafford Integrate 02.1 API and code cleanup to P4HL.
 Lots of work.  Phew.
#8 1549 Sam Stafford Quick tweak to ObjectRev to make sure it's compatible with new
RevType structure.

No functional change.
#7 1452 Sam Stafford Fix nasty flickering bug introduced by FileRevArrow conversion in a
stupid attempt to compensate for the flickering I was seeing as a
result of duplicate pointers (in reality, I only made things worse!).

Lesson learned is to avoid drawing lasers overlapping each other,
which means making the length of time the laser stays on equal to the
time between activations if at all possible.
#6 1405 Sam Stafford Phew - this was a big one!

New functionality:
    The rare case in which a revision has multiple parents, due to
    multiple resolves before submit, is now handled properly.  There
    is no limit on the number of "parents" a revision may have.

    Integration lines are now always "weighted" to indicate whether
    they contributed all, some, or none to the target.  For example,
    a "branch" line will be very solid and wide, whereas an "ignore"
    will be thin and faint.

Rearchitecture:
    Now using low-cost structs to keep track of integration information.
    Also being just a little more efficient with scanning through large
    data structures.  Quite a bit of general code bloat trimmed off now
    that some of the kludges are gone.

Possible problems:
    Not sure yet, but it might happen that "duplicate" integration
    pointers will be created, now that it's not a single variable which
    would get overwritten in the event of a duplicate.

to-do:
    Trim off obsolete member variables.  Use more enums and fewer #defs.
#5 1007 Sam Stafford A stab at making P4HL a bit more accessible to Perforce novices.
During the Precache() phase of the P4HL objects, a "p4 info" is
executed.  If this returns any errors, odds are there's no server
there (I can't think of what other error "p4 info" would return).
If this happens, use "public.perforce.com:1666" as the new port
value for all future Perforce transactions during this session,
and send a message to the console explaining this.
#4 1004 Sam Stafford Different file types are now treated differently - the ObjectFiles
have different skins depending on file type of the head rev, and
non-text revisions will not attempt to display their contents when
expanded.

Possible bug: old-style filetypes might be detected wrong (ie "ktext"
instead of "text+k").  I'd have to put in some pretty complex logic to
make it completely foolproof and backwards-compatible.  Right now it just errs
on the side of thinking a file is text if there's any confusion.
#3 993 Sam Stafford Improvements to integ pointer display :
1) Integ pointers not drawn until both revs have stopped moving.
2) "Branch" type pointers always drawn if target is a "branch" rev.
#2 991 Sam Stafford Tweaks to display of ObjectRevs:
    1) Random variation in their height.  This is intended to make
    overlapping lasers less common.
    2) The "main" revisions are now connected by brighter white beams   
    in order to make it obvious which file is the one we asked about.
#1 937 Sam Stafford Renaming my guest directory to the more conventional
sam_stafford.
//guest/samwise/p4hl/src/dlls/ObjectRev.cpp
#1 936 Sam Stafford Adding P4HL to the public depot.
 See relnotes.txt for
installation instructions; all relevant files are under
p4hl/dist.

Source code is under p4hl/src in the form of a VC++ project.