Sign in to follow this  

[Solved] Here's a real puzzler...

This topic is 3590 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I try not to use this site just for debugging help, but this is one of those times I'm well and truly stumped. Take a look at this compiler output (this is VS 2005 Express):
1>Compiling...
1>ScreenRepository.cpp
1>c:\documents and settings\...\source\humangameview.h(47) : error C2065: 'ScreenRepository' : undeclared identifier
1>HumanGameView.cpp
1>c:\documents and settings\...\source\logiclayer.h(31) : error C2065: 'HumanGameView' : undeclared identifier


Short version: There's absolutely no way those identifiers should be undeclared in the files it complains about. They've been there and working for a long time. Longer version: These suddenly started appearing while I was working in other parts of the program that don't interact with these classes. When it compiles the .cpp file for the class ScreenRepository, it says there's an error in HumanGameView.h. Here's the thing: HumanGameView.h correctly includes ScreenRepository.h, and it's been using the class fine for ages! ScreenRepository.h doesn't include HumanGameView.h, so why does the error crop up when it's ScreenRepository.cpp being compiled? Same for LogicLayer and HumanGameView. Can anyone shed some light on what's going on? [Edited by - Sol Blue on February 11, 2008 12:50:26 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Sol Blue
ScreenRepository.h doesn't include HumanGameView.h, so why does the error crop up when it's ScreenRepository.cpp being compiled? Same for LogicLayer and HumanGameView.
They probably include something that DOES include it. What do they include?

Share this post


Link to post
Share on other sites
Please tell us what you've tried (such as a rebuild all?) so we don't suggest things you've already tried.
Then, please post some code or at least give a through description of what files include what other files and where things are defined etc.
Don't worry, there should be a simple explanation[smile].

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
Don't worry, there should be a simple explanation[smile].


Eheh, I hope so. ^^

Cleaning and rebuilding haven't helped.

Is it probably a problem with #includes? I'm pretty sure I don't have any cyclic dependencies; I've solved those before.

There's way too much code to show, unfortunately. I can give parts of the mentioned .h files, though:


// ScreenRepository.h

// This file only has a few includes. None of them include this file or
// HumanGameView.h.
#include "D3DUtil.h"
#include "ResourceManager.h"
#include "Screen.h"




// HumanGameView.h

// This file is the only one that includes ScreenRepository.h.
// None of the included files below include this file.
#include "ScreenRepository.h"
#include "Globals.h"
#include "Subsystem.h"
#include "Process.h"
#include "ResourceManager.h"
#include "ProcessManager.h"
#include "DevConsole.h"
#include "Aspect.h"
#include "KeyboardInterpreter.h"
#include "Screen.h"
#include "EvKeyDown.h"
#include "EvKeyUp.h"
#include "EvChar.h"
#include "EvMouseDown.h"
#include "EvMouseUp.h"
#include "EvSceneBegins.h"

class HumanGameView : public Subsystem, public Process
{
...
// This is the offending line for the first error in the OP.
shared_ptr<ScreenRepository> mScreenRepository;
...
};




// LogicLayer.h

// None of these files include HumanGameView.h. The only one that
// includes ScreenRepository.h is HumanGameView.h, above.
#include "Subsystem.h"
#include "ProcessManager.h"
#include "ResourceManager.h"
#include "HumanGameView.h"
#include "EntityManager.h"
#include "PhysicsSystem.h"
#include "SceneMainMenu.h"
#include "InitOptions.h"
#include "EvTick.h"

class LogicLayer : public Subsystem
{
...
// This line causes the second error.
shared_ptr<HumanGameView> mHumanGameView;
...
};



A mess, I know! Thanks for the responses and kind words. :)

Share this post


Link to post
Share on other sites
Problem solving technique 1: run the offending source file through the preprocessor (for MSVC you can use the /P switch). Search the resulting file for the first usage of "HumanGameView" and "ScreenRepository". See what they are.

