Passing a value into a bound class.

Started by
21 comments, last by TechRogue 11 years, 6 months ago
Ok here's the deal,

I have an Image class with a draw function like this:

void Img::Draw(SDL_Surface* surface) {
SDL_Rect offset;
offset.x = X;
offset.y = Y;
SDL_BlitSurface(imgSurface, NULL, surface, &offset);
}


I would like to be able to do this in the script:

Image img;

img.x = 0;
img.y = 0;

img.Draw();


But I need to pass the screen Surface to the draw function I don't want my scripters to have to do img.Draw(GetSurface()); I would like this to be handled through the C++ backend code is there a way that everytime img.Draw() is called in script I can pass the SDL_Surface into the C++ method?

If you need this explained better ask away its 12 A.M. here tongue.png might not have explained it the best.
Advertisement
how about you also have this draw function


void Img::Draw() {
Draw(GetSurface());
}

how about you also have this draw function


void Img::Draw() {
Draw(GetSurface());
}



Well I thought that at first too, but the thing is GetSurface(); is in my engine class which has an instance that would need to be passed but I don't know if I can pass the instance into the Image class every time a new one is created in Angelscript. Sorry rather new to Angelscript sad.png
first divide your problem to small problems.

can you do this in your script now?


Image img;
img.x = 0;
img.y = 0;


if not please read this section of the manual
http://www.angelcode.com/angelscript/sdk/docs/manual/doc_register_api_topic.html

first divide your problem to small problems.

can you do this in your script now?


Image img;
img.x = 0;
img.y = 0;


if not please read this section of the manual
http://www.angelcode..._api_topic.html

Yesir :) got that far.
then i just dont understand why you cant create a second function in you Img class.

class Img
{
void Img::Draw(SDL_Surface* surface)
{
SDL_Rect offset;
offset.x = X;
offset.y = Y;
SDL_BlitSurface(imgSurface, NULL, surface, &offset);
}

void Img::Draw()
{
Draw(GetSurface());
}
}

register Img::Draw() to script.
like this

r = engine->RegisterObjectMethod("Image", "void Draw()", asMETHODPR(Image, Draw, (void), void), asCALL_THISCALL);


surely you have access to GetSurface() function in C++. ( or engine->GetSurface() )

then i just dont understand why you cant create a second function in you Img class.

class Img
{
void Img::Draw(SDL_Surface* surface)
{
SDL_Rect offset;
offset.x = X;
offset.y = Y;
SDL_BlitSurface(imgSurface, NULL, surface, &offset);
}

void Img::Draw()
{
Draw(GetSurface());
}
}

register Img::Draw() to script.
like this

r = engine->RegisterObjectMethod("Image", "void Draw()", asMETHODPR(Image, Draw, (void), void), asCALL_THISCALL);


surely you have access to GetSurface() function in C++. ( or engine->GetSurface() )

You are quite right but I cant pass my engine variable into a c++ class that's not instanced yet can I? Sorry for being newbish like I said I'm new to angelscript. But I don't know how to pass in GetSurface() into my Img class. Without first saying Image img = new Image(engine); on my C++ side.
your problem is pretty much a c++ pointer ownership issue.

So what is this mystical "engine" class would you show me?
Here's how I give my classes access to the main engine class:

When I set up the script engine, I pass the address of my engine class instance in as userdata (a void pointer):


engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetUserData(&myGameEngine);


Then, in my class constructors that need a pointer to the engine (to access window drawing, content management, etc.), I do this:


asIScriptContext* context = NULL;
asIScriptEngine* engine = NULL;
context = asGetActiveContext(); // Get the currently executing angelscript context
if ((context = asGetActiveContext()) != NULL && (engine = context->GetEngine()) != NULL)
{
// owner is a member pointer to the engine
owner = reinterpret_cast<Engine*>(engine->GetUserData());
}


Hopefully that helps.

Here's how I give my classes access to the main engine class:

When I set up the script engine, I pass the address of my engine class instance in as userdata (a void pointer):


engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
engine->SetUserData(&myGameEngine);


Then, in my class constructors that need a pointer to the engine (to access window drawing, content management, etc.), I do this:


