Better way to enable/disable a CCMenu object - cocos2d-iphone

* Assertion failure in -[CCTouchDispatcher forceAddHandler:array:], /libs/cocos2d/Platforms/iOS/CCTouchDispatcher.m:108
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Delegate already added to
touch dispatcher.'
The line causing it is
skillsMenu.isTouchEnabled = YES;
skillsMenu is just a CCMenu. I like to enable/disable it with the above line often.
The problem is, I don't know how to interpret this error properly - I have no clue why would setting this property cause such error.
Perhaps it was wrong to use that line in the first place. Is there not a better way to enable/disable a CCMenu?
cocos2d-iphone 1.0.1

isTouchEnabled registers/unregisters the touch handler for the object.
Registering and unregistering of touch handlers in the same step has caused problems in the past, although, in more recent versions, I believe this has been fixed.
In any case, if you simply want to temporarily enable/disable a menu, it will be less problematic to enable/disable the individual menu items:
-(void) modifyMenu:(CCMenu*) menu withEnabledValue:(BOOL) enabled
{
CCMenuItem *menuItem;
CCARRAY_FOREACH(menu.children, menuItem)
{
[menuItem setIsEnabled: enabled ];
}
}

CCMenu has an a .enabled property (setable), use that instead. The difference with isTouchEnabled is that the menu is not registered/deregistered from the touch dispatcher. Instead, when myMenu.enabled is false, the touches are simply ignored from the start in CCMenu's ccTouchBegan delegate method. This is cleaner, and avoids the trap of playing with isTouchEnabled (that is a property of the CCLayer class, which CCMenu extends).

Related

Qt wizard back button Ui issue

I'm new with Qt and I'm making a little application. I've do it with QWizard and QWizardPages.
I Have added 2 CustomButtons to the wizard so it has 5 buttons down: ButA, ButB, Back, Next/Finish, and Cancel.
ButA and ButB don't have to appear in all WizardPages. Eg:
WP0: just ButB
WP1: ButA and ButB
To do that, I have:
void WP0::initializePage()
{
wizard()->button(QWizard::CustomButton1)->setVisible(false);
}
With that when the app starts, you can't see butA. BUT if you go to the next page (where you see ButA and ButB) and then you click on BackButton, then you see ButA in WP0.
I supose that then you click on BackButton there is no call to WP0::initializePage() so my question is: how or where should I call that wizard()->button(QWizard::CustomButton1)->setVisible(false);
to never see ButA on WP0 ? Or what should I do?
I don't know if I understand your question completely. your description is kind of complicated. I think you should try button's events. It means you should call this function in press event or something like that and it's better that you define a boolean variable for true or false and call it by reference. I think this should solve your problem.

Do Raphael sets accept event handler?

Do Raphael sets accept event handler? When I set an event handler on a raphael set, it seems that it is instead assigned on each of the Raphael shapes inside the set and not on the set itself as you can see here if you try to click the set:
http://jsbin.com/aponen/3/edit
I'm not interested in various hacks such as chaining elements inside a set with the set itself via custom attributes or similar approaches.
Thanks
Yes, the event handler is applied to each object individually -- Raphael does not make use of the <g> element of SVG. However, you can fix your issue here with a few keystrokes:
set.push(rect);
set.push(circle);
set.attr({'fill': 'yellow'});
set.click(function(evt) {
//old
this.attr({'fill': 'red'});
//new
set.attr({'fill': 'red'});
});
The biggest difference in the way it works and the way you thought it might work is the meaning of "this" inside the handler. Changing it to "set" will fix that right up.
UPDATE, Jan. 26, 2013
Per comments, you could also attach the set to the children of the set with one line, using Raphael's "data" method:
set.push(rect);
set.push(circle);
set.data('myset', set);
set.attr({'fill': 'yellow'});
set.click(function(evt) {
this.data('myset').attr({'fill': 'red'});
});
I don't believe there is a native way to access the set from children, but I could be missing it.

Can't hide CCMenuItem when using In-App-Purchase

