Sel_CallFuncN cannot cast void to Sel_CallFuncN - cocos2d-x

I'm trying to get an intro screen in my game. After a few seconds it should change to the game itself.
In the Init of my introscreen class, I try to make a sequence, but I'm getting the following error:
cannot cast from type void to member pointer type
'cocos2d::SEL_CallFuncN' (aka
'void(cocos2d::CCObject::*)(cocos2d::CCNode *)'
here's my code:
bool IntroScreen::init() {
if (!CCLayer::init()) {
return false;
}
cocos2d::CCSize screenSize = cocos2d::CCDirector::sharedDirector()->getWinSize();
cocos2d::CCSprite* logomarca = cocos2d::CCSprite::create("rayman_intro.png");
logomarca->setPosition(ccp(screenSize.width / 2, screenSize.height / 2));
this->addChild(logomarca, 1);
cocos2d::CCFiniteTimeAction *seq1 = cocos2d::CCSequence::create(cocos2d::CCDelayTime::create(3.0),
cocos2d::CCCallFuncN::create(this,
cocos2d::SEL_CallFuncN(cocos2d::CCDirector::sharedDirector()->replaceScene(Controller::scene())), NULL);
this->runAction(seq1);
return true;
}
What am I doing wrong?

You can use scheduler here instead of CCFiniteTimeAction like this..
this->scheduleOnce(schedule_selector(IntroScreen::replace), 3);
void IntroScreen::replace(CCObject* sender){
cocos2d::CCDirector::sharedDirector()->replaceScene(Controller::scene();
}
Also insert a statement "using namespace cocos2d;" at the top to avoid writing cocos2d:: everywhere.

in SEL_CallFuncN you should put pointer to function not the function
For example
cocos2d::SEL_CallFuncN(IntroScreen::replace)
In replace put the code you want to invoke, if you use CallFuncN your method should have in first parametr place for object, which run the function
void IntroScreen::replace(CCObject* sender){
cocos2d::CCDirector::sharedDirector()->replaceScene(Controller::scene();
}

Related

How can I get updated parameter from CallFunc? (cocos2d-x V3.0)

I want to get updated the parameter time from CallFunc. However, the time I got from CallFunc where I updated, is always ZERO. That is DelayTime::create(updatedTime) is ZERO.
Do anyone know how to use parameter from CallFunc in DelayTime?
1/ Please provide your code. We don't understand your question.
2/ Both CallFunc and DelayTime return an cocos2d::Action, you can't call one of them inside each other.
3/ CallFunc:
http://www.cocos2d-x.org/docs/api-ref/cplusplus/v3x/d3/d32/classcocos2d_1_1_call_func.html
function define: static CallFunc* create (Ref *target, SEL_CallFunc selector)
example:
using namespace cocos2d;
class A() : Node //(or anything that inherited Ref)
{/*...(defined function f())...*/}
A *a = new A();
CallFunc* callFunc = CallFunc::create(a, SEL_CallFunc(&A::f));
a->runAction(callFunc);
DelayTime:
http://www.cocos2d-x.org/docs/api-ref/cplusplus/v3x/d5/d58/classcocos2d_1_1_delay_time.html
function define: static DelayTime* create(float d)
example:
A *a = new A();
DelayTime* wait = DelayTime::create(4);
a->runAction(wait); // this is useless, you must put a DelayTime in a Sequence
p/s: Sequence is an Action, too. To create a Sequence, use
Sequence* seq = Sequence::create(action1, action2, action3, NULL);

Custom GTK widget in Vala not working

I'm trying to make a custom GTK widget in Vala, but I'm already failing at the very first basic attempt, so I'd like some help in knowing where I'm going wrong. I feel like I must be missing something painstakingly obvious, but I just can't see it.
I have three files with the following contents:
start.vala:
using Gtk;
namespace WTF
{
MainWindow main_window;
int main(string[] args)
{
Gtk.init(ref args);
main_window = new MainWindow();
Gtk.main();
return 0;
}
}
main_window.vala:
using Gtk;
namespace WTF
{
public class MainWindow : Window
{
public MainWindow()
{
/* */
Entry entry = new Entry();
entry.set_text("Yo!");
this.add(entry);
/* */
/*
CustomWidget cw = new CustomWidget();
this.add(cw);
/* */
this.window_position = WindowPosition.CENTER;
this.set_default_size(400, 200);
this.destroy.connect(Gtk.main_quit);
this.show_all();
}
}
}
custom_widget.vala:
using Gtk;
namespace WTF
{
public class CustomWidget : Bin
{
public CustomWidget()
{
Entry entry = new Entry();
entry.set_text("Yo");
this.add(entry);
this.show_all();
}
}
}
As you can see, in main_window.vala, I have two sets of code. One that adds the Entry widget directly, and one that adds my custom widget. If you run the one that adds the Entry widget directly, you get this result:
If you run the one with the custom widget, however, you get this result:
Just for the record, this is the complication command I use:
valac --pkg gtk+-2.0 start.vala main_window.vala custom_widget.vala -o wtf
EDIT:
Following user4815162342's suggestion, I implemented the size_allocate method on my custom Bin widget, like so:
public override void size_allocate(Gdk.Rectangle r)
{
stdout.printf("Size_allocate: %d,%d ; %d,%d\n", r.x, r.y, r.width, r.height);
Allocation a = Allocation() { x = r.x, y = r.y, width = r.width, height = r.height };
this.set_allocation(a);
stdout.printf("\tHas child: %s\n", this.child != null ? "true" : "false");
if (this.child != null)
{
int border_width = (int)this.border_width;
Gdk.Rectangle cr = Gdk.Rectangle()
{
x = r.x + border_width,
y = r.y + border_width,
width = r.width - 2 * border_width,
height = r.height - 2 * border_width
};
stdout.printf("\tChild size allocate: %d,%d ; %d, %d\n", cr.x, cr.y, cr.width, cr.height);
this.child.size_allocate(cr);
}
}
It writes the following in the console:
Size_allocate: 0,0 ; 400,200
Has child: true
Child size allocate: 0,0 ; 400, 200
And the window renders thusly:
GtkBin is an abstract single-child container, typically intended to decorate the child widget in some way, or change its visibility or size. Without some added value, a single-child container would be indistinguishable from the widget it contains and therefore not very useful.
Since GtkBin doesn't know what kind of decorations you will draw around the child, it expects you to implement your own size_allocate. A simple implementation is available in gtk_event_area_size_allocate, a more complex one in gtk_button_size_allocate.
This answer shows a minimal size_allocate implementation in PyGTK which should be straightforward to port to Vala. If you do anything more complex than that, you will need to also implement expose, and possibly other methods, but this will get you started.

Speech API (SAPI) floating point division by zero in C++ Builder on Windows 7

I use the following code for Text-To-Speech application controls for blind persons in C++ Builder (most likely similar example can be used in Delphi). Main form has KeyPreview property checked to enable key F11 preview to start speaking active (focused) control. The code as it is works but there are some problems. This example is in C++ Builder code but from what I've found, Delphi suffers from same problem and the solution I found is the same. If you have Delphi solution, feel free to post it, it is similar anyway.
#include <sapi.h>
#include <WTypes.h>
//---------------------------------------------------------------------------
// Speak text string (synchronous function)
//---------------------------------------------------------------------------
bool SpeakText(UnicodeString Text)
{
ISpVoice* pVoice = NULL;
if (FAILED(::CoInitialize(NULL))) return false;
Word Saved8087CW = Default8087CW; // Disable floating point division by zero exception caused by Speak
Set8087CW(0x133f);
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
if (SUCCEEDED(hr))
{
//pVoice->SpeakCompleteEvent()
//pVoice->SetSyncSpeakTimeout(1000);
hr = pVoice->Speak(WideString(Text).c_bstr(), SPF_DEFAULT, NULL);
pVoice->Release();
pVoice = NULL;
}
Set8087CW(Saved8087CW);
::CoUninitialize();
return true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
{
UnicodeString Speaker;
if (Key == VK_F11)
{
if (Screen->ActiveControl->InheritsFrom(__classid(TButton))) { Speaker += "Button, " + static_cast<TButton*>(Screen->ActiveControl)->Caption + "."; }
else if (Screen->ActiveControl->InheritsFrom(__classid(TEdit))) { Speaker += "Edit box, " + static_cast<TEdit*>(Screen->ActiveControl)->Text + "."; }
}
if (Speaker != "") SpeakText(Speaker);
}
//---------------------------------------------------------------------------
Problems:
pVoice->Speak causes Floating point division by zero if I don't override the exception using the Set8087CW function. This happens only on Windows 7 (possibly Vista and Windows 8 too) but not on Windows XP in the same program (compiled exe). Is there a solution without using Set8087CW? Removing these lines will cause the problem and exception. I have BCB2010.
Function is synchronous and won't shut up or return control to program until it finishes reading text. This is a problem for longer text. It also blocks program events. Is there a way to make it asynchronous or introduce an event to periodically check for F11 key status and if F11 is pressed again it stops reading and uninitializes object? For example poll every 300 ms (or after each word etc.) for key-press F11 and if pressed, stop speaking? Or run it threaded?
Does SAPI has memory leaks as some write on various sites?
Can above code use OleCheck instead of CoCreateInstance and CoUninitialize?
UPDATE for those looking for solution as suggested by Remy Lebeau:
SavedCW = Get8087CW();
Set8087CW(SavedCW | 0x4);
hr = pVoice->Speak(WideString(Text).c_bstr(), SPF_DEFAULT | SPF_ASYNC, NULL);
pVoice->WaitUntilDone(-1); // Waits until text is done... if F11 is pressed simply go out of scope and speech will stop
Set8087CW(SavedCW);
Also found detailed example in CodeRage 4 session: http://cc.embarcadero.com/item/27264
The error does occur in Vista as well. Masking floating point exceptions is the only solution.
To make Speak() run asynchronously, you need to include the SPF_ASYNC flag when calling it. If you need to detect when asynchronous speaking is finished, you can use ISpVoice::WaitUntilDone(), or call ISpVoice::SpeakCompleteEvent() and pass the returned HANDLE to one of the WaitFor...() family of functions, like WaitForSingleObject().
What kind of leaks do other sites talk about?
Not instead of, no. OleCheck() merely checks the value of an HRESULT value and throws an exception if it is an error value. You still have to call COM functions that return the actual HRESULT values in the first place. If anything, OleCheck() would be a replacement for SUCCEEDED() instead.
For what you are attempting, I would suggest the following approach instead:
struct s8087CW
{
Word Saved8087CW;
s8087CW(Word NewCW)
{
Saved8087CW = Default8087CW;
Set8087CW(NewCW);
// alternatively, the VCL documentation says to use SetExceptionMask() instead of Set8087CW() directly...
}
~s8087CW()
{
Set8087CW(Saved8087CW);
}
};
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
::CoInitialize(NULL);
}
//---------------------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
if (pVoice) pVoice->Release();
::CoUninitialize();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
{
if (Key == VK_F11)
{
TWinControl *Ctrl = Screen->ActiveControl;
if (Ctrl)
{
TButton *btn;
TEdit *edit;
if ((btn = dynamic_cast<TButton*>(Ctrl)) != NULL)
SpeakText("Button, " + btn->Caption);
else if ((edit = dynamic_cast<TEdit*>(Ctrl)) != NULL)
SpeakText("Edit box, " + edit->Text);
}
}
}
//---------------------------------------------------------------------------
ISpVoice* pVoice = NULL;
bool __fastcall TForm1::SpeakText(const String &Text)
{
s8087CW cw(0x133f);
if (!pVoice)
{
if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice)))
return false;
}
SPVOICESTATUS stat;
pVoice->GetStatus(&stat, NULL);
while (stat.dwRunningState == SPRS_IS_SPEAKING)
{
ULONG skipped;
pVoice->Skip(L"SENTENCE", 1000, &skipped);
pVoice->GetStatus(&stat, NULL);
}
return SUCCEEDED(pVoice->Speak(WideString(Text).c_bstr(), SPF_ASYNC, NULL));
}

Cocos2d-x schedule error

allyMonser is a CCSprite (Inheritance). When I use schedule, allyMonster is NULL in action(). But, When I call action() directly, allyMonster is Not NULL, it is normal.
When I run this code, the log shows:
1, 0x23ds566
2, 0xfffffff
I want know the reason 1, 0x23ds566 -> 2, 0xfffffff. Why does it change?
void AMS_Moving::runAction()
{
allyMonster->unscheduleAllSelectors();
allyMonster->stopAllActions();
allyMonster->schedule( schedule_selector( AMS_Moving::action ) );
CCLog("1. %x", allyMonster);
}
void AMS_Moving::action()
{
CCLog("2. %x", allyMonster);
...
...
}
I guess the reason is, when you run the scheduled function, it is not pointing to the function you want, but something else, because
void AMS_Moving::action()
is wrong. by default, all schedule function should take an input ccTime dt, which should be
void AMS_Moving::action(ccTime dt)

Create a Non-Database-Driven Lookup

Lots of references for creating lookups out there, but all seem to draw their values from a query.
I want to add a lookup to a field that will add items from a list of values that do not come from a table, query, or any other data source.
Such as from a string: "Bananas, Apples, Oranges"
..or a container ["Bananas", "Apples", "Oranges"]
Assume the string/container is a dynamic object. Drawing from an static enum is not a choice.
Is there a way to create lookups on the fly from something other than a data source?
Example code would be a great help, but I'll take hints as well.
There is the color picker.
Also in the Global you will find pickXxxx such as pickList.
There are others, pickUser, pickUserGroup etc.
Take a look on the implementation. I guess they build a temporary table then displays that. Tables are great!
Update:
To go on you own follow the rules.
For the advanced user, see also: Lookup form returning more than one value.
public void lookup()
{
SysTableLookup sysTableLookup;
TmpTableFieldLookup tmpTableFieldLookup;
Enumerator en;
List entitylist = new list(types::String);
entitylist.addend("Banana");
entitylist.addend("Apple");
en = entityList.getEnumerator();
while (en.moveNext())
{
tmpTableFieldLookup.TableName = en.current();
tmpTableFieldLookup.insert();
}
sysTableLookup = SysTableLookup::newParameters(tableNum(tmpTableFieldLookup), this);
sysTableLookup.addLookupfield(fieldNum(TmpTableFieldLookup, TableName));
//BP Deviation documented
sysTableLookup.parmTmpBuffer(tmpTableFieldLookup);
sysTableLookup.performFormLookup();
}
The above code helps in displaying strings as lookup.
I'm also guessing there's no way to perform a lookup without a table. I say that because a lookup is simply a form with one or more datasources that is displayed in a different way.
I've also blogged about this, so you can get some info on how to perform a lookup, even with a temporary table, here:
http://devexpp.blogspot.com.br/2012/02/dynamics-ax-custom-lookup.html
Example from global::PickEnumValue:
static int pickEnumValue(EnumId _enumId, boolean _omitZero = false)
{
Object formRun;
container names;
container values;
int i,value = -1,valueIndex;
str name;
#ResAppl
DictEnum dictEnum = new DictEnum(_enumId);
;
if (!dictEnum)
return -1;
for (i=1;i<=dictEnum.values();i++)
{
value = dictEnum.index2Value(i);
if (!(_omitZero && (value == 0)))
{
names += dictEnum.index2Label(i);
values += value;
}
}
formRun = classfactory.createPicklist();
formRun.init();
formRun.choices(names, #ImageClass);
formRun.caption(dictEnum.label());
formRun.run();
formRun.wait();
name = formRun.choice();
value = formRun.choiceInt();
if (value>=0) // the picklist form returns -1 if a choice has not been made
{
valueIndex = -1;
for (i=1;i<=conLen(names);i++)
{
if (name == conPeek(names,i))
{
valueIndex = i;
break;
}
}
if (valueIndex>=0)
return conPeek(values,valueIndex);
}
return value;
}
It isn't the most graceful solution, but this does work, and it doesn't override or modify any native AX 2012 objects:
Copy the sysLookup form from AX2009 (rename it) and import it into AX 2012.
We'll call mine myLookupFormCopy.
I did a find/replace of "sysLookup" in the XPO file to rename it.
Create this class method:
public static client void lookupList(FormStringControl _formStringControl, List _valueList, str _columnLabel = '')
{
Args args;
FormRun formRun;
;
if (_formStringControl && _valueList && _valueList.typeId() == Types::String)
{
args = new Args(formstr(myLookupFormCopy));
args.parmObject(_valueList);
args.parm(_columnLabel);
formRun = classFactory.formRunClass(args);
_formStringControl.performFormLookup(formRun);
}
}
In the lookup method for your string control, use:
public void lookup()
{
List valueList = new List(Types::String);
;
...build your valueList here...
MyClass::lookupList(this, valueList, "List Title");
super();
}