Skip to content

Commit

Permalink
Per game settings; persist for anim and pinball
Browse files Browse the repository at this point in the history
  • Loading branch information
chaimgingold committed May 19, 2017
1 parent 2b6f67f commit f836f2b
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 34 deletions.
2 changes: 1 addition & 1 deletion assets/config/AnimWorld.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
</RectFinder>


<TimeVec>-1 0</TimeVec>
<DefaultTimeVec>-1 0</DefaultTimeVec>
<WorldUnitsToSeconds>85</WorldUnitsToSeconds>
<MaxFrameDist>20</MaxFrameDist>
<MaxScreenToFrameDist>50</MaxScreenToFrameDist>
Expand Down
2 changes: 1 addition & 1 deletion assets/config/PinballWorld.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

<!-- General -->
<SoundEnabled>1</SoundEnabled>
<UpVec>-1 0</UpVec>
<DefaultUpVec>-1 0</DefaultUpVec>
<Gravity>.05</Gravity>
<BallReclaimAreaHeight>4</BallReclaimAreaHeight>

Expand Down
81 changes: 67 additions & 14 deletions src/App/TablaApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,26 @@ fs::path TablaApp::getDocsPath() const
return getDocumentsDirectory() / kDocumentsDirectoryName ;
}

fs::path TablaApp::getUserGameSettingsPath() const
{
return getDocsPath() / "game-settings";
}

fs::path TablaApp::getUserLightLinkFilePath() const
{
return getDocsPath() / "LightLink.xml" ;
}

fs::path TablaApp::getUserSettingsFilePath() const
fs::path TablaApp::getUserSettingsFilePathForApp() const
{
return getDocsPath() / "settings.xml" ;
}

fs::path TablaApp::getUserSettingsFilePathForGame( string game ) const
{
return getUserGameSettingsPath() / (game + ".xml") ;
}