Problem solving technique 2: make a copy of your project (source control helps). Delete lines from your source code and compile every so often. Once the error stops occuring, then it's probable that something you just deleted contributes to the problem. Examine those lines. If you can determine the problem just from that, then everything is golden. If not, start deleting other lines until you can't delete anything without either figuring out the problem or removing the problem. If you've deleted everything you could without figuring out the problem, then post the resulting code here. That should be a minimal but complete example of the issue.

Share this post


Link to post
Share on other sites
You're being reluctant to post the relevant code, so it's very hard to guess. By omitting the things that *you* think are irrelevant, your probably omitting the code that is the cause of the problem.

So my complete-and-utter guess is that you have left header-guards unchanged when copying/pasting code in to a new header file.

[Edited by - the_edd on February 9, 2008 8:07:39 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Problem solving technique 1: run the offending source file through the preprocessor (for MSVC you can use the /P switch). Search the resulting file for the first usage of "HumanGameView" and "ScreenRepository". See what they are.


It creates a bunch of different files, one for each translation unit. Is that what you mean? What would count as the first usage?

Quote:
Original post by SiCrane
Problem solving technique 2: make a copy of your project (source control helps). Delete lines from your source code and compile every so often....


I might have to do this eventually. :/ There's thousands of lines of code, though; I was hoping there was some category of problem that creates exactly this error pattern.

Quote:
Original post by yaustar
Have you tried just compiling those single source files rather then the whole build?


Yeah, same problem, but thanks for the response.

Quote:
Original post by Antheus
Are you using namespaces? Do you use "using ..." somewhere?


The only using's I have are for std and boost -- none of my own. Could that cause a problem like this?

Quote:
Original post by the_edd
You're being reluctant to post the relevant code, so it's very hard to guess. By omitting the things that *you* think are irrelevant, your probably omitting the code that is the cause of the problem.


Sorry -- I'll post some code! I have dozens of classes though. I'll post the ones that were being changed sometime before the problem cropped up.


// HumanGameView.cpp

#include "HumanGameView.h"

HumanGameView::HumanGameView(int clientWidth, int clientHeight) : Process(),
mClientWidth(clientWidth), mClientHeight(clientHeight), TOGGLE_DC_CHAR('~')
{
HR(D3DXCreateSprite(gDevice, &mSprite));

//mDevConsole.reset(new DevConsole(mSprite));
mScreenRepository.reset(new ScreenRepository(mSprite, mClientWidth, mClientHeight));
}

HumanGameView::~HumanGameView()
{
RELEASECOM(mSprite);
}

bool HumanGameView::init()
{
std::vector<int> desiredEvents;
desiredEvents.push_back(EV_DEVICE_LOST);
desiredEvents.push_back(EV_DEVICE_RESET);
desiredEvents.push_back(EV_RENDER);
desiredEvents.push_back(EV_KEY_DOWN);
desiredEvents.push_back(EV_KEY_UP);
desiredEvents.push_back(EV_CHAR);
desiredEvents.push_back(EV_MOUSE_DOWN);
desiredEvents.push_back(EV_MOUSE_UP);
desiredEvents.push_back(EV_SCENE_BEGINS);
registerForEvents(desiredEvents);

// Create our ProcessManager.
mProcessMan.reset(new ProcessManager());

// Create our KeyboardInterpreter and add it to the ProcessManager.
shared_ptr<KeyboardInterpreter> keyboardInterpreter(new KeyboardInterpreter());
if (!keyboardInterpreter->init())
return false;

mProcessMan->addProcess(keyboardInterpreter);

return true;
}

bool HumanGameView::update(float dt)
{
mProcessMan->updateProcesses(dt);
return false;
}

// Return value indicates whether the event was consumed and should cease to be propagated by the
// event manager.
bool HumanGameView::handleEvent(shared_ptr<Event> event)
{
switch (event->getType())
{
case EV_CHAR:
{
shared_ptr<EvChar> evChar = dynamic_pointer_cast<EvChar>(event);
TCHAR ch = (TCHAR)evChar->getWParam();

// this is correct, uncomment when methods are implemented
/*if (ch == TOGGLE_DC_CHAR)
mDevConsole->toggleVisible();
else
mDevConsole->acceptCharacter(ch);*/


return true;
}

case EV_MOUSE_DOWN:
{
shared_ptr<EvMouseDown> mouseDown = dynamic_pointer_cast<EvMouseDown>(event);
POINT screenCoords = mouseDown->getCoords();

mCurScreen->checkMouseDown(mouseDown->getMouseButton(), screenCoords);

return true;
}

case EV_MOUSE_UP:
{
shared_ptr<EvMouseUp> mouseUp = dynamic_pointer_cast<EvMouseUp>(event);
POINT screenCoords = mouseUp->getCoords();

mCurScreen->checkMouseUp(mouseUp->getMouseButton(), screenCoords);

return true;
}

case EV_SCENE_BEGINS:
{
shared_ptr<EvSceneBegins> sceneBegins = dynamic_pointer_cast<EvSceneBegins>(event);
handleEvSceneBegins(sceneBegins->getSceneType());
}

default:
return false;
}
}

// Return value indicates whether the event was consumed and should cease to be propagated by the
// event manager.
bool HumanGameView::handleEvent(int eventType)
{
switch (eventType)
{
case EV_RENDER:
render();
return true;

case EV_DEVICE_LOST:
// Fonts and anything in D3DPOOL_DEFAULT must have OnLostDevice and OnResetDevice called.

// This debug message didn't trigger in windowed mode. Next time fullscreen is run, these
// events should be checked to make sure the HGV is indeed getting them.
//MessageBox(0, _T("HGV says device was lost"), 0, MB_OK);
mSprite->OnLostDevice();
return false;

case EV_DEVICE_RESET:
//MessageBox(0, _T("HGV says device was reset"), 0, MB_OK);
mSprite->OnResetDevice();
return false;

default:
return false;
}
}

bool HumanGameView::handleEvSceneBegins(int sceneType)
{
switch (sceneType)
{
case SCENE_MAIN_MENU:
//temp!
//mCurScreen = mScreenRepository->getMainMenuScreen();
mCurScreen = mScreenRepository->getTestScreen();
break;
}

return false;
}

void HumanGameView::render()
{
// Clear the back buffer and depth buffer, and send the start signals.
HR(gDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 0, 255), 1.0f, 0));
HR(gDevice->BeginScene());
HR(mSprite->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_DEPTH_BACKTOFRONT));
HR(gDevice->SetRenderState(D3DRS_ALPHATESTENABLE, true));