asIScriptContext* context = NULL;
asIScriptEngine* engine = NULL;
context = asGetActiveContext(); // Get the currently executing angelscript context
if ((context = asGetActiveContext()) != NULL && (engine = context->GetEngine()) != NULL)
{
// owner is a member pointer to the engine
owner = reinterpret_cast<Engine*>(engine->GetUserData());
}


Hopefully that helps.


Gonna try that but here is my engine class


#include "Engine.h"
#include <windows.h> // For the WaitMessage() function.
#include "Scripting/ScriptManager.h"
using namespace Ogre;
/** Default constructor. **/
AffinityEngine::AffinityEngine() {
m_lLastTick = 0;
m_iWidth = 1024;
m_iHeight = 768;
m_czTitle = 0;
m_pScreen = 0;
m_iFPSTickCounter = 0;
m_iFPSCounter = 0;
m_iCurrentFPS = 0;
m_bMinimized = false;
}
/** Destructor. **/
AffinityEngine::~AffinityEngine() {
SDL_Quit();
}
/** Sets the height and width of the window.
@param iWidth The width of the window
@param iHeight The height of the window
**/
void AffinityEngine::SetSize(const int& iWidth, const int& iHeight) {
m_iWidth = iWidth;
m_iHeight = iHeight;
if(m_vmVideoMode == VideoMode_3D) {
m_pScreen = SDL_SetVideoMode( iWidth, iHeight, 0, SDL_OPENGL );
} else if(m_vmVideoMode == VideoMode_2D) {
m_pScreen = SDL_SetVideoMode( iWidth, iHeight, 0, SDL_SWSURFACE );
}
}
/** Initialize SDL, the window and the additional data. **/
void AffinityEngine::Init(VideoMode videoMode) {
printf("Engine Initialing.\n");
// Register SDL_Quit to be called at exit; makes sure things are cleaned up when we quit.
atexit( SDL_Quit );
// Initialize SDL's subsystems - in this case, only video.
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
fprintf( stderr, "Unable to init SDL: %s\n", SDL_GetError() );
exit( 1 );
}
SetTitle("Affinity Engine");
m_vmVideoMode = videoMode;
// Attempt to create a window with the specified height and width.
SetSize(m_iWidth, m_iHeight);
if(videoMode == VideoMode_3D){
m_rRoot = new Root("plugins_d.cfg", "ogre.cfg", "AffinityEngine.log");
m_rRoot->restoreConfig();
m_rRoot->initialise(false);
NameValuePairList misc;
#ifdef _WIN32
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWMInfo(&wmInfo);

size_t winHandle = reinterpret_cast<size_t>(wmInfo.window);
size_t winGlContext = reinterpret_cast<size_t>(wmInfo.hglrc);

misc["externalWindowHandle"] = StringConverter::toString(winHandle);
misc["externalGLContext"] = StringConverter::toString(winGlContext);
#else
misc["currentGLContext"] = String("True");
#endif
m_rwRenderWindow = m_rRoot->createRenderWindow("MainRenderWindow", 1024, 768, false, &misc);
m_rwRenderWindow->setVisible(true);
printf("Initialized 3D Rendering.\n");
} else {
printf("Initialized 2D Rendering.\n");
}
// If we fail, return error.
if ( m_pScreen == NULL ) {
fprintf( stderr, "Unable to set up video: %s\n", SDL_GetError() );
exit( 1 );
}
printf("Engine Initialized.\n");
AdditionalInit();
}
/** The main loop. **/
void AffinityEngine::Start() {
printf("Engine Started\n");
m_lLastTick = SDL_GetTicks();
m_bQuit = false;
m_smScriptManager = new ScriptManager("../Data/Scripts", this);
m_smScriptManager->Init();
// Main loop: loop forever.
while ( !m_bQuit ) {
// Handle mouse and keyboard input
HandleInput();
if ( m_bMinimized ) {
// Release some system resources if the app. is minimized.
WaitMessage(); // pause the application until focus in regained
} else {
// Do some thinking
DoLogic();
// Render stuff
DoRender();
}
}
End();
}
/** Handles all controller inputs.
@remark This function is called once per frame.
**/
void AffinityEngine::HandleInput() {
// Poll for events, and handle the ones we care about.
SDL_Event event;
while ( SDL_PollEvent(&event) ) {
switch (event.type) {
case SDL_KEYDOWN:
// If escape is pressed set the Quit-flag
/*if (event.key.keysym.sym == SDLK_ESCAPE){
m_bQuit = true;
break;
}*/
m_smScriptManager->e_imInputMgr->InjectKeyboard(event.key.keysym.sym, InputState::Down);
KeyDown(event.key.keysym.sym);
break;
case SDL_KEYUP:
m_smScriptManager->e_imInputMgr->InjectKeyboard(event.key.keysym.sym, InputState::Up);
KeyUp(event.key.keysym.sym);
break;
case SDL_QUIT:
m_bQuit = true;
break;
case SDL_MOUSEMOTION:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseMoved(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_MOUSEBUTTONUP:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseButtonUp(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_MOUSEBUTTONDOWN:
m_smScriptManager->e_imInputMgr->InjectMouse(event.motion.x, event.motion.y, event.button.button);
MouseButtonDown(event.button.button, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
break;
case SDL_ACTIVEEVENT:
if ( event.active.state & SDL_APPACTIVE ) {
if ( event.active.gain ) {
m_bMinimized = false;
WindowActive();
} else {
m_bMinimized = true;
WindowInactive();
}
}
break;
} // switch
} // while (handling input)
}
/** Handles the updating routine. **/
void AffinityEngine::DoLogic() {
long iElapsedTicks = SDL_GetTicks() - m_lLastTick;
m_lLastTick = SDL_GetTicks();
m_smScriptManager->ParseScripts();
Logic( iElapsedTicks );
m_smScriptManager->Update();
m_iFPSTickCounter += iElapsedTicks;
}
/** Handles the rendering and FPS calculations. **/
void AffinityEngine::DoRender() {
++m_iFPSCounter;
if ( m_iFPSTickCounter >= 1000 ) {
m_iCurrentFPS = m_iFPSCounter;
m_iFPSCounter = 0;
m_iFPSTickCounter = 0;
}
if(m_vmVideoMode == VideoMode_2D) {
SDL_FillRect( m_pScreen, 0, SDL_MapRGB( m_pScreen->format, 0, 0, 0 ) );
// Lock surface if needed
if ( SDL_MUSTLOCK( m_pScreen ) )
if ( SDL_LockSurface( m_pScreen ) < 0 )
return;
Render( GetSurface() );
m_smScriptManager->Draw();
// Unlock if needed
if ( SDL_MUSTLOCK( m_pScreen ) )
SDL_UnlockSurface( m_pScreen );
// Tell SDL to update the whole gScreen
SDL_Flip( m_pScreen );
}else{
m_rRoot->renderOneFrame();
SDL_GL_SwapBuffers();
}
}
/** Sets the title of the window
@param czTitle A character array that contains the text that the window title should be set to.
**/
void AffinityEngine::SetTitle(std::string czTitle) {
m_czTitle = czTitle.c_str();
SDL_WM_SetCaption( czTitle.c_str(), 0 );
}
/** Retrieve the title of the application window.
@return The last set windows title as a character array.
@remark Only the last set title is returned. If another application has changed the window title, then that title won't be returned.
**/
const char* AffinityEngine::GetTitle() {
return m_czTitle;
}
/** Retrieve the main screen surface.
@return A pointer to the SDL_Surface surface
@remark The surface is not validated internally.
**/
SDL_Surface* AffinityEngine::GetSurface() {
return m_pScreen;
}
/** Get the current FPS.
@return The number of drawn frames in the last second.
@remark The FPS is only updated once each second.
**/
int AffinityEngine::GetFPS() {
return m_iCurrentFPS;
}
void AffinityEngine::Shutdown() {
m_bQuit = true;
}
ScriptManager* AffinityEngine::GetScriptManager() {
return m_smScriptManager;
}


Ok while making those changes I got this error:

Engine Initialing.
Initialized 2D Rendering.
Engine Initialized.
Engine Started
(0, 0) : ERR : Failed in call to function 'RegisterObjectBehaviour' with 'Imag
e' and 'ref@ f()' (Code: -10)


from this line


r = e_seScriptEngine->RegisterObjectBehaviour("Image", asBEHAVE_FACTORY, "ref@ f()", asFUNCTION(Img_Factory), asCALL_CDECL); assert(r >= 0);


and here is the function:


static Img* Img_Factory() {
return new Img();
}

This topic is closed to new replies.

Advertisement