Danbias/GameLogic/InstanceBlueprint.cpp

300 lines
10 KiB
C++

/////////////////////////////////////////////////////////////////////
// Created by Dan Andersson 2013
/////////////////////////////////////////////////////////////////////
/* // TODO
<object "painting_0">
<displayName>Painting</displayName>
hitPoints = 0
armour = 0
centerOfMass = 0 0 0
mass = 0
<model>../entities/models/painting_0.obj</model>
<description>
A painting of a brunette.@@She has brown eyes...
</description>
<box -0.12763351202 0.566205918789 0.7363961339 0.12763351202 -0.566205918789 -0.7363961339>
</box>
</object>
*/
#include "InstanceBlueprint.h"
#include "Utilities.h"
#include <fstream>
#include <sstream>
using namespace ::GameLogic;
using namespace ::Oyster::Math;
using ::std::string;
using ::std::vector;
using ::std::ifstream;
using ::std::stringstream;
namespace PrivateStatic
{
bool seekNextObject( string &idNameOutput, ::std::istream &source )
{
string str;
vector<string> splitString;
while( !source.eof() )
{
source >> str;
if( str.size() == 0 ) continue;
if( str[0] == '#' )
{ // rest of line is all commentary
::std::getline( source, str );
continue;
}
if( str[0] != '<' ) continue;
if( str.size() == 1 )
{ if( !source.eof() ) source >> str; }
else str = str.substr( 1 );
::Utility::String::toLowerCase( str );
if( str != "object" ) continue;
if( source.eof() ) return false;
source >> str;
::Utility::String::split( splitString, str, '\"' );
// since str have no prefix whitespaces, we can safely assume
// splitString[0] is the string we want. the rest is garbage.
idNameOutput = ::Utility::String::trim( splitString[0] );
return true;
}
return false;
}
void fillInstanceBlueprint( InstanceBlueprint &targetMem, ::std::istream &source, const Float4x4 &transform )
{
string line;
vector<string> splitString;
vector<string> tagDelims(2);
tagDelims[0] = "<";
tagDelims[1] = ">";
Float4 minPoint = Float4( Float3(::std::numeric_limits<Float>::max()), 1.0f ),
maxPoint = Float4( Float3(-::std::numeric_limits<Float>::max()), 1.0f ),
centerOfMass = Float4( Float3::null, 1.0f );
while( !source.eof() )
{
::std::getline( source, line );
line = ::Utility::String::trim( line );
if( line.length() == 0 ) continue;
if( line[0] == '#' ) continue;
splitString = vector<string>();
::Utility::String::split( splitString, line, '#' );
line = ::Utility::String::trim( splitString[0] );
if( line.length() == 0 )
continue; // just to be sure
if( line[0] == '<' )
{ // it's possibly <displayName>, <model>, <box>, <description> or </object>
splitString = vector<string>();
::Utility::String::split( splitString, line, tagDelims );
line = ::Utility::String::toLowerCase( ::Utility::String::trim(splitString[0]) );
if( line == "displayname" )
{ // <displayName>Painting</displayName>
targetMem.name = ::Utility::String::trim(splitString[1]);
}
else if( line == "model" )
{ // <model>../entities/models/painting_0.obj</model>
targetMem.objFileName = ::Utility::String::replaceCharacters( ::Utility::String::trim(splitString[1]), '/', '\\' );
}
else if( line == "description" )
{ /* <description>
A painting of a brunette.@@She has brown eyes...
</description> */
if( splitString.size() > 1 )
line = ::Utility::String::trim( splitString[1] );
else
{
if( source.eof() ) return;
::std::getline( source, line );
}
splitString = vector<string>();
::Utility::String::split( splitString, line, "@@" );
stringstream strBuilder( splitString[0] );
vector<string>::size_type numSplits = splitString.size();
for( vector<string>::size_type i = 1; i < numSplits; ++i )
{
if( i > 1 ) strBuilder << '\n';
strBuilder << splitString[i];
}
targetMem.description = strBuilder.str();
}
else if( line.find_first_of("box") == 0 )
{ /* <box -0.12763351202 0.566205918789 0.7363961339 0.12763351202 -0.566205918789 -0.7363961339>
</box> */
stringstream stream( line );
stream >> line;
if( line != "box" )
continue;
Float3 point;
::Utility::Stream::readFloats( point.element, stream, 3 );
minPoint.xyz = ::Utility::Value::min( minPoint.xyz, point );
maxPoint.xyz = ::Utility::Value::max( maxPoint.xyz, point );
::Utility::Stream::readFloats( point.element, stream, 3 );
minPoint.xyz = ::Utility::Value::min( minPoint.xyz, point );
maxPoint.xyz = ::Utility::Value::max( maxPoint.xyz, point );
}
else if( line == "/object" )
break;
continue; // no point to continue further down
} // end of "if( line[0] == '<' )"
splitString = vector<string>();
::Utility::String::split( splitString, line, '=' );
if( splitString.size() > 1 )
{
splitString[0] = ::Utility::String::toLowerCase( ::Utility::String::trim(splitString[0]) );
if( splitString[0] == "hitpoints" )
{ // hitPoints = 0
splitString[1] = ::Utility::String::trim(splitString[1]);
targetMem.hullPoints = ::std::atoi( splitString[1].c_str() );
}
else if( splitString[0] == "armour" ) // ??
{ // armour = 0
splitString[1] = ::Utility::String::trim(splitString[1]);
targetMem.shieldPoints = ::std::atoi( splitString[1].c_str() );
}
else if( splitString[0] == "mass" )
{ // mass = 0
splitString[1] = ::Utility::String::trim(splitString[1]);
targetMem.mass = (float)::std::atof( splitString[1].c_str() );
if( targetMem.mass == 0.0f )
targetMem.mass = ::std::numeric_limits<float>::max();
}
else if( splitString[0] == "centerofmass" )
{ // centerOfMass = 0 0 0
stringstream stream( splitString[1] );
::Utility::Stream::readFloats( centerOfMass.element, stream, 3 );
}
else if( splitString[0] == "maxspeed" )
{ // maxspeed = [ float of top speed: default 400.0 ]
stringstream stream( splitString[1] );
string value;
stream >> value;
targetMem.movementProperty.maxSpeed = (float)::std::atof( value.c_str() );
}
else if( splitString[0] == "deacceleration" )
{ // deacceleration = [ float of acceleration : default 50.0 ]
stringstream stream( splitString[1] );
string value;
stream >> value;
targetMem.movementProperty.deAcceleration = (float)::std::atof( value.c_str() );
}
else if( splitString[0] == "forward" )
{ // forward = [ float of acceleration : default 50.0 ]
stringstream stream( splitString[1] );
string value;
stream >> value;
targetMem.movementProperty.acceleration.forward = (float)::std::atof( value.c_str() );
}
else if( splitString[0] == "backward" )
{ // backward = [ float of acceleration : default 25.0 ]
stringstream stream( splitString[1] );
string value;
stream >> value;
targetMem.movementProperty.acceleration.backward = (float)::std::atof( value.c_str() );
}
else if( splitString[0] == "strafe" )
{ // strafe = [ float of acceleration : default 25.0 ]
stringstream stream( splitString[1] );
string sValue;
stream >> sValue;
float fValue = (float)::std::atof( sValue.c_str() );
targetMem.movementProperty.acceleration.horizontal = fValue;
targetMem.movementProperty.acceleration.vertical = fValue;
}
else if( splitString[0] == "turnspeed" )
{ // turnspeed = [ float in degrees : default 90.0 ]
stringstream stream( splitString[1] );
string sValue;
stream >> sValue;
float fValue = ::Utility::Value::radian( (float)::std::atof(sValue.c_str()) );
targetMem.rotationProperty.maxSpeed = fValue;
targetMem.rotationProperty.deAcceleration = 2.0f * fValue;
targetMem.rotationProperty.acceleration.pitch = fValue;
targetMem.rotationProperty.acceleration.yaw = fValue;
targetMem.rotationProperty.acceleration.roll = fValue;
}
}
}
targetMem.centerOfMass = transformVector( centerOfMass, centerOfMass, transform ).xyz;
if( minPoint != Float4( Float3(::std::numeric_limits<Float>::max()), 1.0f ) )
if( maxPoint != Float4( Float3(-::std::numeric_limits<Float>::max()), 1.0f ) )
{
transformVector( minPoint, minPoint, transform );
transformVector( maxPoint, maxPoint, transform );
targetMem.hitBox.position = (maxPoint.xyz - minPoint.xyz) * 0.5f;
targetMem.hitBox.halfSize = ::Utility::Value::abs( targetMem.hitBox.position );
targetMem.hitBox.position += minPoint.xyz;
}
}
}
InstanceBlueprint::Result InstanceBlueprint::loadFromFile( vector<InstanceBlueprint*> &output, vector<string> &idOutput, const string &entityFile, const Float4x4 &transform )
{
ifstream file( entityFile );
if( file.is_open() )
{
string idName, workingDir;
::Utility::String::extractDirPath( workingDir, entityFile, '\\' );
while( PrivateStatic::seekNextObject(idName, file) )
{
InstanceBlueprint* blueprint = new InstanceBlueprint();
PrivateStatic::fillInstanceBlueprint( *blueprint, file, transform );
if( blueprint->objFileName.length() > 0 )
blueprint->objFileName = workingDir + blueprint->objFileName;
output.push_back( blueprint );
idOutput.push_back( idName );
}
file.close( );
return Success;
}
else return Failure;
}
InstanceBlueprint::InstanceBlueprint( )
: name(), objFileName(), description(), mass(::std::numeric_limits<float>::max()), centerOfMass(Float3::null),
hullPoints(255), shieldPoints(255)
{
this->hitBox.halfSize = Float3::null;
this->hitBox.position = Float3::null;
this->movementProperty.maxSpeed = 400.0f;
this->movementProperty.deAcceleration = 50.0f;
this->movementProperty.acceleration.forward = 50.0f;
this->movementProperty.acceleration.backward = 25.0f;
this->movementProperty.acceleration.horizontal = 25.0f;
this->movementProperty.acceleration.vertical = 25.0f;
this->rotationProperty.maxSpeed = ::Utility::Value::radian( 90.0f );
this->rotationProperty.deAcceleration = ::Utility::Value::radian( 180.0f );
this->rotationProperty.acceleration.pitch = ::Utility::Value::radian( 90.0f );
this->rotationProperty.acceleration.yaw = ::Utility::Value::radian( 90.0f );
this->rotationProperty.acceleration.roll = ::Utility::Value::radian( 90.0f );
}