// Draw everything that needs to be drawn.
mCurScreen->draw(0, 0);

// The DevConsole, because of its backdoor nature, is always drawn.
//mDevConsole->draw();

// End the scene.
HR(gDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false));
HR(mSprite->End()); // Sprites are flushed here
HR(gDevice->EndScene());

// Present the back buffer.
HR(gDevice->Present(0, 0, 0, 0));
}




// HumanGameView.h

#ifndef HUMANGAMEVIEW_H
#define HUMANGAMEVIEW_H

#include <map>

#include "ScreenRepository.h"
#include "Globals.h"
#include "Subsystem.h"
#include "Process.h"
#include "ResourceManager.h"
#include "ProcessManager.h"
#include "DevConsole.h"
#include "Aspect.h"
#include "KeyboardInterpreter.h"
#include "Screen.h"
#include "EvKeyDown.h"
#include "EvKeyUp.h"
#include "EvChar.h"
#include "EvMouseDown.h"
#include "EvMouseUp.h"
#include "EvSceneBegins.h"

class HumanGameView : public Subsystem, public Process
{
public:
HumanGameView(int clientWidth, int clientHeight);
~HumanGameView();

bool init();
bool update(float dt);

private:
bool handleEvent(shared_ptr<Event> event);
bool handleEvent(int eventType);

bool handleEvSceneBegins(int sceneType);

void render();

// This class is responsible for filling and deleting this naked pointer.
ID3DXSprite* mSprite;

// The character that toggles DevConsole visibility.
const TCHAR TOGGLE_DC_CHAR;;

//shared_ptr<DevConsole> mDevConsole;
shared_ptr<ScreenRepository> mScreenRepository;
shared_ptr<ProcessManager> mProcessMan;

// The screen that is currently active and being displayed.
shared_ptr<Screen> mCurScreen;

// Passed down from AppLayer through LogicLayer.
int mClientWidth, mClientHeight;
};