This time I would like to ask if anybody had such strange problem with disabling button (CCMenuItemImage) in cocos2d. I have in-App-Purchase connected and when purchase is done following function is triggered
- (void)productPurchased:(NSNotification *)notification {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
waitingForStore = FALSE;
[loop setVisible:FALSE];
[buyItem setVisible:FALSE];
// setAccessibilityElementsHidden:YES];
NSString *productIdentifier = (NSString *) notification.object;
NSLog(#"Purchased: %#", productIdentifier);
}
waitingForStore = FALSE;
[loop setVisible:FALSE];
This two operation works fine, but the problem is with the third one. I would like to make the 'BUY' button invisible.
[buyItem setVisible:FALSE];
This one does not do anything at this place( the button is still visible and accessible). If I will use it on the other part of code it works just fine- but here .... not. Trying to change position doesn't work neither.
Could it be connected with inAppPurchase thread or something?
I have found the reason. It was my mistake when making two calls to the apple store and creating two buttons. :) So, it could be closed.
I understand your problem. If you you want to disable menuitem you can set menuitem.isEnabled property.
And if you want to hide button, you can set property menuitem.visible = NO.
If this is not working for you can also use [menuitem runaction:[CCFadeOut actionWithDuration:1.0f] ]. Then use FadeIn as per your requirement.
This is alternative option for you.

Weird bug in Qt application

In my application, I have my re-implemented QGraphicsView checking for a mouseReleaseEvent(), and then telling the item at the position the mouse is at to handle the event.
The QGraphicsItem for my view is made up of two other QGraphicsItems, and I check which one of the two is being clicked on (or rather having the button released on), and handle the respective events.
In my Widget's constructor, I set one of the items as selected by default, using the same methods I used when the items detect a release.
When I debugged, I found that for the LabelItem, select is called without a problem from the constructor (and the result is clear when I first start the application). But, when I click on the items, the application terminates. I saw that I was getting into the select function, but not leaving it. So the problem is here.
Which is very weird, because the select function is just a single line setter.
void LabelItem::select()
{
selected = true;
}
This is the mouseReleaseEvent;
void LayerView::mouseReleaseEvent(QMouseEvent *event)
{
LayerItem *l;
if(event->button() == Qt::LeftButton)
{
l = (LayerItem *) itemAt(event->pos());
if(l->inLabel(event->pos()))
{ //No problem upto this point, if label is clicked on
l->setSelection(true); //in setSelection, I call select() or unselect() of LabelItem,
//which is a child of LayerItem, and the problem is there.
//In the constructor for my main widget, I use setSelection
//for the bottom most LayerItem, and have no issues.
emit selected(l->getId());
}
else if(l->inCheckBox(event->pos()))
{
bool t = l->toggleCheckState();
emit toggled(l->getId(), t);
}
}
}
When I commented the line out in the function, I had no errors. I have not debugged for the other QGraphicsItem, CheckBoxItem, but the application terminates for its events as well. I think the problem might be related, so I'm concentrating on select, for now.
I have absolutely no clue as to what could have caused this and why this is happening. From my past experience, I'm pretty sure it's something simple which I'm stupidly not thinking of, but I can't figure out what.
Help would really be appreciated.
If the LabelItem is on top of the LayerItem, itemAt will most likely return the LabelItem because it is the topmost item under the mouse. Unless the LabelItem is set to not accept any mouse button with l->setAcceptedMouseButtons(0).
Try to use qgraphicsitem_cast to test the type of the item. Each derived class must redefine QGraphicsItem::type() to return a distinct value for the cast function to be able to identify the type.
You also could handle the clicks in the items themselves by redefining their QGraphicsItem::mouseReleaseEvent() method, it would remove the need for the evil cast, but you have to remove the function LayerView::mouseReleaseEvent() or at least recall the base class implementation, QGraphicsView::mouseReleaseEvent(), to allow the item(s) to receive the event.
I have seen these odd behaviours: It was mostly binary incompatibility - the c++ side looks correct, and the crash just does not make sense. As you stated: In your code the "selected" variable cannot be the cause. Do you might have changed the declaration and forgot the recompile all linked objects. Just clean and recompile all object files. Worked for me in 99% of the cases.

NSArray and Sandbox Question

I don't quite understand, but basically I am trying to click a button and have a value added to my NSMutableArray myArray which is a property. I thought my method that would be called when a button is pressed would be something like:
- (IBAction)addInterval {
NSString *string = #"test";
[self.myArray addObject:string];
}
But I don't understand why this doesn't work?
Also, is Wifi, volume control, and bluetooth all not in our sandbox to be used?thanks.
In general, in order for your IBAction to get called, it must have a parameter, e.g.
-(IBAction) addInterval: (id)sender {
}
Also, make sure you have bound the action to the button correctly inside the UI Designer - you should see it as an action outlet for the button.
To make sure your method is being called, stick a line in the method like:
NSLog(#"Called addInterval action");
Bluetooth will not work in sandbox, WiFi will work in the sense that the network connection will function, and the reachability example should help you here.
Could be one of a few things but the classic problem here is forgetting to connect the button to the action in interface builder. Have you checked that?
I'm also assuming that you've synthesized the myArray property so that you can use the dot notation.