Re: Build tool refusing Class directive
Thanks for your response - I forgot to make that call so I am pretty sure that is what the problem is.
I'm a little confused though on how to set up the dll so my game is aware of the NsRegisterReflection method. I would think I need to declare it in a header that my game includes but in all the Noesis code I see it is in a cpp file and the Noesis tools seem to pick it up without any issues. Again, I am new to creating dlls but the information I see online is suggesting I put that function in a header. I tried that but then the Noesis tools fail to load the xaml so I may be setting that up incorrectly. Is this process of generating a dll and then referencing it from within an application explained in more detail somewhere?
Also, as I am using Ogre to insert that call where it needs to go requires me to edit the Ogre Bindings. That really isn't a problem for me as I am including the source directly anyway but I figured I should call that out so that hooks can be built in for future releases of the bindings project.
I'm a little confused though on how to set up the dll so my game is aware of the NsRegisterReflection method. I would think I need to declare it in a header that my game includes but in all the Noesis code I see it is in a cpp file and the Noesis tools seem to pick it up without any issues. Again, I am new to creating dlls but the information I see online is suggesting I put that function in a header. I tried that but then the Noesis tools fail to load the xaml so I may be setting that up incorrectly. Is this process of generating a dll and then referencing it from within an application explained in more detail somewhere?
Also, as I am using Ogre to insert that call where it needs to go requires me to edit the Ogre Bindings. That really isn't a problem for me as I am including the source directly anyway but I figured I should call that out so that hooks can be built in for future releases of the bindings project.
Re: Build tool refusing Class directive
Yes, how to handle extensions to NoesisGUI are left to the user. In fact, our tools use a dynamic systems that scans all the DLLs found in a directory and registers them.
But that solution is quite generic and probably people don't need that complexlity. In fact, you probably have always a single DLL (or even not having a DLL) and the solution is as simple as calling the function to register all the elements.
You don't need to declare the function in the header to be exported. Having it in the cpp is enough to be recognized by XamlPlayer. But you probably will need a header to call it yourself from your application.
I don't think this should affect the Ogre bidings. It is a custom code you can insert after Noesis initialization. You must invoke manually the function:
Although bindings could be improved to have a callback that is invoked automatically and the user can fill with its registrations.
But that solution is quite generic and probably people don't need that complexlity. In fact, you probably have always a single DLL (or even not having a DLL) and the solution is as simple as calling the function to register all the elements.
You don't need to declare the function in the header to be exported. Having it in the cpp is enough to be recognized by XamlPlayer. But you probably will need a header to call it yourself from your application.
Code: Select all
extern "C" NS_DLL_EXPORT void NsRegisterReflection(ComponentFactory* factory, NsBool registerComponents)
{
NS_REGISTER_COMPONENT(UppercaseConverter)
}
Code: Select all
// Setup NsGui
Noesis_Init(mSceneMgr);
NsRegisterReflection(NsGetKernel()->GetComponentFactory(), true);
Noesis_LoadXAML(&mUIRoot, &mUIRenderer, "Gui/Samples/Time.xaml");
Noesis_RendererAntialiasingMode(mUIRenderer, 1); // PAA
Re: Build tool refusing Class directive
Thanks again for your response. I've set up my extensions dll with a header so that I can reference it from my game. The Noesis resource builder parses it fine and generates the resources, but when I call
in my game I get the following exception from line 148 in ComponentFactoryImpl.cpp:
"Component 'Converter<Bool> (TypeConverter)' already registered"
It is very possible I have set up something incorrectly within my extensions dll. Here is the relevant code from within that project:
GuiExtensions.h (included by my game):
GuiExtensions.cpp
NumericUpDown.h
NumericUpDown.cpp
Do you notice any errors with how I have this set up?
Thanks for you help.
Code: Select all
NsRegisterReflection(NsGetKernel()->GetComponentFactory(), true);
"Component 'Converter<Bool> (TypeConverter)' already registered"
It is very possible I have set up something incorrectly within my extensions dll. Here is the relevant code from within that project:
GuiExtensions.h (included by my game):
Code: Select all
#include "stdafx.h"
#include <NsGui/UserControl.h>
#include <NsCore/TypeId.h>
extern "C" NS_DLL_EXPORT
void NsRegisterReflection(Noesis::Core::ComponentFactory* factory, NsBool registerComponents);
Code: Select all
#include "stdafx.h"
#include <NsGui/UserControl.h>
#include <NsCore/TypeId.h>
#include "NumericUpDown.h"
extern "C" NS_DLL_EXPORT
void NsRegisterReflection(Noesis::Core::ComponentFactory* factory, NsBool registerComponents)
{
NS_REGISTER_COMPONENT(NumericUpDown)
};
Code: Select all
#include "stdafx.h"
#pragma warning(disable: 4275)
#pragma warning(disable: 4251)
#include <Noesis.h>
#include <NsGui/UserControl.h>
#include <NsGui/UIElementData.h>
#include <NsGui/FrameworkPropertyMetaData.h>
#include <NsGui/RoutedEvent.h>
#include <NsCore/ReflectionImplement.h>
#include <NsCore/TypeId.h>
#include <NsCore/Package.h>
using namespace Noesis;
using namespace Noesis::Core;
using namespace Noesis::Gui;
////////////////////////////////////////////////////////////////////////////////////////////////////
class NumericUpDown: public UserControl
{
public:
/// Gets or sets numeric spinner value
//@{
NsInt32 GetValue() const;
void SetValue(NsInt32 value);
//@}
public:
static const DependencyProperty* ValueProperty;
static const RoutedEvent* ValueChangedEvent;
protected:
virtual void OnValueChanged(const RoutedPropertyChangedEventArgs<NsInt32>& args);
/// From DependencyObject
//@{
NsBool OnPropertyChanged(const Gui::DependencyPropertyChangedEventArgs& args);
//@}
private:
void UpButton_Click(BaseComponent* sender, const Gui::RoutedEventArgs& e);
void DownButton_Click(BaseComponent* sender, const Gui::RoutedEventArgs& e);
NS_IMPLEMENT_INLINE_REFLECTION(NumericUpDown, UserControl)
{
NsMeta<TypeId>("NumericUpDown");
NsProp("Value", &NumericUpDown::GetValue, &NumericUpDown::SetValue);
NsFunc("UpButton_Click", &NumericUpDown::UpButton_Click);
NsFunc("DownButton_Click", &NumericUpDown::DownButton_Click);
NsString source = "Gui/WKDX/numeric_up_down.xaml";
Ptr<UIElementData> data = NsMeta<UIElementData>(TypeOf<SelfClass>());
data->RegisterProperty<NsInt32>(ValueProperty, "Value",
FrameworkPropertyMetadata::Create(NsInt32(0), FrameworkOptions_None));
data->OverrideMetadata<NsString>(UserControl::SourceProperty, "Source",
FrameworkPropertyMetadata::Create(source, FrameworkOptions_None));
data->RegisterEvent(ValueChangedEvent, "ValueChanged", RoutingStrategy_Bubbling);
}
};
Code: Select all
#include "stdafx.h"
#pragma warning(disable: 4275)
#pragma warning(disable: 4251)
#include "NumericUpDown.h"
#include <Noesis.h>
#include <NsGui/UserControl.h>
#include <NsGui/UIElementData.h>
#include <NsGui/FrameworkPropertyMetaData.h>
#include <NsGui/RoutedEvent.h>
#include <NsCore/ReflectionImplement.h>
#include <NsCore/TypeId.h>
#include <NsCore/Package.h>
using namespace Noesis;
using namespace Noesis::Core;
using namespace Noesis::Gui;
const DependencyProperty* NumericUpDown::ValueProperty;
const RoutedEvent* NumericUpDown::ValueChangedEvent;
NsInt32 NumericUpDown::GetValue() const
{
return DependencyObject::GetValue<NsInt32>(ValueProperty);
}
void NumericUpDown::SetValue(NsInt32 value)
{
DependencyObject::SetValue<NsInt32>(ValueProperty, value);
}
void NumericUpDown::OnValueChanged(const RoutedPropertyChangedEventArgs<NsInt32>& args)
{
RaiseEvent(args);
}
NsBool NumericUpDown::OnPropertyChanged(const Gui::DependencyPropertyChangedEventArgs& args)
{
NsBool handled = ParentClass::OnPropertyChanged(args);
if (!handled)
{
if (args.prop == ValueProperty)
{
NsInt32 oldValue = *static_cast<const NsInt32*>(args.oldValue);
NsInt32 newValue = *static_cast<const NsInt32*>(args.newValue);
RoutedPropertyChangedEventArgs<NsInt32> e(this, ValueChangedEvent,
oldValue, newValue);
OnValueChanged(e);
return true;
}
}
return handled;
}
void NumericUpDown::UpButton_Click(BaseComponent* sender, const Gui::RoutedEventArgs& e)
{
SetValue(GetValue() + 1);
}
void NumericUpDown::DownButton_Click(BaseComponent* sender, const Gui::RoutedEventArgs& e)
{
SetValue(GetValue() - 1);
}
//extern "C" NS_DLL_EXPORT
//void NsRegisterReflection(Noesis::Core::ComponentFactory* factory, NsBool registerComponents)
//{
// NS_REGISTER_COMPONENT(NumericUpDown)
//};
Thanks for you help.
Re: Build tool refusing Class directive
Hmm... I think I know what is happening here. There are two functions named NsRegisterReflection, one in Noesis.dll and the other one in your DLL. And being in the globalnamespace (because they have to be exported) the compiler is not able to distinguish them. When you are calling your NsRegisterReflection you are in fact calling the version found in Noesis.dll. And you are getting errors about component already registered because that function can only be invoked once.in my game I get the following exception from line 148 in ComponentFactoryImpl.cpp:
"Component 'Converter<Bool> (TypeConverter)' already registered"
It is very possible I have set up something incorrectly within my extensions dll. Here is the relevant code from within that project:
We need to fix this by renaming the funcion NsRegisterReflection found in Noesis.dll. Meanwhile as a temporal fix, you have to duplicate your NsRegisterReflection function (give it another name) and call that one from your code.
I don't know if my explanation is clear. Hope so...
Re: Build tool refusing Class directive
Yep, that was the problem. The NumericUpDown example is loading fine now in my game so I am in a good spot to progress with my own controls. Thanks for your help!
Re: Build tool refusing Class directive
I think we don't have to change anything, the current architecture is correct.
- You register your components in a new function called as you wish.
- You implement the required exported function NsRegisterReflection. It is implemented by invoking the function defined above.
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 2 guests