#endif

Share this post


Link to post
Share on other sites

// ResourceManager.cpp

#include "ResourceManager.h"

shared_ptr<ResourceManager> gResourceManager;

ResourceManager::ResourceManager()
{
// This isn't strictly necessary, but it can theoretically improve performance. Since the LAST
// enum is the maximum number of slots these vectors will ever need, they will never
// dynamically resize themselves after construction.
mTextures.resize(TEX_LAST, 0);
mVCMs.resize(VCM_LAST);
}

ResourceManager::~ResourceManager()
{
// We are responsible for manual deletion of all the textures we've loaded.
std::vector<IDirect3DTexture9*>::iterator tex;
for (tex = mTextures.begin(); tex != mTextures.end(); ++tex)
RELEASECOM((*tex));
}

bool ResourceManager::init()
{
// This method does not really need to be here, since it can't fail, but it goes here for
// consistency.
loadAllTextures();

if (!loadAllVCMs())
return false;

return true;
}

void ResourceManager::loadAllTextures()
{
for (int i = 0; i < TEX_LAST; ++i)
loadTexture(i);
}

// If the VCM definition file does not exist or contains incorrect data, loadVCM() can fail,
// so this method has a bool return value which indicates success.
bool ResourceManager::loadAllVCMs()
{
for (int i = 0; i < VCM_LAST; ++i)
if (!loadVCM(i))
return false;

return true;
}

// Loads the texture specified by id into the appropriate slot in mTextures.
void ResourceManager::loadTexture(int textureType)
{
// Return out if the requested texture is already loaded.
if (mTextures[textureType] != 0)
return;

LPCTSTR fileName = getTextureFileName(textureType);
HR(D3DXCreateTextureFromFile(gDevice, fileName, &(mTextures[textureType])));
}

void ResourceManager::removeTexture(int textureType)
{
if (mTextures[textureType] != 0)
{
mTextures[textureType]->Release();
mTextures[textureType] = 0;
}
}

//i was here
// just wrote the ResourceManager side of VCM requesting. still need to modify KeyboardInterpreter.

// hasn't been tested yet!
// Return value indicates success.
bool ResourceManager::loadVCM(int vcmType)
{
// Return out if the requested VCM is already loaded.
if (mVCMs[vcmType] != 0)
return true;

// If we are being asked to load the empty VCM, we don't want to look in a file; we just
// create a VCM with the default constructor and put it in its slot.
if (vcmType == VCM_EMPTY)
{
shared_ptr<VirtualControlMap> emptyControls(new VirtualControlMap());
mVCMs[vcmType] = emptyControls;
return true;
}

IniReader reader;

/* We might want this, but the merge version doesn't have the necessary stuff in AppLayer yet.
File name hardcoded temporarily to get rid of errors.
// Build the full path of the file that contains the control map descriptions.
TSTRING path = gAppLayer->getProgramFilesPath();
path.append(DATA_SUBPATH);
path.append(CONTROL_MAPS_FILE_NAME);
TCHAR name[MAX_PATH] = _T("");
StringCchCat(name, MAX_PATH, path.c_str());

if (!reader.load(name))
return false;*/


if (!reader.load("Control Maps.ini"))
return false;

// Find what section of the ini file we need to look at. The section is the number of the
// VCM enum code. So, for example, the section "0" will contain the keycode-event associations
// for the first item in enum VCMType.
bool sectionExists = reader.setActiveSection(itos(vcmType));
if (!sectionExists)
return false;

shared_ptr<VirtualControlMap> controls(new VirtualControlMap());

int size = reader.getNumberOfLines();

for (int i = 0; i < size; ++i)
{
valret<STRINGPAIR> vrPair = reader.getLine(i);

// This error condition should never be met, because IniReader::getLine() does bounds checking.
if (!vrPair.valid)
return false;

STRINGPAIR line = vrPair.content;

// Get the WPARAM representing the VK code, which is the first part of the pair.
valret<int> vrWParam = stoi(line.first);

if (!vrWParam.valid)
{
// Warn of invalid WPARAM in Control Maps.ini.
errorBox(14);
return false;
}

WPARAM vkCode = (WPARAM)vrWParam.content;

// Get the event code (here, pair::second) that is to correspond with the WPARAM VK code.
valret<int> vrInt = stoi(line.second);

if (!vrInt.valid)
{
// Warn of invalid int in Control Maps.ini.
errorBox(15);
return false;
}

int eventCode = vrInt.content;

controls->associate(vkCode, eventCode);
}

mVCMs[vcmType] = controls;
return true;
}

