c++ How to wait for multiple mouse clicks - c++

I want to draw a Triangle in CImg library. However, I do not know how to write the code that will allow me to draw the triangle using three mouse clicks.
The code in the documentation is this:
while (!main_disp.is_closed() && !draw_disp.is_closed())
{
main_disp.wait();
if (main_disp.button() && main_disp.mouse_y()>=0)
http://cimg.sourceforge.net/reference/group__cimg__tutorial.html
But it is for one mouse click, which I implemented successfully to draw a circle on the mouse click. But to do for three mouse clicks or two has proven to be difficult for me.
I also have the problem of inputting the color I want. I wrote red for example as:
const unsigned char red[] = {250, 0, 0};
Then I want the user to choose which color, enter his choice(assume it's red) and then pass this definition of red into the image.
Anyone can help with this ?!

If you know how to detect when the mouse button is clicked, you can store information about that click for later. For example, you can store previous mouse clicks in a deque.
struct point
{
int x,y;
};
...
std::deque<point> clicks;
while (!main_disp.is_closed() && !draw_disp.is_closed())
{
main_disp.wait();
if (main_disp.button())
{
clicks.push_front({mouse_disp.mouse_x(), mouse_disp.mouse_y()});
if (clicks.size() >= 3)
{
// draw a triangle using clicks[0], clicks[1] and clicks[2]
}
}
}

Related

Change Cursor Image While Hovering Over An Object Drawn At OpenGL And Displaying Object's Variables

I am currently working on a project that I use C++, OpenGL, Qt 5.9.2 and Microsoft Visual Studio Professional 2015 on a 64 bit Operating System, Windows 10 Pro.
I have a user interface that I have created and in that user interface, there is a QGLWidget, that I am using for draw processes, with other widgets like push buttons and a dockWidget. I have a class Ball and it has variables(distance(double) and angle(int)) that determines where an instance of that Ball is going to be drawn inside the QGLWidget. Ball class has got 2 more variables that is, id(int), model(String) and year(int) Every other draw process draws lines except Ball drawings.
Drawings are 2 dimensional.
Every Ball has the same color(rgb)!
First problem: I want to left click to one of the Ball instances and I want to display it's id, model and year at The dockWidget.
Second Problem: While doing the stuff that I have mentioned at the First Problem section. I want the cursor image to change while hovering above any of the Ball instances, and change back to default Windows mouse cursor while not.
I have created a function that checks if the MouseEvent is LeftClick:
void DisplayManager::mousePressEvent(QMouseEvent* ev) {
if (ev->buttons() & Qt::LeftButton) { // Balls Are Green
if(// CHECK IF THERE IS A BALL AT THE CLICKED COORDINATES) {
// DISPLAY THE X and Y OF THE BALL AT THE DOCK WIDGET
}
}
}
This is my initializeGL function: (DisplayManager is the name of my QGLWidget)
void DisplayManager::initializeGL() {
glEnable(GL_COLOR_MATERIAL); // Enables the changing of the draw color with glColor() functions
glColor3f(0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1); //sets a black background 1 0 0 1
}
On the basis this is a Picking problem and there are several information about it at the internet but I am not using GLUT and I am not using any shader. So in the light of all these I was unable to find any effective solution or clue about how can I accomplish all that I want.
I would be really glad if someone could help me with at least one of these problems.
I have currently finished working with the project. I thought that I should provide an answer to my question in case someone with a similar problem comes across with my question in the future.
void DisplayManager::mousePressEvent(QMouseEvent* ev) {
// The processes that are being executed after a left mouse button click on the DisplayManager.
if (ev->buttons() & Qt::LeftButton) {
double aspectRatio = openGLWidgetWidth / openGLWidgetHeight;
int xOfClicked = ev->x() - (openGLWidgetWidth / 2);
int yOfClicked = - (ev->y() - (openGLWidgetHeight / 2));
// The variable to be used for calculating fault tolerance of the click event.
int distanceBetweenPressAndDraw = 0;
// Executes the processes inside for every ball in vector.
for (int i = 0; i < ballVector.length(); i++) {
// Calculates the screen coordinates of the i'th ball.
int rangeOfBallInScreenDistance = rangeToScreenDistance(ballVector.at(i).range);
double screenXOfBall = rangeOfBallInScreenDistance * sin(ballVector.at(i).degree * DEGTORAD);
double screenYOfBall = rangeOfBallInScreenDistance * cos(ballVector.at(i).degree * DEGTORAD);
// Calculates the distance between pressed position and the i'th ball according to the screen coordinates.
distanceBetweenPressAndDraw = sqrt(pow((screenXOfBall - xOfClicked), 2) + pow((screenYOfBall - yOfClicked), 2));
// Decides if the clicked position is a ball (considering the fault tolerance).
if (distanceBetweenPressAndDraw < 10) {
emit printXY(QPointF(xOfClicked, yOfClicked)); // Prints the screen coordinates of the clicked positions (At the Dock Widget inside Main Window).
}
}
}
}
This was the solution for my First Problem. I would be glad though if someone could answer my Second problem in a comment or answer somehow.

OpenGL - Moving Primitives along the X and Y using arrow keys

I'm building a 2D drawing canvas that allows users to draw shapes on the screen by first selecting which shape you want to draw, and then clicking into the drawing area to draw your shape. Here's what the UI looks like for a better visualization:
So far, I have some code that allows the user to click on the derired shape, draw the shape, then click on another shape to draw, and so on...
First I check if a button has been clicked on in my processMouse() function:
if (x >= 0 && x <= 95 && y >= 302 && y <= 380) { // area of SQUARE shape
// squareShape = false by default
squareShape = true;
}
else squareShape = false;
If it has, we highlight the shape in my display() function:
if (squareShape != false) {
drawHighlight(100, 50, 350, true); // highlighted SQUARE
}
and in the same function, we enable some points to be drawn:
if (areaClicked2 != false) {
for (int i = 0; i < points.size();i++)
{
//areaClicked2 = true;
glLineWidth(1);
glBegin(GL_LINES);
glVertex2i(points[i].x + lineOffset.x, points[i].y + lineOffset.y);
}
}
I have applied this exact same method for every other button, and they all seem to be working fine...
My issue?
If I click on a button to draw squares, it draws a few squares, but when I click on an another button, my squares disappear because I don't have the square button selected. So for every button when I click to draw, the shapes are only visible until I click on an another button. How can I fix this?
EDIT:
Everytime I want to make a new points vector for a new shape, I make a new vector like this:
std::vector <point> lines; // old vector
point OnePoint;
std::vector <point> dots; // new vector
point OneDot;
Should I not be doing this? If not, how should I be? I tried to keep lines and just make new point variables but then when I draw, they're exactly the same point.
Just a guess, I think you are clearing(or creating new) points[] collection on each shape selection. You should preserve old point collection and append new shape points so that it will be visible even on different shape selection.

Drawing Dice in a Windows C++ program?

We just started learning windows programming in C++. We have to make a program that has 4 die on the screen, and when the user presses 'SpaceBar', the die roll, or the number of dots on the die change randomly. Our professor hasent given us a lot of information, so I am kind of just looking for some direction.
Right now, I have 4 squares drawn on the screen, made with the Rectangle() function.
Rectangle(hDC,30,100,130,200);
Rectangle(hDC,180,100,280,200);
Rectangle(hDC,330,100,430,200);
Rectangle(hDC,480,100,580,200);
My question is 1) how would I go about drawing dots on these 'squares' and not on the 'screen'. So if I move the die upwards, the dots move with the square and dont just stay stationed painted on the screen. And 2.) How would I go about making those dots randomly change when spacebar is pressed (simulating that they have been rolled)?
Just looking for some direction, thanks.
1)
You will still have to draw them on the screen, but you can structure your program to realize the dots as part of the square.
void moveSquare()
{
//change square position
//change dots positions the same as you changed the square
}
2)
You can capture keypresses in your window with the WM_KEYDOWN and WM_KEYUP messages, or the WM_CHAR message. Just start a chain of changing how many dots are supposed to appear on the die when space is pressed (SetTimer could be handy), and let WM_PAINT do the work of painting the dots (or call something to calculate the positions of the dots, and let WM_PAINT loop through each dot it needs to draw.
void OnSpacePressed()
{
//start changing dots every so often, handled elsewhere
//maybe check if finished rolling before doing so
}
void calculateDotPositions()
{
switch (numberOfDots) {...} //hint: use the square as a reference point
}
void OnPaint()
{
//paint each sqaure
//paint each dot in the correct position, which should be updated with square
}
void OnChangeDots()
{
//change number of dots
//also start a new change to happen later if not done rolling
}
For drawing dots, use Warren P's reference link.
Another method is to create a bitmap or picture in memory. One for each of the 6 faces of the die. The objective here is to copy the bitmaps to the screen, rather than having to redraw them each time. Research "bitmap", and "bitblt".
You should make a routine that draws a die at the origin, offset by given coordinates. I'm not familiar with the particular library you are using, so I don't know what hDC is, but it should look something like the following.
void drawDie(HDC hDC, int xCoord, int yCoord, int dieValue)
{
Rectangle(hDC, -50 + xCoord, -50 + yCoord, 50 + xCoord, 50 + yCoord);
// draw some number of circles specified by dieValue at appropriate coordinates
// translated by xCoord and yCoord arguments
}
Then you can just redraw dice over your previous ones if you want them to change.

Trapping the mouse?

I'm using GLUT and developing a FPS game. I need a way to trap the mouse so that the camera continues to move because right now when the mouse position exceeds the monitor limit, there is no way to calculate change in X or change in Y. How can I 'trap' the mouse with GLUT?
Thanks
I'd recommend using a ready-made engine like OGRE 3D instead, but if you really want to reinvent the wheel, here's how...
In all cases I'm aware of, PC FPS games "trap" the pointer by registering a mouse motion callback, noting the relative motion, and then warping the pointer back to the center of the window.
Here's some code I wrote to add mouse input to a sample ping-pong table in an OpenGL with C++ course a year or two ago:
void resetPointer() {
glutWarpPointer(TABLE_X/2, TABLE_Y/2);
lastMousePos = TABLE_Y/2;
}
void mouseFunc(int sx, int sy) {
if (!started) { return; }
int vertMotion = lastMousePos - sy;
lastMousePos = sy;
player1.move(vertMotion);
// Keep the pointer from leaving the window.
if (fabs(TABLE_X/2 - sx) > 25 || fabs(TABLE_Y/2 - sy) > 25) {
resetPointer();
}
}
// This goes in with your "start new game" code if you want a menu
resetPointer();
glutSetCursor(GLUT_CURSOR_NONE);
glutPassiveMotionFunc(mouseFunc);
It only tracks vertical motion, but adding horizontal is trivial.

How to get the x,y coordinate of a mouse-click with win32 C++ on a directx object?

How can I get the x,y coordinate of a mouse click, to see if it is over my menu button drawn by directx? Currently, my codebase has the following mouse-related class that doesn't seem to be able to give me this..I'm not sure how this might work.
InputMouse::InputMouse() :
m_LastX(-1),
m_LastY(-1)
{
m_MouseActionEvent.clear();
}
InputMouse::~InputMouse()
{
}
void InputMouse::PostUpdate()
{
m_CurrentAction.clear();
}
bool InputMouse::IsEventTriggered(int eventNumber)
{
for (unsigned int i = 0; i < m_CurrentAction.size(); i++)
{
if (m_MouseActionEvent.size() > 0 && m_MouseActionEvent[m_CurrentAction[i]] == eventNumber)
{
return true;
}
}
return false;
}
void InputMouse::AddInputEvent(int action, int eventNumber)
{
m_MouseActionEvent[action] = eventNumber;
}
void InputMouse::SetMouseMouse(int x, int y)
{
if (m_LastX != -1)
{
if (x > m_LastX)
{
m_CurrentAction.push_back(MOUSE_RIGHT);
}
else if (x < m_LastX)
{
m_CurrentAction.push_back(MOUSE_LEFT);
}
if (y > m_LastY)
{
m_CurrentAction.push_back(MOUSE_UP);
}
else if (y < m_LastY)
{
m_CurrentAction.push_back(MOUSE_DOWN);
}
}
m_LastX = x;
m_LastY = y;
}
DirectX or not, GetCursorPos is going to retrieve the position of the mouse in screen co-ordinates. ScreenToClient will map the screen relative point to a point relative to the client area of your window/directX surface.
If your menu buttons are 2D, this should be as simple as remembering the screen co-ordinates used for your buttons.
If you're trying to determine if a click lands on a 3D object that's been rendered, then the technique you are looking for is called Picking.
A simple Google for "directx picking" comes up with some good results:
http://www.mvps.org/directx/articles/rayproj.htm
http://www.gamedev.net/community/forums/topic.asp?topic_id=316274
Basically, the technique involves converting the mouse click into a ray into the scene. For your menu items, a simple bounding box will probably suffice for determining a 'hit'.
Once an object is drawn, the system has no knowledge of which pixels on the screen it changed, nor do those pixels know which object or objects changed it (nor if those objects even still exist). Therefore, if you need to know where something is on-screen, you have to track it yourself. For buttons and other GUI elements this usually means keeping your GUI in memory along with the rectangles that define the boundaries of each element. Then you can compare your mouse position to the boundary of each element to see which one it is pointing at.