Jump to content
  • Advertisement

gameXcore

Member
  • Content Count

    241
  • Joined

  • Last visited

Everything posted by gameXcore

  1. Hi All, I have an c# implementation of a pluggable factory similar to the C++ implementation on here in that it uses static registration objects to register types with the factory, for example: static PluggableFactory<string, ControlBase>.Maker<ButtonControl> Maker = new PluggableFactory<string, ControlBase>.Maker<ButtonControl>("Button Control"); Within the same assembly this pattern works fine, however as with the C++ implementation it falls over when you place the code within a library and attempt to reference it: the static objects don't get created! Is there method I can use of forcing these objects to create when they are within an assembly I am referencing? Thanks, Scott
  2. There is not. The C# style approach to this involves Attributes and reflection, not member creation shenanigans. [/quote] Ahh that was posted during my last post, as you have probably gathered, in depth knowledge of C# is something I don't yet possess, could you give me a quick explanation of what this would involve? My first idea is that I would attribute my classes with a tag of some kind and then write some code that checks through all the types in the assembly and adds them into the factory if they have the tag?
  3. Then yes I have got confused. The constructor of a maker will register its type with the a singleton instance of the pluggable factory, using the key passed into the constructor, the idea being that you need no explicit code to load the factory with the types, only to add the type into the project. public class Singleton<T> where T : class { static Singleton() { } public static readonly T Instance = typeof(T).InvokeMember(typeof(T).Name, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, null, null) as T; } public class PluggableFactory<TKeyType, TBase> : Singleton<Factory<TKeyType, TBase>> { public class Maker<TDerivedType> where TDerivedType : TBase { public Maker(TKeyType name) { PluggableFactory<TKeyType, TBase>.Instance.RegisterType<TDerivedType>(name); } } } public class Factory<TKeyType, TBase> { private Dictionary<TKeyType, Type> loadedTypes = new Dictionary<TKeyType, Type>(); public Dictionary<TKeyType, Type>.KeyCollection Keys { get { return loadedTypes.Keys; } } public void RegisterType<TDerived>(TKeyType name) where TDerived : TBase { if (loadedTypes.ContainsKey(name)) { Logging.Logger.LogWarning("Attempted to add duplicate item to factory. " + " Alias: " + name.ToString() + "Current Type: " + loadedTypes[name].ToString() + "New Type: " + typeof(TBase).ToString() + ". Request ignored."); } else { loadedTypes.Add(name, typeof(TDerived)); } } public TBase Create(TKeyType name, params object[] args) { return (TBase)Activator.CreateInstance(loadedTypes[name], args); } public bool TryCreate(out TBase outObj, TKeyType name, params object[] args) { try { outObj = (TBase)Activator.CreateInstance(loadedTypes[name], args); return true; } catch(Exception e) { Logging.Logger.LogError("Factory failed to create type: " + name.ToString() + ". Error Message: " + e.Message); outObj = default(TBase); return false; } } } An example: Listing 1 class Base {public void Print(){Console.WriteLine("Base");} class A : Base {public void Print(){Console.WriteLine("A");} class B : Base {public void Print(){Console.WriteLine("B");} static PluggableFactory<string, Base>.Maker<A> maker = new PluggableFactory<string, Base>.Maker<A>("A"); static PluggableFactory<string, Base>.Maker<B> maker = new PluggableFactory<string, Base>.Maker<B>("B"); Listing 2 void Func() { // Factory is already loaded with types due to the static maker objects Base a = PluggableFactory<string, Base>.Instance.Create("A"); Base b = PluggableFactory<string, Base>.Instance.Create("B"); a.Print(); b.Print(); } If listing 1 is in the same assembly as listing 2 then the output is A B if listing 1 is in a different assembly to listing 2 (ie a common library) then PluggableFactory<string, Base> contains no types and fails during the calls to Create. I hope that helped explain a little clearer. What I am after is for the constructor on the static Maker objects to be called automatically during program start up even when that static object is in a referenced library.
  4. Hi all, I am currently porting some code from C++ into C# and have come a little stuck with recreating my template factory class. I was wandering if anyone could give me any hints or pointers as to where I would start. First I'll post the C++ code, then I will post a description and use-case example. Code: FactoryTemplate.h #include <map> #include "../Utilities/Logger.h" namespace XF { namespace Utilities { #define XF_FACTORY_JOIN_MACRO( X, Y) XF_FACTORY_DO_JOIN( X, Y ) #define XF_FACTORY_DO_JOIN( X, Y ) XF_FACTORY_DO_JOIN2(X,Y) #define XF_FACTORY_DO_JOIN2( X, Y ) X##Y #define XF_FACTORY_CLASS_NAME XF_FACTORY_JOIN_MACRO(Factory, XF_FACTORY_NUM_ARGS) #define XF_FACTORY_MAKER_BASE_NAME XF_FACTORY_JOIN_MACRO(MakerBase, XF_FACTORY_NUM_ARGS) #define XF_FACTORY_MAKER_NAME XF_FACTORY_JOIN_MACRO(Maker, XF_FACTORY_NUM_ARGS) #if XF_FACTORY_NUM_ARGS > 0 #define XF_FACTORY_SEPERATOR , #else #define XF_FACTORY_SEPERATOR #endif template <typename Type, typename Key XF_FACTORY_SEPERATOR XF_FACTORY_TEMPLATE_ARGS> class XF_FACTORY_CLASS_NAME { private: template <typename Type, typename Key XF_FACTORY_SEPERATOR XF_FACTORY_TEMPLATE_ARGS> class XF_FACTORY_MAKER_BASE_NAME { public: typedef typename Type BaseType; typedef typename Key KeyType; public: XF_FACTORY_MAKER_BASE_NAME(const KeyType& k):key(k) {} const KeyType &GetKey() {return key;} virtual BaseType* Create(XF_FACTORY_ARG_PARAMS) = 0; virtual std::string GetMakeTypeName() = 0; private: KeyType key; }; template <typename BaseType, typename Make, typename Key XF_FACTORY_SEPERATOR XF_FACTORY_TEMPLATE_ARGS> class XF_FACTORY_MAKER_NAME : public XF_FACTORY_MAKER_BASE_NAME<BaseType, Key XF_FACTORY_SEPERATOR XF_FACTORY_ARGS> { public: typedef typename Make MakeType; XF_FACTORY_MAKER_NAME(const KeyType &key) : XF_FACTORY_MAKER_BASE_NAME(key) {} BaseType* Create(XF_FACTORY_ARG_PARAMS) { return new MakeType(XF_FACTORY_PARAMS); } std::string GetMakeTypeName(){return typeid(MakeType).name();} }; typedef typename XF_FACTORY_MAKER_BASE_NAME<Type, Key XF_FACTORY_SEPERATOR XF_FACTORY_TEMPLATE_ARGS> MakerBaseType; public: typedef typename Type ObjectType; typedef typename Key KeyType; XF_FACTORY_CLASS_NAME(){} ~XF_FACTORY_CLASS_NAME() { UnregisterTypes(); } template <typename CreationType> void RegisterType(const KeyType &key) { MakerCollectionIt it(makers.find(key)); if(it == makers.end()) { MakerBaseType *newMaker = new XF_FACTORY_MAKER_NAME<ObjectType, CreationType, KeyType XF_FACTORY_SEPERATOR XF_FACTORY_TEMPLATE_ARGS>(key); makers.insert(std::make_pair(key, newMaker)); LOG_INFO << "Type registered: ([" << typeid(CreationType).name() << "] - '" << key << "')"; } else { LOG_WARNING << "Attempting to register type using duplicate key ('" << key << "')" << Logging::LnBreak << " Original: [" << it->second->GetMakeTypeName() << "]" << Logging::LnBreak << " New: [" << typeid(CreationType).name() << "]" << Logging::LnBreak << " Request Ignored!"; } } void UnregisterTypes() { for(MakerCollectionIt it(makers.begin()); it != makers.end(); ++it) { delete it->second; } makers.clear(); } ObjectType* Create(const KeyType &key XF_FACTORY_SEPERATOR XF_FACTORY_ARG_PARAMS) { MakerCollectionIt it(makers.find(key)); return it == makers.end() ? NULL : it->second->Create(XF_FACTORY_PARAMS); } protected: typedef std::map<KeyType, MakerBaseType*> MakerCollection; typedef typename MakerCollection::iterator MakerCollectionIt; MakerCollection makers; }; } } #undef XF_FACTORY_JOIN_MACRO #undef XF_FACTORY_DO_JOIN #undef XF_FACTORY_DO_JOIN2 #undef XF_FACTORY_CLASS_NAME #undef XF_FACTORY_SEPERATOR #undef XF_FACTORY_MAKER_NAME #undef XF_FACTORY_MAKER_BASE_NAME Factory.h #ifndef XF_UTILITIES_FACTORY_H #define XF_UTILITIES_FACTORY_H #define XF_FACTORY_NUM_ARGS 0 #define XF_FACTORY_TEMPLATE_ARGS #define XF_FACTORY_ARGS #define XF_FACTORY_ARG_PARAMS #define XF_FACTORY_PARAMS #include "FactoryTemplate.h" #undef XF_FACTORY_NUM_ARGS #undef XF_FACTORY_ARGS #undef XF_FACTORY_TEMPLATE_ARGS #undef XF_FACTORY_ARG_PARAMS #undef XF_FACTORY_PARAMS #define XF_FACTORY_NUM_ARGS 1 #define XF_FACTORY_TEMPLATE_ARGS typename A1 #define XF_FACTORY_ARGS A1 #define XF_FACTORY_ARG_PARAMS A1 a1 #define XF_FACTORY_PARAMS a1 #include "FactoryTemplate.h" #undef XF_FACTORY_NUM_ARGS #undef XF_FACTORY_ARGS #undef XF_FACTORY_TEMPLATE_ARGS #undef XF_FACTORY_ARG_PARAMS #undef XF_FACTORY_PARAMS #define XF_FACTORY_NUM_ARGS 2 #define XF_FACTORY_TEMPLATE_ARGS typename A1, typename A2 #define XF_FACTORY_ARGS A1, A2 #define XF_FACTORY_ARG_PARAMS A1 a1, A2 a2 #define XF_FACTORY_PARAMS a1, a2 #include "FactoryTemplate.h" #undef XF_FACTORY_NUM_ARGS #undef XF_FACTORY_ARGS #undef XF_FACTORY_TEMPLATE_ARGS #undef XF_FACTORY_ARG_PARAMS #undef XF_FACTORY_PARAMS #endif The user #includes Factory.h to use the factory. The above code will generate 3 templates Factory0<ReturnType>, Factory2<ReturnType, ParamType1> and Factory2<ReturnType, ParamType1, ParamType2> which can then be used to create factory's templated to any type the user requires. Use case: class A {}; class AA : public A {} class AB : public A {} class B {B(int, float){}}; class BA : public A{BA(int, float) : B(){}}; Factory0<A> f1; Factory2<B, int, float> f2; f1.RegisterType<AA>("AA"); f1.RegisterType<AB>("AB"); f2.RegisterType<BA>("BA"); A *a1 = f1.Create("AA"); A *a2 = f1.Create("AB"); B *b1 = f2.Create("BA", 1, 2.0f); B *b2 = f2.Create("BA", 4, 7.8f); With no direct replacement for the way I use #define in the above code to generate the class names, as well as fill in the argument types/ parameters etc I'm completely stumped on what mechanisms are available. Any help or pointers would be greatly appreciated. Thanks, Scott
  5. Ahh I completely didn't spot the Activator line, I must have read it as simply creating the type, then by the looks of it that looks perfect for what I'm after. As for the performance I can use this for the game and then if it ever becomes a bottleneck I can simply replace it with a direct factory dealing with that specific type. Thanks a lot. Scott
  6. @Telastyn Indeed this is one of those areas where c# lacks when you put it against C++ and I did think it was going to be bit of an ask to find a direct replacement, this is just one of those bits of code which I realized I use a lot and it would have been nice to have it around with the familiar interface! @a_loho I also thought of that option however I was under the impression that in order to use params object[] args [font="Arial"]for the variable arguments that I would also have to have the objects take in params object[] as their sole constructor arguments, as opposed to actual types.[/font]
  7. Hi All, Since leaving uni and getting a real job I haven't been around on these board a lot, mainly due to the complete lack of programming I have done outside of the office, however recently I decided to start learning 3D programming from a technical standpoint using native Direct X (In the past I have always used wrappers, Ogre, XNA etc). I have been following a few tutorials learning the syntax and how things fit together, and have come to the topic of lighting, I quickly hacked together my first lighted demo app and amnoticing a very strange occurance that I cannot explain and was hoping a fellow board member could enlighten me as to what is happening. The program is a simple app that sets up a cube, renders it and allows the user to interact using the keyboard to translate, rotate and scale it. With the D3DRS_LIGHTING renderstate set to false the app works fine, you are able to move the cube around with no problems, (Code listing 2 below). The problem occurs when I refactor the code slightly to turn D3DRS_LIGHTING on and setup one light. The app initially works fine, the cube is correctly lit throught the user moving it, however precicely 6 seconds after the program starts a second cube "Appears" at the origin, this cube then procceeds to play back the motions of the original cube precicely 6 seconds after they happened, mirroring all movements, scaling changes and rotations. Now barring that I may have accidently stubled upon AI which is currently playing tricks with me and may soon take over the world, I am failing to remove/add bits of code to track down what exactly is causing this strange occurance. Thanks a lot for any help, Scott Code listings for D3D9 setup [1], the program with no lighting[2] and the program with lighting and strange behaviour[3] follow, aswell as my typedefs for a few of D3D's types: #include "DeviceManager.h" #include "ApplicationDisplay.h" namespace XF { namespace GFX { DeviceManager::DeviceManager() { d3d = NULL; d3dDevice = NULL; } bool DeviceManager::Init(HWND hWnd, ApplicationDisplay &appDisp) { d3d = Direct3DCreate9(D3D_SDK_VERSION); if(!d3d) return false; ZeroMemory(&d3dPP, sizeof(d3dPP)); d3dPP.Windowed = !appDisp.Fullscreen(); d3dPP.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dPP.hDeviceWindow = hWnd; d3dPP.BackBufferFormat = D3DFMT_X8R8G8B8; d3dPP.BackBufferWidth = appDisp.WindowWidth(); d3dPP.BackBufferHeight = appDisp.WindowHeight(); d3dPP.EnableAutoDepthStencil = TRUE; d3dPP.AutoDepthStencilFormat = D3DFMT_D16; if(FAILED(d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dPP, &d3dDevice))) { return false; } d3dDevice->SetRenderState(D3DRS_ZENABLE, true); return true; } void DeviceManager::Destroy() { d3dDevice->Release(); d3d->Release(); } void DeviceManager::BeginFrame() { d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3dDevice->BeginScene(); } void DeviceManager::EndFrame() { d3dDevice->EndScene(); d3dDevice->Present(NULL, NULL, NULL, NULL); } } } #include "TestGameScreen.h" #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE) struct CustomVertex { float x, y, z; DWORD diffuse; }; bool TestGameScreen::OnInit() { CustomVertex vertices[] = { { -1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 0, 255), }, { 1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB(0, 255, 0), }, { -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(255, 0, 0), }, { 1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB(0, 255, 255), }, { -1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 255), }, { 1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB(255, 0, 0), }, { -1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 0), }, { 1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB(0, 255, 255), }, }; short indices[] = { 0, 1, 2, // side 1 2, 1, 3, 4, 0, 6, // side 2 6, 0, 2, 7, 5, 6, // side 3 6, 5, 4, 3, 1, 7, // side 4 7, 1, 5, 4, 5, 0, // side 5 0, 5, 1, 3, 7, 2, // side 6 2, 7, 6, }; app->device.GetDevice()->CreateVertexBuffer( 24 * sizeof(CustomVertex), 0, CUSTOMFVF, D3DPOOL_MANAGED, &vBuffer, NULL); app->device.GetDevice()->CreateIndexBuffer( 36 * sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &iBuffer, NULL); void* voidPtr; vBuffer->Lock(0, 0, (void**)&voidPtr, 0); memcpy(voidPtr, vertices, sizeof(vertices)); vBuffer->Unlock(); iBuffer->Lock(0, 0, (void**)&voidPtr, 0); memcpy(voidPtr, indices, sizeof(indices)); iBuffer->Unlock(); D3DXMatrixLookAtLH( &viewMatrix, &XF::GFX::Vector3(0.0f, 0.0f, 10.0f), &XF::GFX::Vector3Zero, &XF::GFX::Vector3Up); D3DXMatrixPerspectiveFovLH( &projMatrix, D3DXToRadian(45), (float)app->device.GetPresentationParameters().BackBufferWidth / (float)app->device.GetPresentationParameters().BackBufferHeight, 1.0f, 100.0f); position = XF::GFX::Vector3Zero; rotation = XF::GFX::Vector3Zero; scale = XF::GFX::Vector3One; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); light.Direction = XF::GFX::Vector3(-1.0f, -0.3f, -1.0f); app->device.GetDevice()->SetLight(0, &light); app->device.GetDevice()->LightEnable(0, false); ZeroMemory(&material, sizeof(XF::GFX::D3DMaterial)); material.Diffuse = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); app->device.GetDevice()->SetMaterial(&material); return true; } void TestGameScreen::OnUpdate(float dT) { if(app->input.KeyDown(XF::Keys::Q)) { scale.x -= 1.0f * dT; scale.y -= 1.0f * dT; scale.z -= 1.0f * dT; } if(app->input.KeyDown(XF::Keys::R)) { scale.x += 1.0f * dT; scale.y += 1.0f * dT; scale.z += 1.0f * dT; } if(app->input.KeyDown(XF::Keys::Up)) position.y += 0.5f * dT; if(app->input.KeyDown(XF::Keys::Down)) position.y -= 0.5f * dT; if(app->input.KeyDown(XF::Keys::Left)) position.x += 0.5f * dT; if(app->input.KeyDown(XF::Keys::Right)) position.x -= 0.5f * dT; if(app->input.KeyDown(XF::Keys::W)) rotation.z -= 0.5f * dT; if(app->input.KeyDown(XF::Keys::E)) rotation.z += 0.5f * dT; if(app->input.KeyDown(XF::Keys::S)) rotation.y -= 0.5f * dT; if(app->input.KeyDown(XF::Keys:)) rotation.y += 0.5f * dT; } void TestGameScreen::OnDraw() { app->device.GetDevice()->SetRenderState(D3DRS_LIGHTING, false); //app->device.GetDevice()->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50)); app->device.GetDevice()->SetFVF(CUSTOMFVF); XF::GFX::Matrix positionMatrix; D3DXMatrixTranslation(&positionMatrix, position.x, position.y, position.z); XF::GFX::Matrix rotationMatrix; D3DXMatrixRotationYawPitchRoll( &rotationMatrix, rotation.y, rotation.x, rotation.z); XF::GFX::Matrix scaleMatrix; D3DXMatrixScaling(&scaleMatrix, scale.x, scale.y, scale.z); app->device.GetDevice()->SetTransform(D3DTS_WORLD, &(rotationMatrix * scaleMatrix * positionMatrix)); app->device.GetDevice()->SetTransform(D3DTS_VIEW, &viewMatrix); app->device.GetDevice()->SetTransform(D3DTS_PROJECTION, &projMatrix); app->device.GetDevice()->SetStreamSource(0, vBuffer, 0, sizeof(CustomVertex)); app->device.GetDevice()->SetIndices(iBuffer); app->device.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12); } void TestGameScreen::OnDestroy() { vBuffer->Release(); iBuffer->Release(); } #include "TestGameScreen.h" #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL) struct CustomVertex { float x, y, z; XF::GFX::Vector3 normal; }; bool TestGameScreen::OnInit() { CustomVertex vertices[] = { { -1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), }, // side 1 { 1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), }, { -1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), }, { 1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 0.0f, 1.0f), }, { -1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), }, // side 2 { -1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), }, { 1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), }, { 1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 0.0f, -1.0f), }, { -1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), }, // side 3 { -1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), }, { 1.0f, 1.0f, -1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), }, { 1.0f, 1.0f, 1.0f, XF::GFX::Vector3(0.0f, 1.0f, 0.0f), }, { -1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), }, // side 4 { 1.0f, -1.0f, -1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), }, { -1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), }, { 1.0f, -1.0f, 1.0f, XF::GFX::Vector3(0.0f, -1.0f, 0.0f), }, { 1.0f, -1.0f, -1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), }, // side 5 { 1.0f, 1.0f, -1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), }, { 1.0f, -1.0f, 1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), }, { 1.0f, 1.0f, 1.0f, XF::GFX::Vector3(1.0f, 0.0f, 0.0f), }, { -1.0f, -1.0f, -1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), }, // side 6 { -1.0f, -1.0f, 1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), }, { -1.0f, 1.0f, -1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), }, { -1.0f, 1.0f, 1.0f, XF::GFX::Vector3(-1.0f, 0.0f, 0.0f), }, }; short indices[] = { 0, 1, 2, // side 1 2, 1, 3, 4, 5, 6, // side 2 6, 5, 7, 8, 9, 10, // side 3 10, 9, 11, 12, 13, 14, // side 4 14, 13, 15, 16, 17, 18, // side 5 18, 17, 19, 20, 21, 22, // side 6 22, 21, 23, }; app->device.GetDevice()->CreateVertexBuffer( 24 * sizeof(CustomVertex), 0, CUSTOMFVF, D3DPOOL_MANAGED, &vBuffer, NULL); app->device.GetDevice()->CreateIndexBuffer( 36 * sizeof(short), 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &iBuffer, NULL); void* voidPtr; vBuffer->Lock(0, 0, (void**)&voidPtr, 0); memcpy(voidPtr, vertices, sizeof(vertices)); vBuffer->Unlock(); iBuffer->Lock(0, 0, (void**)&voidPtr, 0); memcpy(voidPtr, indices, sizeof(indices)); iBuffer->Unlock(); D3DXMatrixLookAtLH( &viewMatrix, &XF::GFX::Vector3(0.0f, 0.0f, 10.0f), &XF::GFX::Vector3Zero, &XF::GFX::Vector3Up); D3DXMatrixPerspectiveFovLH( &projMatrix, D3DXToRadian(45), (float)app->device.GetPresentationParameters().BackBufferWidth / (float)app->device.GetPresentationParameters().BackBufferHeight, 1.0f, 100.0f); position = XF::GFX::Vector3Zero; rotation = XF::GFX::Vector3Zero; scale = XF::GFX::Vector3One; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); light.Direction = XF::GFX::Vector3(-1.0f, -0.3f, -1.0f); app->device.GetDevice()->SetLight(0, &light); app->device.GetDevice()->LightEnable(0, true); ZeroMemory(&material, sizeof(XF::GFX::D3DMaterial)); material.Diffuse = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); app->device.GetDevice()->SetMaterial(&material); return true; } void TestGameScreen::OnUpdate(float dT) { if(app->input.KeyDown(XF::Keys::Q)) { scale.x -= 1.0f * dT; scale.y -= 1.0f * dT; scale.z -= 1.0f * dT; } if(app->input.KeyDown(XF::Keys::R)) { scale.x += 1.0f * dT; scale.y += 1.0f * dT; scale.z += 1.0f * dT; } if(app->input.KeyDown(XF::Keys::Up)) position.y += 0.5f * dT; if(app->input.KeyDown(XF::Keys::Down)) position.y -= 0.5f * dT; if(app->input.KeyDown(XF::Keys::Left)) position.x += 0.5f * dT; if(app->input.KeyDown(XF::Keys::Right)) position.x -= 0.5f * dT; if(app->input.KeyDown(XF::Keys::W)) rotation.z -= 0.5f * dT; if(app->input.KeyDown(XF::Keys::E)) rotation.z += 0.5f * dT; if(app->input.KeyDown(XF::Keys::S)) rotation.y -= 0.5f * dT; if(app->input.KeyDown(XF::Keys:)) rotation.y += 0.5f * dT; } void TestGameScreen::OnDraw() { app->device.GetDevice()->SetRenderState(D3DRS_LIGHTING, true); app->device.GetDevice()->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50)); app->device.GetDevice()->SetFVF(CUSTOMFVF); XF::GFX::Matrix positionMatrix; D3DXMatrixTranslation(&positionMatrix, position.x, position.y, position.z); XF::GFX::Matrix rotationMatrix; D3DXMatrixRotationYawPitchRoll( &rotationMatrix, rotation.y, rotation.x, rotation.z); XF::GFX::Matrix scaleMatrix; D3DXMatrixScaling(&scaleMatrix, scale.x, scale.y, scale.z); app->device.GetDevice()->SetTransform(D3DTS_WORLD, &(rotationMatrix * scaleMatrix * positionMatrix)); app->device.GetDevice()->SetTransform(D3DTS_VIEW, &viewMatrix); app->device.GetDevice()->SetTransform(D3DTS_PROJECTION, &projMatrix); app->device.GetDevice()->SetStreamSource(0, vBuffer, 0, sizeof(CustomVertex)); app->device.GetDevice()->SetIndices(iBuffer); app->device.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12); } void TestGameScreen::OnDestroy() { vBuffer->Release(); iBuffer->Release(); } #include <Windows.h> #include <d3d9.h> #include <d3dx9.h> #ifndef XF_GFX_DX9TYPEDEFSANDDEFINES_H #define XF_GFX_DX9TYPEDEFSANDDEFINES_H namespace XF { namespace GFX { typedef LPDIRECT3D9 Direct3D; typedef LPDIRECT3DDEVICE9 Direct3DDevice; typedef D3DPRESENT_PARAMETERS PresentationParameters; typedef LPDIRECT3DVERTEXBUFFER9 VertexBuffer; typedef LPDIRECT3DINDEXBUFFER9 IndexBuffer; typedef D3DXMATRIX Matrix; static const Matrix MatrixIdentity = Matrix(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); typedef D3DXVECTOR3 Vector3; static const Vector3 Vector3Zero = Vector3(0.0f, 0.0f, 0.0f); static const Vector3 Vector3One = Vector3(1.0f, 1.0f, 1.0f); static const Vector3 Vector3Up = Vector3(0.0f, 1.0f, 0.0f); static const Vector3 Vector3Down = Vector3(0.0f, -1.0f, 0.0f); static const Vector3 Vector3Left = Vector3(-1.0f, 0.0f, 0.0f); static const Vector3 Vector3Right = Vector3(1.0f, 0.0f, 0.0f); static const Vector3 Vector3In = Vector3(0.0f, 0.0f, 1.0f); static const Vector3 Vector3Out = Vector3(0.0f, 0.0f, -1.0f); typedef D3DXVECTOR2 Vector2; static const Vector2 Vector2Zero = Vector2(0.0f, 0.0f); static const Vector2 Vector2One = Vector2(1.0f, 1.0f); static const Vector2 Vector2Up = Vector2(0.0f, 1.0f); static const Vector2 Vector2Down = Vector2(0.0f, -1.0f); static const Vector2 Vector2Left = Vector2(-1.0f, 0.0f); static const Vector2 Vector2Right = Vector2(1.0f, 0.0f); typedef D3DLIGHT9 Light; typedef D3DMATERIAL9 D3DMaterial; } } #endif
  8. gameXcore

    D3D 9 Strange "Ghost" artifact

    That makes sense, a circular buffer of some sort, with the numbers being just right to give the effect, an interesting one definately!
  9. gameXcore

    D3D 9 Strange "Ghost" artifact

    Ok, So I got home from work and decided to do some investigation, drivers upto date etc. I also noticed a distinct "flicker" in the window which was occuring at regular 6 second intervals. I started prodding and poking, removing and adding trying to narrow down what was causing the problem, I then noticed that in the version using no lighting the cube wasn't displaying correctly, only the front and back sides were visible. Anyway, I narrowed that down to the drawIndexedPrimitive call being incorrect: app->device.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12); Whereas actually there are 24 verices: app->device.GetDevice()->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12); Fixing this call cause the problem to go away, what I don't understand is why it occured in the first place? Can anyone explain this? Thanks, Scott
  10. gameXcore

    D3D 9 Strange "Ghost" artifact

    Well I'm working on my laptop which at the tail end of last week had a fresh install of Windows 7, and then the 4 terrabytes of updates to everything that comes with it, including updates for the graphics drivers, I guess tomorro I could try seeing if my drivers are actually upto date. I could also try running on a different machine, I would have to get it set up tho. This is indeed bizarre.
  11. Hi all, I've just moved back to some C#/XNA work and am bolstering up my input systems. A system I am adding is the ability to register key combinations (combinations of keyboard keys, mouse buttons, gamepad buttons) with appropriate logic (and, or) and then query the input system for whether that combination is true. Here's an example, a little app makes the screen go black when: - The G AND F keys are both down at the same time OR - The frame that the left mouse button is clicked on OR - the frame that the right mouse button is release while the W key is held down To register this named event I write: [source language="c#"] input.CreateNamedInputEvent("Blackscreen", new BIEOr( new BIEAnd(new BIEDown(Keys.G), new BIEDown(Keys.F)), new BIEPressed(MouseButtons.LeftButton), new BIEAnd(new BIEDown(Keys.W), new BIEReleased(MouseButtons.RightButton)))); And then to query I simply use: [source language="c#"] if (input.QueryNamedInputEvent("Blackscreen")) clearColor = Color.Black; else clearColor = Color.CornflowerBlue; Everything works fine, I was just wandering if there is a clean and easy way to avoid the "new" keyword in order to make the combinations easier on the eye. Thanks, Scott
  12. wow, fast reply, and good, thankyou. I ruled out the parsing method because i decided that having a bullet-proof parsing method that could handle anything was going to be a mammoth task prone to error, not to mention little bugs that could arise from typing the string slightly wrong. The second method looks rather interesting tho, I'm not sure how operater overloading could be done in this way?
  13. Hey all, So this is post number 1 million regarding problems revolving around me moving my engine into a seperate library. This time my issue is with static variables not initializing. I utilize the pluggable factory pattern in a few places around my engine, using a similar implementation to the one described in the article on this site "why pluggable factorys rock my multiplayer world". Within my engine I have a standard subset of items that should be added to the factory, these are compiled within the library, I then have another set of items that are game-specific and added in the project that is using the engine. The problem I'm having is that the static makers within the library never seem to initialize, and thus never get registered with the factory. Is this expected behaviour within a library, or should I be looking for the problem elsewhere? If so, how do I go about ensuring these statics initialize? Thanks, Scott
  14. Well this is bit of a headache, luckily I'm not too worried right now about cross compiler portability, so long as it compiles on MSVC I'm happy, so the pragma option should work. The only problem is, I've never come across dumpbin before, and cannot find it, the internet says I should already have it installed. Any ideas? Thanks, Scott
  15. Hi all, I'm busy surgically removing the "Engine" from my latest projects and building it into its own reusable library which I can then host in its own SVN project etc etc and avoid having to maintain multiple copys across each project, this will also allow for me to post it in an open-source repo and anyone who is interested in trying out the component based entitys stuff I've been developing in it can. One of the problems I'm not sure how to handle is the message subject enumerations, I use a message system for communication and a message is as such: struct Message { MessageSubject::ENUM Subject; int SenderID; int ReceiverID; float SendTime; void* Data; }; And message's are defined in an enum, there is also a matching array of strings so that we can convert string - enum, or enum - string at any time, these files are generated using a tool to keep them synced. Here's the file as in its most recent form: /***********************************************************/ /* This File was Auto-generated by the Message Maker App */ /* Authors: Christopher Pepper & Scott Bevin */ /***********************************************************/ //AUTO GENERATED VERSION:176 #include <string> #pragma once #define NO_MESSAGE 999 namespace XF { namespace MessageSubject { enum ENUM { //Group:Graphics API PLEASE_SEND_RENDERER=0, // Params -: :- SENT_RENDERER, // Params -: :- //End Of Group: Graphics API //Group:Sound API ADD_MUSIC, // Params -: std::String tag, (this loads the music into memory ready to be played, paused etc it will automaticaly loop :- PLAY_MUSIC, // Params -: std::string tag of music (must be Added first :- STOP_MUSIC, // Params -: std::String tag, will remove the music from memory :- STOP_SOUND, // Params -: std::string tag (this is used for internal messageS) :- PAUSE_MUSIC, // Params -: std::string tag, will pause the music :- PLAY_SOUND_EX, // Params -: PropertyContainer (why didnt i think of this already =]) :- //this is currently for the PlaySound component to use //it can be sent a variety of properties via the PropertyContainer //currently that includes the track, the position and the length of the track, the minimum distance it can be heard from //if it doesnt have a lengthh property it will play the sound looped until the sound is destroyed by a STOP_SOUND message STOP_SOUND_EX, // Params -: :- // used for stoping sounds using a specially UID, this is all managed in playsound component and sent to the sound component UPDATE_MUSIC_TRACK_POSITION, // Params -: sound data packet :- PLAY_SOUND, // Params -: std::String :- PLAY_3D_SOUND, // Params -: SoundDataPacket struct :- SET_LISTENER_DATA, // Params -: ListenerInformation struct :- ADD_SOUND, // Params -: Use only if you want to add a sound that is not pre-loaded, SEND a std::string filepath :- //End Of Group: Sound API //Group:Particle API CREATE_PARTICLE_SYSTEM, // Params -: :- //End Of Group: Particle API //Group:Collision system SEND_ME_ENITIES_IN_RADIUS, // Params -: float :- SEND_ME_ENITIES_IN_RAY, // Params -: XF::GameEntity :- SENT_YOU_ENTITIES_IN_RAY, // Params -: std::vector<XF::GameEntity> :- SENT_YOU_ENTITIES_IN_RADUIS, // Params -: std::vector<XF::GameEntity> :- SEND_ME_DETECTION_RADIUS, // Params -: :- SENT_YOU_DETECTION_RADIUS, // Params -: float :- //End Of Group: Collision system //Group:GUI SENT_GUI, // Params -: :- PLEASE_SEND_GUI, // Params -: :- PLEASE_SEND_ME_ACTION_CAMERA, // Params -: :- SENT_YOU_ACTION_CAMERA, // Params -: Ogre::Camera* :- STOP_USING_ACTION_CAMERA, // Params -: :- ESCAPE_SCREEN, // Params -: :- //End Of Group: GUI //Group:Error Processing ERROR_MESSAGE, // Params -: std::String :- //End Of Group: Error Processing //Group:Cosole SEND_ME_DISPLAY, // Params -: :- SENT_CONSOLE_DISPLAY, // Params -: :- SHOW_PAUSE_MENU, // Params -: :- TRACK_GAME_ENTITY, // Params -: :- STOP_TRACKING_GAME_ENTITY, // Params -: :- //End Of Group: Cosole //Group:Game world -> HUD TOWER_CLICKED, // Params -: GameEntity* :- MULITPLE_TOWER_CLICKED, // Params -: std::list<GameEntity*> :- NOTHING_CLICKED, // Params -: NULL :- SET_LEFT_PANE_CAMERA, // Params -: :- //End Of Group: Game world -> HUD //Group:HUD OUT TELL_ME_COST_OF, // Params -: string (containing filepath of towerFile) :- HOW_MUCH_DO_YOU_COST_TO_UPGRADE, // Params -: :- WHAT_IS_YOUR_UPGRADE_FILE, // Params -: :- WHAT_IS_YOUR_SELL_VALUE, // Params -: :- ARE_YOU_UPGRADABLE, // Params -: :- YES_I_AM_UPGRADABLE, // Params -: :- MY_UPGRADE_FILE_IS, // Params -: std::string :- SHOW_UPGRADE, // Params -: :- SEND_ME_UPGRADE_DESCRIPTION, // Params -: :- STOP_SHOWING_UPGRADE, // Params -: :- BUILD_TOWER, // Params -: SEND string containing filepath of towerFile :- UPGRADE_TOWER, // Params -: NULL :- SELL, // Params -: NULL :- UPDATE_SELECTED, // Params -: NULL :- POINT_CAMERA_AT, // Params -: xf::vector3 :- //End Of Group: HUD OUT //Group:Entity managment COST_IS, // Params -: string (containing filepath of towerFile) :- MY_UPGRADE_COST_IS, // Params -: :- MY_SELL_VALUE_IS, // Params -: :- ATTATCH_CAMERA_TO_ENTITY, // Params -: :- ATTATCH_CAMERA_TO_RANDOM_ENTITY, // Params -: :- REMOVE_ENEMY, // Params -: GameEntity* :- SPAWN_NEXT_WAVE, // Params -: :- BUILD_SPACE_STATION, // Params -: :- //End Of Group: Entity managment //Group:Game Stuff SPACE_STATION_SELECTED, // Params -: :- ADD_PROJECTILE_TO_WORLD, // Params -: :- ADJUST_MONEY, // Params -: // int (will add to money) :- ADJUST_LIFE, // Params -: int (will add to life) :- HOW_MUCH_MONEY_IS_LEFT, // Params -: :- SENT_HOW_MUCH_MONEY_LEFT, // Params -: :- MONEY_HAS_CHANGED_TO, // Params -: :- LIFE_HAS_CHANGED_TO, // Params -: :- GAME_OVER, // Params -: bool, if true the game was won, if false the game was lost :- NO_MORE_ENEMIES_AND_ALL_WAVES_SPAWNED, // Params -: :- //End Of Group: Game Stuff //Group:Entity To Entity REDUCE_LIFE, // Params -: float :- YOU_HAVE_BEEN_SHOT, // Params -: :- YOU_KILLED_ME, // Params -: GameEnity* (the enity sending the message) :- //This message is sent when one entity kills another //End Of Group: Entity To Entity //Group:Tower Stuff UPGRADE_YOURSELF, // Params -: NULL :- BEEN_SOLD, // Params -: NULL in case we want a component to make a sparkly effect or something :- TARGET_PRIORITY_CHANGED, // Params -: enum TargetPriotiry :- YOU_ARE_BEING_PLACED, // Params -: :- UN_CLICKED, // Params -: :- LOOK_AT, // Params -: :- CLICKED, // Params -: :- FIRE_AT_ENTITIES, // Params -: :- SET_ACTION_CAMERA, // Params -: :- FIRE_AT_NOTHING, // Params -: :- //End Of Group: Tower Stuff //Group:Station stuff SELL_STATION, // Params -: :- SELL_ALL_TOWERS, // Params -: :- UPGRADE_ALL_TOWERS, // Params -: :- //End Of Group: Station stuff //Group:AI control AI_PAUSE_THINKING, // Params -: :- AI_RESUME_THINKING, // Params -: :- AI_SET_AGGRESSIVE, // Params -: :- AI_SET_PASSIVE, // Params -: :- AI_SET_DEFENSIVE, // Params -: :- ENTITIES_DETECTED, // Params -: :- ENEMIES_DETECTED, // Params -: :- //End Of Group: AI control //Group:Steering STEERING_TURN_OFF_ALL, // Params -: :- STEERING_TURN_ON_ALL, // Params -: :- STEERING_SEEK_TO_TARGET_POS, // Params -: XF::vector3 :- STEERING_FOLLOW_PATH, // Params -: PathDataPacket :- STEERING_ARRIVE_AT_TARGET_POS, // Params -: XF::vector3 :- STEERING_SET_ARRIVE_DECELERATION, // Params -: float :- STEERING_WANDER, // Params -: :- STEERING_UPDATE_STEER_DATA, // Params -: steering data :- PATH_DATA, // Params -: :- UPDATE_TARGET_POS, // Params -: :- UPDATE_TARGET_ENTITY, // Params -: :- SEND_ME_DISTANCE_TO_GOAL, // Params -: :- SENT_DISTANCE_TO_GOAL, // Params -: float :- TURN_ON_STEERING_BEHAVIOUR, // Params -: :- TURN_OFF_STEERING_BEHAVIOUR, // Params -: :- ADD_STEERING_BEHAVIOUR, // Params -: :- REMOVE_STEERING_BEHAVIOUR, // Params -: :- //End Of Group: Steering //Group:Body APPLY_FORCE, // Params -: :- SET_POSITION, // Params -: :- ROTATE_TO_FACE, // Params -: vector3 :- //End Of Group: Body //Group:Entity To Self CREATE_FIRE_AND_FORGET_ENTITY, // Params -: :- DIED, // Params -: :- CREATED, // Params -: :- FIRE, // Params -: :- ROAD_MAP_CHANGED, // Params -: :- ARRIVED_AT_GOAL, // Params -: :- OOPS, // Params -: :- //This message is sent to itself if the entity kills someone on their own team HEALTH_CHANGED, // Params -: :- YOU_ARE_FROZEN, // Params -: :- YOU_ARE_UNFROZEN, // Params -: :- YOU_ARE_SLOWED, // Params -: :- YOU_ARE_NOT_SLOWED, // Params -: :- //End Of Group: Entity To Self //Group:Entity Out DECREASE_ENEMIES, // Params -: :- //End Of Group: Entity Out }; std::string MessageSubjectToString(XF::MessageSubject::ENUM sub); XF::MessageSubject::ENUM StringToMessageSubject(std::string message);} } Now as you can see, this file is buryed deep inside the engine, and requires modifying every time a new message is needed, not very good for compiling the library into a .lib and jsut using that instead of recompiling it from source every time. Now, I would rather steer clear of the obvious "change messageSubject to a string" if possible, so does anyone have any suggestions as to how I can change this? Thanks all, Scott Code posted to google code: https://code.google.com/p/xframeworkcomponentsengine/ [Edited by - gameXcore on June 1, 2010 5:24:43 PM]
  16. gameXcore

    function pointer

    You may also want to google for "Delegates" for a more robust solution. Personally my favorite type is "impossibly fast delegates".
  17. gameXcore

    Component-Based Entity Help

    The way I solved this was to design components carefully. If any one component is dependant upon another I make sure that component gets refactored and rewritten into such a way that the dependency no longer exists.
  18. The ideas seem very nice, if I'm completely honest however, I'm not understanding them enough to see how they would fit in, for example, using Katie's suggestion, how would that fit into a switch statement (to avoid having to re-write) as don't switch statements require a constant expression, and from what I understand from your post, I would require a function to turn the 8 letter message "GUI_SENT" into an integer for the switch. Thanks, Scott
  19. Hey Matt, Sorry for taking so long to reply, and wow that was a long descriptive post. What I gather from it however is that it is a proposal of using a callback system, where a class would have to register with every message it would ever be interested in. Almost the same as how I notify when Property's change, I use an events system like you would find in C#, basically a list of delegates, when I create a component, for example the "Renderable" component, it registers a callback with the "Position" property, which is called when "Position" changes, this way the Renderable component can update the view. The problem with this is how much code would have to be changed. And also it doesn't feel as intuitive or easy to use as simply sticking an extra case into a switch statement. I have just come up with one idea, which while a little ugly and hacky does seem to work and requires barely any modifications to the existing code-base. Here's my solution: First off I change the Message class to accept an int as the subject, as opposed to XF::MessageSubject::Enum. struct Message { int Subject; int SenderID; int ReceiverID; float SendTime; void* Data; }; Now, I utilize the scoping of enums to allow the user to "add" extra enumerations to the list, first I modify my internal message enum so that it starts counting from some high value: namespace XF { namespace MessageSubject { enum ENUM { //Group:Graphics API PLEASE_SEND_RENDERER = 10000, // Params -: :- SENT_RENDERER, // Params -: :- //End Of Group: Graphics API Scoping means that you access these using XF::MessageSubject::PLEASE_SEND_RENDERER, as opposed to XF::MessageSubject::ENUM::PLEASE_SEND_RENDERER. And as you can see, this enum counts up from 1000. So here's the hacky bit, in my project I create a second enumeration, starting at 0, but in the same namespaces "XF::MessageSubject" as follows: namespace XF { namespace MessageSubject { enum EXT_ENUM { BOB, CHARLES, WOOP, }; } } Now the XF::MessageSubject namespace all contains the following: PLEASE_SEND_RENDERER, SENT_RENDERER, BOB, CHARLES, WOOP And providing the user doesn't go over 10000 message enums, hey all have unique integer values meaning I can switch on them happily, as an added bonus (instead of just declaring an enum in any namespace, which would work) I can use intellisense to give me a list of possible message types all int he same namespace. [That bit doesn't make much sense, but I can't think of a better way to phrase it]. Anyway, packaged with a tool for streamlining the creation of the enumeration as well as a list of string values to convert between enum and string representation this could just work. I'm very interested to here reactions and responses to this admittedly hacky approach, here's the full listing of my little test program I wrote to try it: (MessageSubjects.h) namespace XF { namespace MessageSubject { enum EXT_ENUM { BOB, CHARLES, WOOP, }; } } (MainProg.cpp) #include "MessageSubjects.h" #include <XFramework.h> #include <iostream> class TestClass : public XF::Messenger { public: bool OnHandleMessage(const XF::Message &message) { switch(message.Subject) { case XF::MessageSubject::BOB: { std::cout << "bob\n"; break; } case XF::MessageSubject::PLEASE_SEND_RENDERER: { std::cout << "Renderer\n"; break; } } return true; } }; int main() { XF::Message message; message.Subject = XF::MessageSubject::BOB; TestClass c; c.HandleMessage(message); message.Subject = XF::MessageSubject::PLEASE_SEND_RENDERER; c.HandleMessage(message); system("pause"); return 0; } (Program output) bob Renderer
  20. gameXcore

    Which google code license to use?

    Hey, Sorry for my late reply, I came across that site but completly missed the section you pointed me to and quickly got bogged down. Thankyou very much.
  21. Hi, I'm pretty sure this is a common question on here, but I cant come across the search terms to find a previous discussion. I've just uploaded my project to google code, and I'm wandering which license to go with, and am completely stuck with where to start. Does anyone know of a good resource which weighs up the pros's and con;s of each so I can make an educated decision of which one to use? Thanks, Scott
  22. So, opening my mind to rewriting all my message handlers, I guess the only way around this is to use strings, given strings are rather hard to maintain tho, I'm going to have to come up with someway of keeping things in order. Does anyone have any suggestions or bright ideas, I've spent the last couple of days trying to come up with the golden solution, but nothing works, or feels right. I'm thinking the solution is probably going to involve some pre-processor code generation magic.
  23. Hi all, After a major redesign and rework of one of my systems I've come across a bit of a problem that I'm stumped on. I have two functions in the same (template) class: IProperty* MakeProperty(const std::string &name, const std::string &initialValue) { MakerType *newProp = new MakerType(mIDName, name); newProp->SetFromString(initialValue); return newProp; } IProperty* MakeProperty(const std::string &name, PropertyType value) { MakerType *newProp = new MakerType(mIDName, name); newProp->Set(value); return newProp; } MakerType is a template argument that will be a class that derives from Property<template> which in turn derives from IProperty (the explanation has been simplified). SetFromString will set the property by reading in a string and converting to the correct data type and Set sets the property using its native (template) type. So as you can see the two functions above will create a new property and set its value using one of the two methods (string or native) depending on usage (both are needed for different occasions, ie, when reading and creating a property from a script file we will set by text, however when creating a property in code we would want to set it using the native data type). The problem I am having is when creating a Property<std::string> because both of these functions have the same signature (well not the same, but too similar for the compiler to choose the correct one): IProperty* MakeProperty(const std::string &name, const std::string &initialValue); IProperty* MakeProperty(const std::string &name, std::string value) Does anyone have any ideas how I can solve this problem in a generic way without adding case specific code for the string property type? Thanks, Scott
  24. Using that suggestion how would I go about determining the type of the message when it is received? The main reason I dont want to use std::strings as the message subject is that I would rather not go through and rewrite 3 projects worth of statements which switch on an enumeration in every handle message function to statements which perform an if...if else...else chain.
  25. I did indeed change the same of the second function, I also moved the role up a level, instead of the Maker class having two functions it now only has one: IProperty* MakeProperty(const std::string &name); This function will make the property and set it to an initial value. The PropertyFactory class, which will choose the correct maker now has two functions: static IProperty* CreateProperty(const std::string &id, const std::string &name, const std::string &initialValue); template<class T> static Prop<T>* CreatePropertyUsingType(std::string name, T value) The second will work out which Maker to use based on the template type (so calling CreatePropertyUsingType<bool>("visible") will locate the PropertyMaker<bool> instance in the collection) and use it to create a Prop<bool> which is then set to value. Again thanks for all the comments and discussion.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!