void ResourceManager::removeVCM(int vcmType)
{
}

IDirect3DTexture9* ResourceManager::getTexture(int textureType)
{
if (mTextures[textureType] != 0)
return mTextures[textureType];
else
{
// Warn that a texture was requested that has not been loaded, but go ahead and load it now.
// This message should never be displayed to the player, which means that if it comes up during
// development, we need to find out why we hadn't loaded it yet.
errorBox(17);
loadTexture(textureType);
return mTextures[textureType];
}
}

shared_ptr<VirtualControlMap> ResourceManager::getVCM(int vcmType)
{
if (mVCMs[vcmType] != 0)
return mVCMs[vcmType];
else
{
// Warn that a VCM was requested that has not been loaded, but go ahead and load it now.
// This message should never be displayed to the player, which means that if it comes up during
// development, we need to find out why we hadn't loaded it yet.
errorBox(17);
loadVCM(vcmType);
return mVCMs[vcmType];
}
}

// A temporary method that returns a hardcoded file name for the given texture. Ideally, instead
// of calling this method, a call would be made into gStringManager. As it stands, the contents of this
// method will change from game to game, as different textures will be used.
LPCTSTR ResourceManager::getTextureFileName(int textureType)
{
switch (textureType)
{
case TEX_MAIN_MENU_BKGD_800:
return _T("main menu background 800.bmp");

case TEX_MAIN_MENU_BKGD_1024:
return _T("main menu background 1024.bmp");

case TEX_DC_FIELD_BKGD:
return _T("dev console field background.bmp");

case TEX_BTN_UP_MM_NEW_GAME:
case TEX_BTN_DOWN_MM_NEW_GAME:
case TEX_BTN_UP_MM_EXIT:
case TEX_BTN_DOWN_MM_EXIT:
case TEX_BTN_UP_MM_LOAD_GAME:
case TEX_BTN_DOWN_MM_LOAD_GAME:

case TEX_TEST_BUTTON:
return _T("test button.bmp");

case TEX_LAST:
errorBox(16);
// Falls through.

case TEX_ERROR:
default:
return _T("error.bmp");
}
}




// ResourceManager.h

// Responsible for loading and cleaning up resources like textures and audio
// files. Other parts of the program should never do any of this themselves.

// Theoretically, the load...()/remove...() methods could be used to control
// which resources are in memory at any given time, reducing memory usage.
// However, as this is a bit more complicated, at the moment the init() method
// calls all the loadAll...() methods.

#ifndef RESOURCEMANAGER_H
#define RESOURCEMANAGER_H

#include "AppLayer.h" // For getProgramFilesPath().
#include "D3DUtil.h"
#include "Globals.h" // For file paths.
#include "VirtualControlMap.h"
#include "IniReader.h"

