Greetings Community of experts, I am trying to synchronize the movement and zoom in two windows of AutoCAD models, that is, in two different planes open .dwg divided into two windows one active and the other inactive synchronize the zoom (scroll + or -) or the movement (PAN) from the active window to the inactive one (In model with two open planes in AutoCAD M3D -> SYSWINDOWS :: tile Vertical), I was researching and I found this code that does what I want but only with one plane, the problem is that I can not make it work in VS2019 c ++, I get an error in the lines with "WinCallBack" indicating that BOOL cannot become a constant, I appreciate your help in advance.
#include "StdAfx.h"
#include "resource.h"
#pragma warning( disable : 4278 )
#include <windows.h>
#include <stdio.h>
#include "acedCmdNF.h"
#include "AcMyEditorReactor.h"
#include "AcMyInputContextReactor.h"
// Viewchanged notification is not received during a pan or zoom using mouse wheel.
// So identify those using WM messages.
BOOL WinCallBack(MSG *pMsg)
{
if( pMsg->message == WM_VSCROLL ||
pMsg->message == WM_HSCROLL ||
pMsg->message == WM_MOUSEWHEEL ||
pMsg->message == WM_MBUTTONUP)
{
// Sync the modelspace viewports
acDocManager->sendStringToExecute(acDocManager->mdiActiveDocument(), ACRX_T("SyncVTR "), false, true, false);
}
return FALSE;
}
class CMyTest1App : public AcRxArxApp
{
private:
AcMyEditorReactor *pEditorReactor;
AcMyInputContextReactor *pInputContextReactor;
public:
CMyTest1App () : AcRxArxApp ()
{
}
virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt)
{
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
// Editor reactor to receive to ViewChanged notification
pEditorReactor = new AcMyEditorReactor(true);
// InputContext reactor to receive quiescent state change notification
pInputContextReactor = new AcMyInputContextReactor();
// Viewchanged notification is not received during a pan or zoom using mouse wheel.
// So identify those using WM messages.
acedRegisterFilterWinMsg(WinCallBack);
return (retCode);
}
virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt)
{
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
// cleanup
if(pEditorReactor)
{
delete pEditorReactor;
pEditorReactor = NULL;
}
if(pInputContextReactor)
{
delete pInputContextReactor;
pInputContextReactor = NULL;
}
acedRemoveFilterWinMsg(WinCallBack);
return (retCode);
}
virtual AcRx::AppRetCode On_kLoadDwgMsg (void *pkt)
{
AcRx::AppRetCode retCode =AcRxArxApp::On_kLoadDwgMsg (pkt) ;
return (retCode) ;
}
virtual void RegisterServerComponents ()
{
}
// Command to sync the model space viewport parameters
static void AdskMyTestSyncVTR()
{
// Get the VTR updated
acedVports2VportTableRecords();
// We will update the other VTR only if view parameters change
Adesk::Boolean updateNeeded = Adesk::kFalse;
Acad::ErrorStatus es;
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
AcApDocument *pDoc = acDocManager->document(pDb);
if( pDoc == NULL )
return;
es = acDocManager->lockDocument(pDoc);
// This code at present can only deal with 2 Modelspace viewports split vertically in half
if(pDb->tilemode() == Adesk::kFalse)
{
struct resbuf rb;
if(ads_getvar(_T("cvport"), &rb) != RTNORM)
{
acutPrintf(_T("\nError using ads_getvar().\n"));
return;
}
if(rb.resval.rint == 1)
{
return; // Can only work with model space viewports.
}
}
AcDbViewportTable *pVT = NULL;
pDb->getViewportTable(pVT,AcDb::kForRead);
// Identify the left and right modelspace viewports
AcDbViewportTableRecord *pLeftVTR = NULL;
AcDbViewportTableRecord *pRightVTR = NULL;
AcDbViewportTableIterator *pIter = NULL;
es = pVT->newIterator(pIter);
if(es == Acad::eOk)
{
for (;!pIter->done();pIter->step())
{
AcDbViewportTableRecord *pVTR = NULL;
es = pIter->getRecord(pVTR, AcDb::kForRead);
if(es == Acad::eOk)
{
AcGePoint2d ll = pVTR->lowerLeftCorner();
AcGePoint2d ur = pVTR->upperRightCorner();
if(ll.isEqualTo(AcGePoint2d(0, 0)))
{// Left modelspace viewport
pLeftVTR = pVTR;
}
else if(ur.isEqualTo(AcGePoint2d(1.0, 1.0)))
{// Right modelspace viewport
pRightVTR = pVTR;
}
else
pVTR->close();
}
}
// If for some reason, we did not have two modelspace viewports,
// lets stop here.
if(pLeftVTR == NULL)
{
if(pRightVTR != NULL)
pRightVTR->close();
return;
}
if(pRightVTR == NULL)
{
if(pLeftVTR != NULL)
pLeftVTR->close();
return;
}
// Ensure that the two viewports are split vertically in half.
// If not, the view parameters when applied from one to another
// may not apply directly using this code.
// If the viewports were resized manually, set them right.
AcGePoint2d ll1 = pLeftVTR->lowerLeftCorner();
AcGePoint2d ur1 = pLeftVTR->upperRightCorner();
AcGePoint2d ll2 = pRightVTR->lowerLeftCorner();
AcGePoint2d ur2 = pRightVTR->upperRightCorner();
if(ll1.isEqualTo(AcGePoint2d(0.0, 0.0)) == false)
{
if(! pLeftVTR->isWriteEnabled())
pLeftVTR->upgradeOpen();
pLeftVTR->setLowerLeftCorner(AcGePoint2d(0.0, 0.0));
}
if(ur1.isEqualTo(AcGePoint2d(0.5, 1.0)) == false)
{
if(! pLeftVTR->isWriteEnabled())
pLeftVTR->upgradeOpen();
pLeftVTR->setUpperRightCorner(AcGePoint2d(0.5, 1.0));
}
if(ll2.isEqualTo(AcGePoint2d(0.5, 0.0)) == false)
{
if(! pRightVTR->isWriteEnabled())
pRightVTR->upgradeOpen();
pRightVTR->setLowerLeftCorner(AcGePoint2d(0.5, 0.0));
}
if(ur2.isEqualTo(AcGePoint2d(1.0, 1.0)) == false)
{
if(! pRightVTR->isWriteEnabled())
pRightVTR->upgradeOpen();
pRightVTR->setUpperRightCorner(AcGePoint2d(1.0, 1.0));
}
// Get the active model space viewport
struct resbuf res;
acedGetVar(L"CVPORT", &res);
short vpnumber = res.resval.rint;
// Identify the model space viewports from/to which settings will be copied
// The active modelspace viewport is the viewport from which settings will be copied
AcDbViewportTableRecord *pFromVTR = NULL;
AcDbViewportTableRecord *pToVTR = NULL;
if(pLeftVTR->number() == vpnumber)
{
pFromVTR = pLeftVTR;
pToVTR = pRightVTR;
}
if(pRightVTR->number() == vpnumber)
{
pFromVTR = pRightVTR;
pToVTR = pLeftVTR;
}
// Sorry, we did not identify the active viewport
// from which settings need to be copied.
if(pFromVTR == NULL || pToVTR == NULL)
return;
// Copy the VTR settings from one modelspace viewport to another
// only if they are different. We will use a tolerance to ensure
// very small differences do not get us in a soup. I meant loop :)
AcGeTol newTol;
newTol.setEqualPoint (0.00001);
newTol.setEqualVector(0.00001);
// ViewDirection
AcGeVector3d fromViewDir = pFromVTR->viewDirection();
AcGeVector3d toViewDir = pToVTR->viewDirection();
if(pFromVTR->viewDirection().isEqualTo(pToVTR->viewDirection(), newTol) == false)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setViewDirection(pFromVTR->viewDirection());
updateNeeded = Adesk::kTrue;
}
// ViewTwist
if(abs(pFromVTR->viewTwist() - pToVTR->viewTwist()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setViewTwist(pFromVTR->viewTwist());
updateNeeded = Adesk::kTrue;
}
// Target
if(pFromVTR->target().isEqualTo(pToVTR->target(), newTol) == false)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setTarget(pFromVTR->target());
updateNeeded = Adesk::kTrue;
}
// BackClipEnabled
if(pFromVTR->backClipEnabled() != pToVTR->backClipEnabled())
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setBackClipEnabled(pFromVTR->backClipEnabled());
updateNeeded = Adesk::kTrue;
}
// BackClipDistance
if(abs(pFromVTR->backClipDistance() - pToVTR->backClipDistance()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setBackClipDistance(pFromVTR->backClipDistance());
updateNeeded = Adesk::kTrue;
}
// FrontClipEnabled
if(pFromVTR->frontClipEnabled() != pToVTR->frontClipEnabled())
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setFrontClipEnabled(pFromVTR->frontClipEnabled());
updateNeeded = Adesk::kTrue;
}
// FrontClipDistance
if(abs(pFromVTR->frontClipDistance() - pToVTR->frontClipDistance()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setFrontClipDistance(pFromVTR->frontClipDistance());
updateNeeded = Adesk::kTrue;
}
// Elevation
if(abs(pFromVTR->elevation() - pToVTR->elevation()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setElevation(pFromVTR->elevation());
updateNeeded = Adesk::kTrue;
}
// centerPoint
if(pFromVTR->centerPoint().isEqualTo(pToVTR->centerPoint(), newTol) == false)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setCenterPoint(pFromVTR->centerPoint());
updateNeeded = Adesk::kTrue;
}
// Height
if(abs(pFromVTR->height() - pToVTR->height()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setHeight(pFromVTR->height());
updateNeeded = Adesk::kTrue;
}
// Width
if(abs(pFromVTR->width() - pToVTR->width()) > 0.01)
{
if(! pToVTR->isWriteEnabled())
pToVTR->upgradeOpen();
pToVTR->setWidth(pFromVTR->width());
updateNeeded = Adesk::kTrue;
}
// Done with the VTR
pLeftVTR->close();
pRightVTR->close();
delete pIter;
}
es = pVT->close();
es = acDocManager->unlockDocument(pDoc);
// Update the Vports if we did change any of the VTR parameters
if(updateNeeded)
{
acedVportTableRecords2Vports();
}
}
};
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CMyTest1App)
ACED_ARXCOMMAND_ENTRY_AUTO(CMyTest1App, AdskMyTest, SyncVTR, SyncVTR, ACRX_CMD_MODAL, NULL)
https://adndevblog.typepad.com/autocad/2014/07/synchronizing-model-space-viewports.html
I found two apps that solve the question in question, DWGsync (free and compatible until autocad 2021) https://apps.autodesk.com/ACD/es/Detail/Index?id=2788892389049910944&appLang=en&os=Win32_64 and Drawing Sync (licensed and compatible autocad 2018) https://apps.autodesk.com/ACD/en/Detail/Index?id=2152736212918385179&appLang=en&os=Win32_64
Related
I'm trying to draw the cursor position, with a square, when mouse moving.
I'm using SharpGL and the OpenGLControl, but there is a delay between cursor arrow and the drawn square.
On MouseMove event I store a square centered in the mouse position (mapped in _pointCursor that is a list of vertex), then in the Draw event of the control, I actually draw it:
private void DrawPointers(OpenGL gl)
{
if (_pointCursor == null)
return;
SetColor(gl, Color.LightGray);
gl.Begin(OpenGL.GL_LINE_LOOP);
foreach (var item in _pointCursor)
{
gl.Vertex(item.X, item.Y, item.Z);
}
gl.End();
}
Is there any trick,configuration or strategy in order to avoid this delay?
I think the problem is how everything is drawn. If I remove DrawAxis() and DrawGrid() there is not more delay. In this case it can depend on my drawing strategy, I use a lot of gl.Begin() and gl.End().
Another thing is that DrawGrid() and DrawAxis() continues to draw a fixed background. I don't use shaders.
This is the code:
private void MouseDrawCursors(XglVertex v)
{
if ((_view == ViewType._2D) && ((_status == EditStatus.Idle) || (_status == EditStatus.DrawLine)))
{
_pointCursor = v.DrawSquare(0.1f); //Return a list of vertex
_pointCross = v.DrawCross(20); //Return a list of vertex
}
}
private void openGLControl1_MouseMove(object sender, MouseEventArgs e)
{
if (_gl == null)
return;
double worldX = 0;
double worldY = 0;
double worldZ = 0;
_gl.GetWorldCoords(e.X, e.Y, ref worldX, ref worldY, ref worldZ);
XglVertex v = new XglVertex((float)worldX, (float)worldY, (float)worldZ);
MouseDrawCursors(v);
}
private void Draw()
{
if (_gl == null)
return;
//Enable 3D
if (_view == ViewType._2D)
_gl.Disable(OpenGL.GL_DEPTH_TEST);
else
_gl.Enable(OpenGL.GL_DEPTH_TEST);
_gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
//Enable Aplpha
_gl.Enable(OpenGL.GL_BLEND);
_gl.BlendFunc(OpenGL.GL_SRC_ALPHA, OpenGL.GL_ONE_MINUS_SRC_ALPHA);
#region Projection
_gl.MatrixMode(OpenGL.GL_MODELVIEW);
_gl.LoadIdentity();
_gl.Scale(Params.ScaleFactor, Params.ScaleFactor, Params.ScaleFactor);
_gl.Translate(Params.X, Params.Y, Params.Z);
if (_status == EditStatus.Rotate)
_arc_ball_effect.ArcBall.TransformMatrix(_gl);
else
_gl.Rotate(Params.XAngle, Params.YAngle, Params.ZAngle);
_gl.MatrixMode(OpenGL.GL_PROJECTION); //matrice di proiezione
_gl.LoadIdentity(); //ripristina matrice identità
float worldWidth = Params.Width;
float worldHeight = Params.Height;
float near = Params.Near;
float far = Params.Far;
_gl.Viewport(0, 0, openGLControl1.Width, openGLControl1.Height);
if (_aspect_ratio >= 1.0)
_gl.Ortho(0, (worldWidth * _aspect_ratio), 0, worldHeight, near, far);
else
_gl.Ortho(0, worldWidth, 0, (worldHeight / _aspect_ratio), near, far);
#endregion
if (Params.ShowPointers)
DrawPointers(_gl);
if (Params.ShowAxis)
DrawAxis(_gl);
if (Params.ShowGrid)
DrawGrid(_gl);
_gl.Flush();
}
private void DrawPointers(OpenGL gl)
{
if (_pointCursor == null)
return;
if (_pointCursor.Count == 0)
return;
SetColor(gl, Color.LightGray);
gl.Begin(OpenGL.GL_LINE_LOOP);
foreach (var item in _pointCursor)
{
gl.Vertex(item.X, item.Y, item.Z);
}
gl.End();
if (_pointCross == null)
return;
SetColor(gl, Color.LightGreen);
gl.Begin(OpenGL.GL_LINES);
foreach (var item in _pointCross)
{
gl.Vertex(item.X, item.Y, item.Z);
}
gl.End();
}
private void DrawGrid(OpenGL gl)
{
if (_gl == null)
return;
if (_grid == null)
return;
if (!Params.ShowGrid)
return;
SetColor(gl, _grid.GridColor);
if (_grid.EnableXY)
{
gl.Begin(OpenGL.GL_POINTS);
foreach (var p in _grid.XY)
{
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
if (_grid.EnableYZ)
{
gl.Begin(OpenGL.GL_POINTS);
foreach (var p in _grid.YZ)
{
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
if (_grid.EnableZX)
{
gl.Begin(OpenGL.GL_POINTS);
foreach (var p in _grid.ZX)
{
gl.Vertex(p.X, p.Y, p.Z);
}
gl.End();
}
}
I added xdg-shell v5 to app to draw windows. When I send set_fullscreen or set_maximize commands, I see correctly set window states and correct sizes in configure event but nothing is happens.
My configure event function:
static void
xdg_surface_handle_configure(void *data,
struct xdg_surface *xdg_surface,
int32_t width,
int32_t height,
struct wl_array *states,
uint32_t serial) {
printf("Configure event got, width: %d, height: %d\n", width, height);
VirtIOGPU *g = (VirtIOGPU*) data;
g->window_state.activated = g->window_state.fullscreen =
g->window_state.maximized = g->window_state.resizing = false;
uint32_t *state;
wl_array_for_each(state, states) {
if(*state == XDG_SURFACE_STATE_MAXIMIZED) {
printf("Surface state: XDG_SURFACE_STATE_MAXIMIZED\n");
g->window_state.maximized = true;
} else if(*state == XDG_SURFACE_STATE_FULLSCREEN) {
printf("Surface state: XDG_SURFACE_STATE_FULLSCREEN\n");
g->window_state.fullscreen = true;
} else if(*state == XDG_SURFACE_STATE_RESIZING) {
printf("Surface state: XDG_SURFACE_STATE_RESIZING\n");
g->window_state.resizing = true;
} else if(*state == XDG_SURFACE_STATE_ACTIVATED) {
printf("Surface state: XDG_SURFACE_STATE_ACTIVATED\n");
g->window_state.activated = true;
}
}
if (width > 0 && height > 0) {
g->prev_width = g->width;
g->prev_height = g->height;
g->width = width;
g->height = height;
} else {
g->width = g->prev_width;
g->height = g->prev_height;
}
xdg_surface_ack_configure(xdg_surface, serial);
wl_surface_damage(g->surface, 0, 0, g->width, g->height);
wl_surface_commit(g->surface);
wl_display_dispatch_pending(g->display);
wl_display_flush(g->display);
}
So, how to see maximized window after I sent set_maximized?
Is it possible to unminimize minimized window programmatically (now by Super+Tab)?
Your client probably needs to attach and commit a new buffer with the correct dimensions to the surface. The compositor has done everything it's supposed to do, and expects your client to resize.
I'am trying to build a simple game with a ball and target,
and I want to increse the score when the ball touch the target,
but the callback "onContactBegin" doesnt invoke.
There is a target("goal") in the button of the screen, and when the user touch the screen the ball created and start moving.
#include <string>
#include "HelloWorldScene.h"
#define COCOS2D_DEBUG 1
USING_NS_CC;
enum class PhysicsCategory {
None = 0,
Goal = (1 << 0),
Ball = (1 << 1),
All = PhysicsCategory::Goal | PhysicsCategory::Ball
};
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
return scene;
}
bool HelloWorld::init()
{
CCLOG("Init");
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
height = visibleSize.height;
width = visibleSize.width;
score = 0;
m_score_label = Label::createWithTTF(Itos(score), "fonts/Marker Felt.ttf", 24);
auto vSize = Director::getInstance()->getVisibleSize();
m_score_label->setPosition(Point(origin.x + vSize.width/2,
origin.y + vSize.height - m_score_label->getContentSize().height));
this->addChild(m_score_label, 1);
goal = Sprite::create("images.jpg");
goal->setPosition(Point((visibleSize.width / 2) + origin.x , (visibleSize.height / 6) + origin.y));
auto goalSize = goal->getContentSize();
auto physicsBody = PhysicsBody::createBox(Size(goalSize.width , goalSize.height),
PhysicsMaterial(0.1f, 1.0f, 0.0f));
physicsBody->setCategoryBitmask((int)PhysicsCategory::Goal);
physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
physicsBody->setContactTestBitmask((int)PhysicsCategory::Ball);
goal->setPhysicsBody(physicsBody);
mySprite = Sprite::create("CloseNormal.png");
mySprite->setPosition(Point((visibleSize.width / 2) + origin.x , (visibleSize.height / 2) + origin.y));
this->addChild(mySprite);
this->addChild(goal);
CCScaleBy* action = CCScaleBy::create(3,5);
mySprite->runAction(action);
auto eventListener = EventListenerTouchOneByOne::create();
eventListener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(eventListener, this);
auto contactListener = EventListenerPhysicsContact::create();
contactListener->onContactBegin = CC_CALLBACK_1(HelloWorld::onContactBegan, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(contactListener, this);
return true;
}
bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event) {
cocos2d::Sprite * sp = Sprite::create("CloseNormal.png");
sp->setPosition(Point(touch->getLocation().x , touch->getLocation().y));
MoveTo *action = MoveTo::create(2, Point(width ,0) );
auto ballSize = sp->getContentSize();
auto physicsBody = PhysicsBody::createBox(Size(ballSize.width , ballSize.height),
PhysicsMaterial(0.1f, 1.0f, 0.0f));
physicsBody->setDynamic(true);
physicsBody->setCategoryBitmask((int)PhysicsCategory::Ball);
physicsBody->setCollisionBitmask((int)PhysicsCategory::None);
physicsBody->setContactTestBitmask((int)PhysicsCategory::Goal);
sp->setPhysicsBody(physicsBody);
sp->runAction( action );
this->addChild(sp);
return true;
}
void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif
Director::getInstance()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
bool HelloWorld::onContactBegan(PhysicsContact &contact)
{
CCLOG("onContactBegan");
auto nodeA = contact.getShapeA()->getBody()->getNode();
auto nodeB = contact.getShapeB()->getBody()->getNode();
nodeA->removeFromParent();
nodeB->removeFromParent();
++score ;
m_score_label->setString(Itos(score));
return true;
}
std::string HelloWorld::Itos ( int num )
{
std::ostringstream ss;
ss << num;
return ss.str();
}
HelloWorld.cpp
Scene* HelloWorld::createScene() {
auto scene = Scene::createWithPhysics();
auto layer = HelloWorld::create();
layer->setPhysicsWorld(scene->getPhysicsWorld());
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
scene->addChild(layer);
return scene;
}
bool GameScene::didBeginContact(cocos2d::PhysicsContact &contact) {
PhysicsBody *bodyA = contact.getShapeA()->getBody();
PhysicsBody *bodyB = contact.getShapeB()->getBody();
}
HelloWorld.h
cocos2d::PhysicsWorld *physicsWorld;
void setPhysicsWorld(cocos2d::PhysicsWorld *withWorld) {physicsWorld = withWorld;};
bool didBeginContact(cocos2d::PhysicsContact &contact);
After collision using listener one, sprite1 should be destroyed and other sprite2 will jump. I destroy sprite1 but sprite2 is not jumping after collision with sprite1. Here is my code:
Update(float dt) {
if(collisionOccurs == 1)
{
CCJumpTo * myJump = CCJumpTo::create(1, ccp(winSize.width/6,winSize.height/8),winSize.height/2 ,1);
Sprite2->runAction(myJump);
collisionOccurs = 0;
if(Sprite1 != NULL && BodyofSprite1 != NULL)
{
BodyofSprite1->SetActive(false);
Sprite1->removeFromParentAndCleanup(true);
}
}
}
I'm a beginner that just followed cocos2d-x's native tutorials and I am faced with a huge wall!
This is my error:
>c:\cocos2d-2.0-x-2.0.3\cocos2dsimplegame\classes\helloworldscene.cpp(86): error C2440: 'type cast' : cannot convert from 'void (__thiscall HelloWorld::* )(cocos2d::CCTime)' to 'cocos2d::SEL_SCHEDULE'
>Pointers to members have different representations; cannot cast between them
My cpp file:
#include "HelloWorldScene.h"
using namespace cocos2d;
CCScene* HelloWorld::scene()
{
CCScene * scene = NULL;
do
{
// 'scene' is an autorelease object
scene = CCScene::create();
CC_BREAK_IF(! scene);
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
CC_BREAK_IF(! layer);
// add layer as a child to scene
scene->addChild(layer);
} while (0);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
bool bRet = false;
_targets = CCArray::create();
_projectiles = CCArray::create();
do {
////////////////////
// super init first
////////////////////
if ( !CCLayerColor::initWithColor( ccc4(255, 255, 255, 255) ) )
{
return false;
}
////////////////////
// add your codes below..
////////////////////
// 1. Add a menu item with "X" image, which is clicked to quit the program.
// Create a "close" menu item with close icon, it's an auto release object.
CCMenuItemImage *pCloseItem = CCMenuItemImage::itemWithNormalImage(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(HelloWorld::menuCloseCallback));
CC_BREAK_IF(! pCloseItem);
// Place the menu item bottom-right conner.
pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
//Create a menu with the "close" menu item, it's an auto release object.
CCMenu* pMenu = CCMenu::menuWithItems(pCloseItem, NULL);
pMenu->setPosition(CCPointZero);
CC_BREAK_IF(! pMenu);
//Add the menu to HelloWorld layer as a child layer.
this->addChild(pMenu, 1);
//////////////////////
// 2. add your codes below...
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSprite *player = CCSprite::spriteWithFile("Player.png", CCRectMake(0, 0, 27, 40));
player->setPosition(ccp(player->getContentSize().width/2, winSize.height/2));
this->addChild(player);
bRet = true;
} while (0);
// Call game logic about every second
this->schedule( schedule_selector(HelloWorld::gameLogic), 1.0);
// You can shoot the bullet
this->setTouchEnabled(true);
this->schedule( schedule_selector(HelloWorld::update) );
return bRet;
}
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
// "close" menu item clicked
CCDirector::sharedDirector()->end();
}
void HelloWorld::addTarget()
{
CCSprite *target = CCSprite::spriteWithFile("Target.png", CCRectMake(0, 0, 27, 40));
// Determine where to spawn the target along the Y axis
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
int minY = target->getContentSize().height/2;
int maxY = winSize.height - target->getContentSize().height/2;
int rangeY = maxY - minY;
// srand( TimGetTicks() );
int actualY = ( rand() % rangeY ) + minY;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated
target->setPosition( ccp(winSize.width + (target->getContentSize().width/2), actualY) );
this->addChild(target);
// Determine speed of the target
int minDuration = (int)2.0;
int maxDuration = (int)4.0;
int rangeDuration = maxDuration - minDuration;
// srand( TimGetTicks() );
int actualDuration = ( rand() % rangeDuration ) + minDuration;
// Create the actions
CCFiniteTimeAction* actionMove = CCMoveTo::actionWithDuration( (float)actualDuration, ccp(0 - target->getContentSize().width/2, actualY) );
CCFiniteTimeAction* actionMoveDone = CCCallFuncN::actionWithTarget( this, callfuncN_selector(HelloWorld::spriteMoveFinished) );
target->runAction( CCSequence::actions( actionMove, actionMoveDone, NULL) );
// Add to targets array
target->setTag(1);
_targets->addObject(target);
}
void HelloWorld::spriteMoveFinished(CCNode* sender)
{
CCSprite *sprite = (CCSprite *)sender;
this->removeChild(sprite, true);
if (sprite->getTag() == 1) // target
{
_targets->removeObject(sprite);
}
else if (sprite->getTag() == 2) // projectile
{
_projectiles->removeObject(sprite);
}
}
void HelloWorld::gameLogic(float dt)
{
this->addTarget();
}
void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
// Choose one of the touches to work with
CCTouch* touch = (CCTouch*)( touches->anyObject() );
CCPoint location = touch->locationInView();
location = CCDirector::sharedDirector()->convertToGL(location);
// Set up initial location of projectile
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCSprite *projectile = CCSprite::spriteWithFile("Projectile.png", CCRectMake(0, 0, 20, 20));
projectile->setPosition( ccp(20, winSize.height/2) );
// Determine offset of location to projectile
int offX = location.x - projectile->getPosition().x;
int offY = location.y - projectile->getPosition().y;
// Bail out if we are shooting down or backwards
if (offX <= 0) return;
// OK to add now - we've double checked position
this->addChild(projectile);
// Determine where we wish to shoot the projectile to
int realX = winSize.width + (projectile->getContentSize().width/2);
float ratio = (float)offY / (float)offX;
int realY = (realX * ratio) + projectile->getPosition().y;
CCPoint realDest = ccp(realX, realY);
// Determine the length of how far we're shooting
int offRealX = realX - projectile->getPosition().x;
int offRealY = realY - projectile->getPosition().y;
float length = sqrtf((offRealX * offRealX) + (offRealY * offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/velocity;
// Move projectile to actual endpoint
projectile->runAction( CCSequence::actions( CCMoveTo::actionWithDuration(realMoveDuration, realDest), CCCallFuncN::actionWithTarget(this, callfuncN_selector(HelloWorld::spriteMoveFinished)), NULL) );
// Add to projectiles array
projectile->setTag(2);
_projectiles->addObject(projectile);
}
void HelloWorld::update(CCTime dt)
{
CCArray *projectilesToDelete = CCArray::create();
CCObject* arrayItem1;
CCARRAY_FOREACH(_projectiles, arrayItem1)
{
CCSprite* projectile = (CCSprite*)arrayItem1;
CCRect projectileRect = CCRectMake(
projectile->getPosition().x - (projectile->getContentSize().width/2),
projectile->getPosition().y - (projectile->getContentSize().height/2),
projectile->getContentSize().width,
projectile->getContentSize().height);
CCArray* targetsToDelete = CCArray::create();
CCObject* arrayItem2;
CCARRAY_FOREACH(_targets, arrayItem2)
{
CCSprite* target = (CCSprite*) arrayItem2;
CCRect targetRect = CCRectMake(
target->getPosition().x - (target->getContentSize().width/2),
target->getPosition().y - (target->getContentSize().height/2),
target->getContentSize().width,
target->getContentSize().height);
if (CCRect::CCRectIntersectsRect(projectileRect, targetRect))
{
targetsToDelete->addObject(target);
}
}
CCARRAY_FOREACH(targetsToDelete, arrayItem2)
{
CCSprite* target = (CCSprite*) arrayItem2;
_targets->removeObject(target);
this->removeChild(target, true);
}
if (targetsToDelete->count() > 0)
{
projectilesToDelete->addObject(projectile);
}
targetsToDelete->release();
}
CCARRAY_FOREACH(projectilesToDelete, arrayItem1)
{
CCSprite* projectile = (CCSprite*) arrayItem1;
_projectiles->removeObject(projectile);
this->removeChild(projectile, true);
}
projectilesToDelete->release();
}
Maybe this part is a problem:
bool HelloWorld::init()
{
....
this->schedule( schedule_selector(HelloWorld::update) );
....
}
But I don't understand why this part is a problem.
Please, help me!
change CCTime to float.
in old cocos2d-x version, they have ccTime instead of CCTime
but in 2.0 they remove it. since it is duplicated with float.