void TablaApp::setup()
{
cout << getAppPath() << endl;
Expand All @@ -73,8 +83,9 @@ void TablaApp::setup()
// enumerate hardware
enumerateDisplaysAndCamerasToConsole();

// make docs folder if needed
// make docs folders if needed
if ( !fs::exists(getDocsPath()) ) fs::create_directory(getDocsPath());
if ( !fs::exists(getUserGameSettingsPath()) ) fs::create_directory(getUserGameSettingsPath());

// app config
mFileWatch.loadXml( hotloadableAssetPath("config") / "app.xml", [this]( XmlTree xml ) {
Expand All @@ -101,7 +112,7 @@ void TablaApp::setup()
// user settings
mPipelineStageSelection = "undistorted"; // default (don't want it in header)

mFileWatch.loadXml( getUserSettingsFilePath(), [this]( XmlTree xml )
mFileWatch.loadXml( getUserSettingsFilePathForApp(), [this]( XmlTree xml )
{
if ( xml.hasChild("settings") ) {
loadUserSettingsFromXml(xml.getChild("settings"));
Expand Down Expand Up @@ -541,20 +552,47 @@ void TablaApp::loadGame( string systemName )
cout << "loadGame: " << mGameWorld->getSystemName() << endl;

// get config xml
fs::path xmlConfigPath = getXmlConfigPathForGame(mGameWorld->getSystemName()) ;

mFileWatch.loadXml( xmlConfigPath, [xmlConfigPath,this]( XmlTree xml )
{
// if we had already loaded this once, we stomp that old lambda and force a reload now.
fs::path xmlConfigPath = getXmlConfigPathForGame(mGameWorld->getSystemName()) ;

// why conditional?
// make sure we aren't hotloading xml from game we aren't running anymore
if ( xmlConfigPath == getXmlConfigPathForGame(mGameWorld->getSystemName()) )
mFileWatch.loadXml( xmlConfigPath, [xmlConfigPath,this]( XmlTree xml )
{
// if we had already loaded this once, we stomp that old lambda and force a reload now.

// why conditional?
// make sure we aren't hotloading xml from game we aren't running anymore
if ( xmlConfigPath == getXmlConfigPathForGame(mGameWorld->getSystemName()) )
{
// set params from xml
setGameWorldXmlParams(xml);
}
});
}

// get settings xml
{
fs::path xmlSettingsPath = getUserSettingsFilePathForGame(mGameWorld->getSystemName()) ;

// init settings?
if ( !fs::exists(xmlSettingsPath) )
{
// set params from xml
setGameWorldXmlParams(xml);
mGameWorld->initSettings();
mGameWorld->setAreUserSettingsDirty(); // so we save them...
}
});

// load and watch...
mFileWatch.loadXml( xmlSettingsPath, [xmlSettingsPath,this]( XmlTree xml )
{
// if we had already loaded this once, we stomp that old lambda and force a reload now.

// why conditional?
// make sure we aren't hotloading xml from game we aren't running anymore
if ( xmlSettingsPath == getUserSettingsFilePathForGame(mGameWorld->getSystemName()) )
{
mGameWorld->setUserSettings( xml );
}
});
}

// set world bounds
mGameWorld->setWorldBoundsPoly( getWorldBoundsPoly() );
Expand Down Expand Up @@ -767,6 +805,7 @@ void TablaApp::update()
mGameWorld->setMousePosInWorld(getMousePosInWorld()); // TODO: figure out if it actually contains it...
mGameWorld->update();
mGameWorld->prepareToDraw();
maybeSaveGameWorldSettings();
}

if (mAVClacker>0.f) mAVClacker = max(0.f,mAVClacker-.1f);
Expand Down Expand Up @@ -1211,7 +1250,21 @@ XmlTree TablaApp::getUserSettingsXml() const
void TablaApp::saveUserSettings()
{
XmlTree t = getUserSettingsXml();
t.write( writeFile(getUserSettingsFilePath()) );
t.write( writeFile(getUserSettingsFilePathForApp()) );
}

void TablaApp::maybeSaveGameWorldSettings() const
{
if ( mGameWorld && mGameWorld->getAreUserSettingsDirty() )
{
fs::path path = getUserSettingsFilePathForGame(mGameWorld->getSystemName());

XmlTree settingsXml = mGameWorld->getUserSettings();

settingsXml.write( writeFile(path) );

mGameWorld->setAreUserSettingsDirty(false);
}
}

void TablaApp::saveCameraImageToDisk()
Expand Down
7 changes: 5 additions & 2 deletions src/App/TablaApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,10 @@ class TablaApp : public App {

// paths
fs::path getDocsPath() const;
fs::path getUserGameSettingsPath() const;
fs::path getUserLightLinkFilePath() const;
fs::path getUserSettingsFilePath() const;
fs::path getUserSettingsFilePathForApp() const;
fs::path getUserSettingsFilePathForGame( string ) const;

string getOverloadedAssetPath() const; // calculates it (from arguments, env vars)
string mOverloadedAssetPath; // => is stored here
Expand All @@ -213,7 +215,8 @@ class TablaApp : public App {
void loadUserSettingsFromXml( XmlTree );
XmlTree getUserSettingsXml() const;
void saveUserSettings();

void maybeSaveGameWorldSettings() const;

// misc
void saveCameraImageToDisk();

Expand Down
9 changes: 7 additions & 2 deletions src/Utilities/xml.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,16 @@ inline bool getVec2sFromXml( const XmlTree &xml, string name, vec2 var[], int le
else return false;
}

inline string vecToString( vec2 v )
{
return toString(v.x) + " " + toString(v.y);
}

inline XmlTree vec2sToXml( string name, vector<vec2> vs )
{
XmlTree xml(name,"");
for( auto v : vs ) {
xml.push_back( XmlTree("v", toString(v.x) + " " + toString(v.y) ) );
xml.push_back( XmlTree("v", vecToString(v) ) );
}
return xml;
}
Expand All @@ -220,7 +225,7 @@ inline XmlTree vec2sToXml( string name, const vec2* vs, int n )
XmlTree xml(name,"");
for ( int i=0; i<n; ++i ) {
vec2 v = vs[i];
xml.push_back( XmlTree("v", toString(v.x) + " " + toString(v.y) ) );
xml.push_back( XmlTree("v", vecToString(v) ) );
}
return xml;
}
Expand Down
5 changes: 0 additions & 5 deletions src/Vision/LightLink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@
#include "LightLink.h"
#include "xml.h"

static string vecToString( vec2 v )
{
return toString(v.x) + " " + toString(v.y);
};

static string noNewline( string str )
{
for( auto &c : str ) {
Expand Down
28 changes: 27 additions & 1 deletion src/Worlds/AnimWorld/AnimWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ AnimWorld::AnimWorld()

void AnimWorld::setParams( XmlTree xml )
{
getXml(xml,"TimeVec",mTimeVec);
getXml(xml,"DefaultTimeVec",mDefaultTimeVec);
getXml(xml,"WorldUnitsToSeconds",mWorldUnitsToSeconds);
getXml(xml,"MaxFrameDist",mMaxFrameDist);
getXml(xml,"MaxScreenToFrameDist",mMaxScreenToFrameDist);
Expand All @@ -63,6 +63,30 @@ void AnimWorld::setParams( XmlTree xml )
}
}

void AnimWorld::initSettings()
{
mTimeVec = mDefaultTimeVec;
}

XmlTree AnimWorld::getUserSettings() const
{
XmlTree xml("settings","");

xml.push_back( XmlTree("TimeVec", vecToString(mTimeVec)) );

return xml;
}

void AnimWorld::setUserSettings( XmlTree settingsXml )
{
if ( settingsXml.hasChild("settings") )
{
XmlTree xml = settingsXml.getChild("settings");

getXml(xml, "TimeVec", mTimeVec );
}
}

map<string,vec2> AnimWorld::getOrientationVecs() const
{
map<string,vec2> m;
Expand All @@ -78,6 +102,8 @@ void AnimWorld::setOrientationVec ( string name, vec2 value )
{
mTimeVec = value;
}

setAreUserSettingsDirty();
}

void AnimWorld::printAnims( const AnimSeqMap& as )
Expand Down
7 changes: 6 additions & 1 deletion src/Worlds/AnimWorld/AnimWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,13 @@ class AnimWorld : public GameWorld
string getSystemName() const override { return "AnimWorld"; }

void setParams( XmlTree ) override;
void updateVision( const Vision::Output&, Pipeline& ) override;

void initSettings() override;
XmlTree getUserSettings() const override;
void setUserSettings( XmlTree ) override;

void update() override;
void updateVision( const Vision::Output&, Pipeline& ) override;
void draw( DrawType ) override;

void drawMouseDebugInfo( vec2 ) override;
Expand All @@ -122,6 +126,7 @@ class AnimWorld : public GameWorld
Rectf getFrameBBoxInLocalSpace( const Frame& ) const;

float mAnimTime; // our local animation time, in case we want to pause, etc...
vec2 mDefaultTimeVec=vec2(1,0);
vec2 mTimeVec=vec2(1,0);
float mWorldUnitsToSeconds=10.f;
float mAnimLengthQuantizeToSec=.5f;
Expand Down
28 changes: 22 additions & 6 deletions src/Worlds/GameWorld/GameWorld.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,44 @@ class GameWorld
public:
virtual ~GameWorld() {} // make sure children can overload destructor


// names used for loading associated files and showing to user
virtual string getSystemName() const { return "GameWorld"; } // for xml param block name
virtual string getUserName() const { return getSystemName(); }


// load hard coded configuration/tuning xml data
virtual void setParams( XmlTree ){}

void setVisionParams( Vision::Params p ) { mVisionParams=p; }
Vision::Params getVisionParams() const { return mVisionParams; }
// app automatically loads xml params for GameWorld and sets them.
// it then gets them when they are needed.

virtual void setParams( XmlTree ){}
virtual void updateVision( const Vision::Output&, Pipeline& ){} // probably lower freq than update()

// user settings
virtual void initSettings() {} // called if there is no settings file on disk
virtual XmlTree getUserSettings() const { return XmlTree(); }
virtual void setUserSettings( XmlTree ) {}
// tell system that settings changed so it can save them; (and it can tell us it saved them)
void setAreUserSettingsDirty( bool dirty=true ) { mUserSettingsDirty=dirty; }
bool getAreUserSettingsDirty() { return mUserSettingsDirty; }

// world bounds + orientation
void setWorldBoundsPoly( PolyLine2 ); // only calls didChange if it is different
PolyLine2 getWorldBoundsPoly() const { return mWorldBoundsPoly; }
virtual void worldBoundsPolyDidChange(){}

virtual map<string,vec2> getOrientationVecs() const { return map<string,vec2>(); }
virtual void setOrientationVec ( string, vec2 ) {}

vec2 getRandomPointInWorldBoundsPoly() const; // a little lamely special case;
// might be more useful to have something like random point on contour,
// and then pick whether you want a hole or not hole.
// randomPointOnContour()

virtual map<string,vec2> getOrientationVecs() const { return map<string,vec2>(); }
virtual void setOrientationVec ( string, vec2 ) {}


// event handling
enum class DrawType
{
Projector,
Expand All @@ -56,6 +71,7 @@ class GameWorld

virtual void gameWillLoad(){}
virtual void update(){} // called each frame
virtual void updateVision( const Vision::Output&, Pipeline& ){} // probably lower freq than update()
virtual void prepareToDraw() {} // called once per frame, before all draw calls.
virtual void draw( DrawType ){} // might be called many times per frame

Expand All @@ -77,7 +93,7 @@ class GameWorld
Vision::Params mVisionParams;
PolyLine2 mWorldBoundsPoly;
vec2 mMousePosInWorld;

bool mUserSettingsDirty=false;
};
typedef std::shared_ptr<GameWorld> GameWorldRef;

Expand Down
Loading

0 comments on commit f836f2b

Please sign in to comment.