enum TextureType {TEX_ERROR,
TEX_MAIN_MENU_BKGD_800,
TEX_MAIN_MENU_BKGD_1024,
TEX_BTN_UP_MM_NEW_GAME,
TEX_BTN_DOWN_MM_NEW_GAME,
TEX_BTN_UP_MM_EXIT,
TEX_BTN_DOWN_MM_EXIT,
TEX_BTN_UP_MM_LOAD_GAME,
TEX_BTN_DOWN_MM_LOAD_GAME,
TEX_TEST_BUTTON,
TEX_DC_FIELD_BKGD, //unused
TEX_DC_DISPLAY_FIELD_BORDER, //unused
TEX_DC_ENTRY_FIELD_BORDER, //unused
TEX_LAST};

enum VCMType {VCM_EMPTY, // Has no key associations.
VCM_TEST, // test only
VCM_LAST};

class ResourceManager
{
public:
ResourceManager();
~ResourceManager();

// Return value indicates success.
bool init();

void loadAllTextures();
bool loadAllVCMs();

void loadTexture(int textureType);
void removeTexture(int textureType);

// loadVCM() uses an IniReader, which can fail, so it has a bool RV
// which indicates success.
bool loadVCM(int vcmType);
void removeVCM(int vcmType);

IDirect3DTexture9* getTexture(int textureType);
shared_ptr<VirtualControlMap> getVCM(int vcmType);

private:
// Helper method to loadTexture(). Possibly temp, check .cpp comments.
LPCTSTR getTextureFileName(int textureType);

// Texture with enum X is found in mTextures[X]. If mTextures[X] == 0,
// that texture has not been loaded, or it was loaded and removed.
std::vector<IDirect3DTexture9*> mTextures;

// VCM with enum X is found in mVCMs[X]. If mVCMs[X] == 0, that texture
// has not been loaded.
std::vector< shared_ptr<VirtualControlMap> > mVCMs;
};

// If this declaration were in Globals.h, that file would have to include
// this one, but this one includes Globals.h.
extern shared_ptr<ResourceManager> gResourceManager;

#endif




// Globals.cpp

#include "Globals.h"

boost::shared_ptr<StringManager> gStringManager;
boost::shared_ptr<EventManager> gEventManager;

IDirect3D9* gD3D = 0;
IDirect3DDevice9* gDevice = 0;
ID3DXFont* gDevConsoleFont = 0;

const TCHAR* APP_TITLE = _T("Project Zero");
const TCHAR* APP_VERSION = _T("Pre-Alpha");

bool gAppInitSucceeded = false;


void errorBox(TSTRING message)
{
if (gStringManager)
MessageBox(0, message.c_str(), gStringManager->get(0).c_str(), MB_OK);
else
MessageBox(0, message.c_str(), _T("Error (w/o string cache)"), MB_OK);
}

void errorBox(int stringManagerIndex)
{
if (gStringManager)
{
TSTRING message = gStringManager->get(stringManagerIndex);
MessageBox(0, message.c_str(), gStringManager->get(0).c_str(), MB_OK);
}
else
MessageBox(0, _T("Error (w/o string cache)"), _T("Error (w/o string cache)"), MB_OK);
}




// Globals.h

#ifndef GLOBALS_H
#define GLOBALS_H

#include <boost/shared_ptr.hpp>

#include "StringManager.h"
#include "EventManager.h"

// Subsystems --------------------------------------------------------

// In addition to the game components declared here, there are gAppLayer,
// gLogicLayer, and gResourceManager, declared in their respective .h files.

extern boost::shared_ptr<StringManager> gStringManager;
extern boost::shared_ptr<EventManager> gEventManager;

// Enums -------------------------------------------------------------

// Some enums need to be seen by classes that, if .h files were traded,
// would have cyclic dependencies.

enum SceneType {SCENE_MAIN_MENU,
SCENE_LOADING_SCREEN}; // example, yet to be used!

// Constants ---------------------------------------------------------

extern const TCHAR* APP_TITLE;
extern const TCHAR* APP_VERSION;

const float ZLAYER_BACKGROUND = 1.0f;
const float ZLAYER_DEV_CONSOLE = 0.0f;

