I have 2 problem on CCTransitionPageTurn. I target to work on a layer with topLayer and pageLayer. Where topLayer always on top and have menuItem to change page. And pageLayer be content with TurnPage effect.
Since I cannot add a CCScene over another CCScene (i.e. MainScene(CCScene) -> PageScene(CCScene) -> TopLayer(CCLayer) ). So, I think the design will be doing turn page effect on CCLayer (i.e. MainScene(CCScene) -> PageLayer(CCLayer) -> TopLayer(CCLayer) ). But this time CCTransitionPageTurn only support `CCScene. Any advice which is a better approach?
I see CCTransitionPageTurn is turning page at right-bottom corner (forward or backward). But how can I make it at left-bottom corner? Something like flip-X.
Just use CCPageTurn3D action on the layers, which is actually what drives the CCTransitionPageTurn.
Then, to make the page turn from another corner, just subclass CCPageTurn3D. Open the source file of CCPageTurn3D, and you'll see that it implements a single method. Copy that method to your new subclass, and alter it to make the action take place from any corner you like. If you can't accomplish this, just ask, and I'll help you figure it out.
(Pro Tip: when I was new to cocos2d, I'd always forget it's open source, so don't forget that! I figured out this answer by checking the cocos2d source code!)
Related
I'm creating a game using Cocos2d-x. I'm currently creating a gameover menu, in that menu I need to be able to switch to both my menuscene and my gamescene (When I say switch to gamescene I only really only mean "to restart" the game). But circular dependencies stop me from being able to do this.
MenuScene needs to be able to useGameScene::create() in order to switch to the gamescene and the gameover menu needs to be able to use both of GameScene::create() or its restart funtion and MenuScene::create() which is giving me circular dependency problems
I can't separate my gameover menu to it's own file as I still need the GameScene dependency and GameScene would need gameover.
I can't combine them as GameScene then needs to depend on MenuScene
So my question is: How do I alternate between two scenes in cocos2d-x c++.
I read somewhere about pushing and popnig scenes in Director, but I don't really understand how that works, or if I could use that for my purpose.
Thank you in advance!
EDIT:
Now that I think about it, could I not just push mMenuScene to Director before switching to GameScene? That should work if I understand that push/pop mechanic correctly.
I think you might have a misconception of how complex this is, using the way I provided below you can and should definitely split your game over scene into its own file.
The scene replace is easy enough, just use the code below:
Including your file:
#include "MainGameScene.h"
Creating and switching scenes in your onClickListener:
auto gameOverScene = GameOverScene::createScene();
// use code below for hard replace
Director::getInstance()->replaceScene(gameOverScene );
// or use code below for transition fade replace
Director::getInstance()->replaceScene(TransitionFade::create(1, gameOverScene , Color3B(255, 255, 255)));
As for the restart functionality. I usually provide a callback to my game over scene that I call when the restart button has been clicked. Not that I ever swap out my scene completely for a mobile game over scene, but I still do it the same way regardless. So lets do steps (This assumes you seperated your game over scene into it's own file named GameOverScene :) ).
Store a function pointer in your GameOverScene.h to your reset method in MainGameScene:
std::function<void()> _resetCallback;
Set your function pointer from the main game scene, before running with the GameOverScene.
auto gameOverScene = GameOverScene::createGameOverScene();
gameOverScene->setResetCallback(std::bind(&MainGameScene::reset, this));
When your reset button is clicked, call the _resetCallback
void GameOverScene::onResetClicked(Ref* sender)
{
_resetCallback();
}
This should provide you with all the functionality you need to set up a what you want as well as remove the circular dependency that you have. I have used this way many times before and it always works. Let me know if this solution works for you.
So I built a CCMenuItemImage with cocosbuilder in my cocosbuilder project and use it later in my project.
However, the responding method is never called.
Go up to the Document menu and make sure "JavaScript Controlled" is unchecked.
I was having a really hard time with this. CCBControlButtons called their selectors, but CCMenuItemImages didn't. Changed that setting and it's working now.
You didn't provide very much information that allows us to help. However, I recently did the same thing with my app so perhaps I can give you some ideas on where to look. First, is the CCMenu its own root node (separate file) or is it a child of a CCLayer in your CocosBuilder file?
In the first scenario, the CCMenu (and CCMenuItemImage) is a separate node file, then you would link it to your game layer code with the statement:
CCMenu *menu = [CCBReader nodeGraphFromFile:#"filename.ccbi" owner:self];
Then in the Cocosbuilder program, where you type in the name of the method the CCMenuItemImage links to, make sure you select "Owner" instead of "Document root".
The second scenario is where your Cocosbuilder file is a CCLayer and the CCMenu is a child of that layer, which might be a more likely scenario. If you successfully loaded your ccb file with
CCScene *scene = [CCBReader sceneWithNodeGraphFromFile:#"filename.ccbi"]; (might need to double-check that one, I am not at my XCode)
Then, in Cocosbuilder when you type in your CCMenuItemImage method name, select "Document Root" to link this to your code.
Then in your game layer's code, you should have the same method as you typed into Cocosbuilder. So if your game layer's method is:
-(void)pressedButton:(id)sender {
CCLOG(#"Button pressed!");
}
Then you need to have the same method
pressedButton:
linked to that button in Cocosbuilder.
Hope this helps.
well, that's happened to me too...
the solution is
first, u have to press enter after u've typed the selector field..
secondly, u have to publish (I do more than once).
for your info.... when u saved cocosbuilder project (cmd + s), u will not save the entire project... u'll only save current scene....
so, just in case u should save and publish on every scene u worry..
last tip (i don't know the different though), I chose document root (not owner ) :D
may this tips help you bro!
I have an MFC window which acts as a drop target. Depending on where the user drops certain types of data, I'd like to change the cursor shape to indicate what action will occur, only the actions are not move/copy/link, but more complex actions for which I have custom cursors.
Here's an example, if it helps. Imagine I have a window with 2 squares where the user can drop a file: in the first square, the file is e-mailed, in the second, the file is stored on Dropbox. I have one e-mail cursor and one dropbox cursor, and I'd like the cursor to change accordingly when the user hovers over the squares.
In MFC, you can create a COleDropSource object and override its GiveFeedback() method to do exactly this. However, this only works if you can pass that object to COleDataSource::DoDragDrop(), ie if you start the drag operation yourself. If the drag originates inside my application, this method works and I can get the desired cursor type. If the drag originates from Windows Explorer, I don't have a chance of providing my own COleDropSource object, and so I can't override the cursor shape.
Setting the cursor directly in OnDragOver() does not work, since Windows uses the result value of that method to change the cursor, so I only see the desired cursor for a fraction of a second before Windows changes it back to one of the standard shapes.
Is there any other way of solving this?
(This question is similar to this one, only I'm using MFC so the proposed solution there does not work.)
I'm afraid the source application is reponsible for the user feedback. You can provide hints to the source application via IDropTarget but it's the sources reponsiblity for using that feedback.
It makes sense really, the source application is the one that really knows what the data is and what can be done with it (think dragging a file from a zip file etc.).
In our application, we have a variable number of dockwidgets because some of them are added by plugins that are loaded at runtime. Not all dockwidgets need to be visible at the same time necessarily. This depends strongly on what the user is working on and what plugins are active.
However, if too many dockwidgets are added programmatically with addDockWidget(...), they start to overlap each other (not in terms of tabs, but in terms of content of one being painted on the area of a different one, which obviously looks broken).
The user can move the dockwidgets to dockareas that still have space left, but the layout/main window successfully prevents (untabbed) re-addition to the "crowded" dockarea.
We do allow tabbed docks to allow the user to arrange the dockwidgets a required, but we don't want to enable QMainWindow::ForceTabbedDocks since this would constrain the number of simultaneously visible dockwidgets too much (one per dock area).
How can I prevent this or better control how dockwidgets are added?
Not answering your question directly but it might be worthwhile to actually forget about Qt and actually think of how the whole interaction should work. What are the user expectations? What should actually happen if 10 different plugins become active? Should they be docked or should they be floating or should they become pin-able docking windows with initial state as a small button on the MainWindow edges? I think once you do that ground work and come up with user interface mock-ups, you can then start looking at Qt and figure out if Qt provides a direct way to develop that interface and if not what additional components you will need to develop to get that interface working.
From my own experience, I had developed a similar interface long back but in MFC. The way we did it was that some of the docked windows were deemed to be must have and they would come up as docked. Then there were a set of windows that didnt need to be visible always but should be quickly available and their initial state was as hidden pin-able dock window which meant they came up as buttons on the MainWindow edge. Finally there was a third set that was not required by the user always and could be called in from File->View Menu. Once the user made it visible, the user typically would assign it to one of the first two groups or keep it afloat. This whole configuration was saved in a config file and from there onwards whenever the plugin was loaded/became active the last used state of the associated docking window was used. It though involved quite a bit of extra work but the end result was to the satisfaction of all users.
Have you tryed setDockOptions(QMainWindow::AllowNestedDocks)? I can't test it now but it may help.
By default, QMainWindow::dockOptions is set to AnimatedDocks | AllowTabbedDocks so you would want something like
setDockOptions(QMainWindow::AllowNestedDocks | QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
EDIT:
If you are having too many problems, you may be going about this the wrong way. Instead of using docks, you may want to try using QMdiArea with QMdiWindow. This may not work for your program, but its something to think about.
This is the solution I tried:
I created in QTCreator an empty project with a window, a minimalistic menu labelled "New Dock" and a DockWidget named dockWidget
This is the triggered() handler for my menu item:
void MainWindow::on_actionNew_Dock_triggered()
{
QDockWidget* w = new QDockWidget("Demo", ui->dockWidget);
this->addDockWidget(Qt::LeftDockWidgetArea,w);
this->tabifyDockWidget(ui->dockWidget,w);
}
tabifyDockWidget(QDockWidget* first, QDockWidget* second) is a QMainWindow method that stacks the second dockwidget upon the first one. Hope it helps...
I am trying to create a tab-control that have the tab-buttons aligned from right-to-left, in Win32/c++. The WS_EX_LAYOUTRTL flag doesn't help me, as it mirrors the drawing completely both for the tab items and the tab page contents. The application itself handles the mirroring automatically (it's a cross platform UI solution), which is also a reason for us not to use WS_EX_LAYOUTRTL flag (we have mirroring implemented in a generic way for all UI frameworks/platforms).
One solution would be to override TCM_GETITEMRECT and TCM_HITTEST in the subclassed TabCtrls window procedure. This enables me to move the buttons allright, but the mouse events still acts on the positions that the control "knows" the buttons really are at (ie. mouseover on the first button invalidates the leftmost button - the coordinates are not mirrored).
So that seems to be a dead end for me.
Another possibility would be to insert padding before the first tab button, to push them all to the right edge. I haven't been able to figure out how to do that, though. Visual Studio sports this little dialog:
How did they put the buttons in front of the first tab page? Knowing this would enable me to solve this problem.
Update, solution:
The solution to my problem is to use the built-in RTL support. For this to work, the tab control must have both the WS_EX_LAYOUTRTL and WS_EX_NOINHERITLAYOUT flags. That will preserve the function of all existing drawing code while only the TabCtrl buttons are mirrored. I didn't realize that the ES_EX_NOINHERITLAYOUT flag goes on the parent (the TabCtrl), which is why I was looking for the workaround originally described.
For reference, I am still curious to have an answer to the original question, though.
If you take a look with a spy application you will see that it is not actually a normal windows tab-control but custom thing and the drawing is done by the parent window AFAIK:
Both Visual Studio and Office use a lot of custom controls, some of the features make their way into the common controls after a few years, some features stay private...