// Nothing can actually be drawn to this z position.
const float ZLAYER_BELOW_ALL = 1.1f;

// Data --------------------------------------------------------------

// These COM objects are managed by AppLayer.
extern IDirect3D9* gD3D;
extern IDirect3DDevice9* gDevice;
extern ID3DXFont* gDevConsoleFont;

// This is defined by AppLayer::getUserAppDataPath().
extern const TCHAR* gUserAppDataPath;

// This is defined by AppLayer::getProgramFilesPath().
extern const TCHAR* gProgramFilesPath;

// Has AppLayer::init() finished and returned true?
extern bool gAppInitSucceeded;

// Functions ---------------------------------------------------------

// This should really be in the util file, but that doesn't know
// about gStringManager, which is used inside the function.
void errorBox(TSTRING message);
void errorBox(int stringManagerIndex);

#endif

Share this post


Link to post
Share on other sites
Here's the LogicLayer stuff, which I don't think I had changed in a while, but are somehow involved in the problem.


// LogicLayer.cpp

#include "LogicLayer.h"

shared_ptr<LogicLayer> gLogicLayer;

LogicLayer::LogicLayer(shared_ptr<InitOptions> initOptions) : mInitOptions(initOptions)
{
}

// Returns false if there was a problem with anything.
bool LogicLayer::init()
{
// Ask for the events we want.
std::vector<int> desiredEvents;
desiredEvents.push_back(EV_TICK);
registerForEvents(desiredEvents);

// Create the global ResourceManager.
gResourceManager.reset(new ResourceManager());
if (!gResourceManager->init())
return false;

// Create our ProcessManager.
mProcessMan.reset(new ProcessManager());

// Create the HumanGameView and add it to our ProcessManager.
mHumanGameView.reset(new HumanGameView(mInitOptions->clientWidth, mInitOptions->clientHeight));
if (!mHumanGameView->init())
return false;
mProcessMan->addProcess(mHumanGameView);

// Create and add the EntityManager.
mEntityMan.reset(new EntityManager());
// if Em needs init, it goes here
mProcessMan->addProcess(mEntityMan);

// Create and add the PhysicsSystem.
mPhysics.reset(new PhysicsSystem());
if (!mPhysics->init())
return false;
mProcessMan->addProcess(mPhysics);

mCurScene.reset(new SceneMainMenu());
mCurScene->begin();

return true;
}

bool LogicLayer::handleEvent(shared_ptr<Event> event)
{
switch (event->getType())
{
case EV_TICK:
{
shared_ptr<EvTick> tick = dynamic_pointer_cast<EvTick>(event);
update(tick->getDT());
return false;
}

default:
return false;
}
}

bool LogicLayer::handleEvent(int eventType)
{
return false;
}

void LogicLayer::update(float dt)
{
mProcessMan->updateProcesses(dt);
}




// LogicLayer.h

// The logic layer contains the heart of the game.

#ifndef LOGICLAYER_H
#define LOGICLAYER_H

#include "HumanGameView.h"
#include "Subsystem.h"
#include "ProcessManager.h"
#include "ResourceManager.h"
#include "EntityManager.h"
#include "PhysicsSystem.h"
#include "SceneMainMenu.h"
#include "InitOptions.h"
#include "EvTick.h"

class LogicLayer : public Subsystem
{
public:
LogicLayer(shared_ptr<InitOptions> initOptions);

bool init();

private:
bool handleEvent(shared_ptr<Event> event);
bool handleEvent(int eventType);

void update(float dt);

shared_ptr<ProcessManager> mProcessMan;
shared_ptr<HumanGameView> mHumanGameView;
shared_ptr<EntityManager> mEntityMan;
shared_ptr<PhysicsSystem> mPhysics;

shared_ptr<Scene> mCurScene;
shared_ptr<InitOptions> mInitOptions;
};

// If this declaration were in Globals.h, that file would have to include
// this one, but this one includes Globals.h.
extern shared_ptr<LogicLayer> gLogicLayer;

#endif

Share this post


Link to post
Share on other sites
Quote:
Original post by Sol Blue
Quote:
Original post by SiCrane
Problem solving technique 1: run the offending source file through the preprocessor (for MSVC you can use the /P switch). Search the resulting file for the first usage of "HumanGameView" and "ScreenRepository". See what they are.


It creates a bunch of different files, one for each translation unit. Is that what you mean? What would count as the first usage?


Take a look at the .i file generated for one the files that you're having this problem with. Use Ctrl-F or whatever search functionality your favorite text editor has. Enter "HumanGameView" or "ScreenRepository". Hit enter once or the ok button. See what gets highlighted.

Share this post


Link to post
Share on other sites
FIXED! I had introduced a really complicated cyclic dependency. SiCrane, thanks so much for your advice and patience. Looking in the preprocessor files was how I found the cycle.

Thanks to everyone else who helped. I rated you all up, for what it's worth from a 1000. :)

Quote:
Original post by the_edd
In humagameview.h you have:

const TCHAR TOGGLE_DC_CHAR;; // double semi-colon

It comes right before your first error, so is somewhat suspicious.


Thanks, I fixed it!

Quote:
Original post by smitty1276
Why are you including so many headers in your class definition file? It looks like you are including a ton of things that aren't used in the header...


They're the .h files for everything the .cpp needs. Is putting them there not the usual practice?

[Edited by - Sol Blue on February 11, 2008 1:49:23 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Sol Blue
They're the .h files for everything the .cpp needs. Is putting them there not the usual practice?
Not in the header. The header should only #include things it absolutely needs the full class definition of; for instance base classes and classes it has as member variables. For everything else, like parameters to functions, and member variables that are pointers or references, forward declarations are better (E.g. class SomethingOrOther;). You can then #include the relevant file in the .cpp file.

If you include a header in a header, you're running the risk of generating a cyclic dependancy. I don't know if boost needs the full class declaration to instance a shared_ptr, but my guess it doesn't - which would let you cut down on a lot of those #includes.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by Sol Blue
They're the .h files for everything the .cpp needs. Is putting them there not the usual practice?
Not in the header. The header should only #include things it absolutely needs the full class definition of; for instance base classes and classes it has as member variables. For everything else, like parameters to functions, and member variables that are pointers or references, forward declarations are better (E.g. class SomethingOrOther;). You can then #include the relevant file in the .cpp file.

If you include a header in a header, you're running the risk of generating a cyclic dependancy. I don't know if boost needs the full class declaration to instance a shared_ptr, but my guess it doesn't - which would let you cut down on a lot of those #includes.


Ooooh. That makes sense. Thanks! I guess I have another refactoring to do. ^^

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
Quote:
Original post by Sol Blue
They're the .h files for everything the .cpp needs. Is putting them there not the usual practice?
Not in the header. The header should only #include things it absolutely needs the full class definition of; for instance base classes and classes it has as member variables. For everything else, like parameters to functions, and member variables that are pointers or references, forward declarations are better (E.g. class SomethingOrOther;). You can then #include the relevant file in the .cpp file.


It is common to get around this by making separate, stripped-down versions of header files with only forward declarations of classes: see, for example, <iosfwd> in the standard library. This lets you do


#ifndef FOOBARFWD_H
#define FOOBARFWD_H
class Foo;
class Bar;
#endif





#ifndef FOOBAR_H
#define FOOBAR_H

class Foo {
// lots of stuff
};

class Bar {
// lots of stuff
};
#endif





#ifndef BAZ_H
#define BAZ_H
#include "foobarfwd.h"

class Baz {
// I am going to dynamically allocate copies and assume ownership...
Foo* f;
Bar* b;
// ... of things passed in via the constructor:
public:
Baz(const Foo& f, const Bar& b): f(new Foo(f)), b(new Bar(b)) {}
// lots more
};
#endif





#include "foobar.h"
#include "baz.h"

Baz myBaz(Foo(1), Bar(2));


Share this post


Link to post
Share on other sites

This topic is 3590 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this