mirror of https://github.com/adamdruppe/arsd.git
remove unneeded static import to try to help user
This commit is contained in:
parent
d503ac5011
commit
fe3cca9e83
533
simpledisplay.d
533
simpledisplay.d
|
@ -1,8 +1,3 @@
|
||||||
// Please note when compiling on Win64, you need to explicitly list
|
|
||||||
// `-Lgdi32.lib -Luser32.lib` on the build command. If you want the Windows
|
|
||||||
// subsystem too, use `-L/subsystem:windows -L/entry:mainCRTStartup`
|
|
||||||
//
|
|
||||||
// On Mac, when compiling with X11, you need XQuartz and -L-L/usr/X11R6/lib passed to dmd.
|
|
||||||
/*
|
/*
|
||||||
FIXME:
|
FIXME:
|
||||||
|
|
||||||
|
@ -58,6 +53,31 @@
|
||||||
and may add new features and fix bugs, but It do not expect to
|
and may add new features and fix bugs, but It do not expect to
|
||||||
significantly change the API. It has been stable a few years already now.
|
significantly change the API. It has been stable a few years already now.
|
||||||
|
|
||||||
|
Installation_instructions:
|
||||||
|
|
||||||
|
`simpledisplay.d` does not have any dependencies outside the
|
||||||
|
operating system and `color.d`, so it should just work most the
|
||||||
|
time, but there are a few caveats on some systems:
|
||||||
|
|
||||||
|
Please note when compiling on Win64, you need to explicitly list
|
||||||
|
`-Lgdi32.lib -Luser32.lib` on the build command. If you want the Windows
|
||||||
|
subsystem too, use `-L/subsystem:windows -L/entry:mainCRTStartup`.
|
||||||
|
|
||||||
|
On Win32, you can pass `-L/subsystem:windows` if you don't want a
|
||||||
|
console to be automatically allocated.
|
||||||
|
|
||||||
|
On Mac, when compiling with X11, you need XQuartz and -L-L/usr/X11R6/lib passed to dmd.
|
||||||
|
|
||||||
|
On Ubuntu, you might need to install X11 development libraries to
|
||||||
|
successfully link.
|
||||||
|
|
||||||
|
$(CONSOLE
|
||||||
|
$ sudo apt-get install libglc-dev
|
||||||
|
$ sudo apt-get install libx11-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Jump_list:
|
Jump_list:
|
||||||
|
|
||||||
Don't worry, you don't have to read this whole documentation file!
|
Don't worry, you don't have to read this whole documentation file!
|
||||||
|
@ -108,7 +128,7 @@
|
||||||
import std.conv;
|
import std.conv;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
auto window = new SimpleWindow(Size(500, 500), "My D App");
|
auto window = new SimpleWindow(Size(500, 500), "Event example - simpledisplay.d");
|
||||||
|
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
|
@ -148,126 +168,6 @@
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
$(H3 Pong-example)
|
|
||||||
This program creates a little Pong-like game. Player one is controlled
|
|
||||||
with the keyboard. Player two is controlled with the mouse. It demos
|
|
||||||
the pulse timer, event handling, and some basic drawing.
|
|
||||||
|
|
||||||
---
|
|
||||||
// dmd example.d simpledisplay.d color.d
|
|
||||||
import arsd.simpledisplay;
|
|
||||||
|
|
||||||
enum paddleMovementSpeed = 8;
|
|
||||||
enum paddleHeight = 48;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
auto window = new SimpleWindow(600, 400, "Pong game!");
|
|
||||||
|
|
||||||
int playerOnePosition, playerTwoPosition;
|
|
||||||
int playerOneMovement, playerTwoMovement;
|
|
||||||
int playerOneScore, playerTwoScore;
|
|
||||||
|
|
||||||
int ballX, ballY;
|
|
||||||
int ballDx, ballDy;
|
|
||||||
|
|
||||||
void serve() {
|
|
||||||
import std.random;
|
|
||||||
|
|
||||||
ballX = window.width / 2;
|
|
||||||
ballY = window.height / 2;
|
|
||||||
ballDx = uniform(-4, 4) * 3;
|
|
||||||
ballDy = uniform(-4, 4) * 3;
|
|
||||||
if(ballDx == 0)
|
|
||||||
ballDx = uniform(0, 2) == 0 ? 3 : -3;
|
|
||||||
}
|
|
||||||
|
|
||||||
serve();
|
|
||||||
|
|
||||||
window.eventLoop(50, // set a 50 ms timer pulls
|
|
||||||
// This runs once per timer pulse
|
|
||||||
delegate () {
|
|
||||||
auto painter = window.draw();
|
|
||||||
|
|
||||||
painter.clear();
|
|
||||||
|
|
||||||
// Update everyone's motion
|
|
||||||
playerOnePosition += playerOneMovement;
|
|
||||||
playerTwoPosition += playerTwoMovement;
|
|
||||||
|
|
||||||
ballX += ballDx;
|
|
||||||
ballY += ballDy;
|
|
||||||
|
|
||||||
// Bounce off the top and bottom edges of the window
|
|
||||||
if(ballY + 7 >= window.height)
|
|
||||||
ballDy = -ballDy;
|
|
||||||
if(ballY - 8 <= 0)
|
|
||||||
ballDy = -ballDy;
|
|
||||||
|
|
||||||
// Bounce off the paddle, if it is in position
|
|
||||||
if(ballX - 8 <= 16) {
|
|
||||||
if(ballY + 7 > playerOnePosition && ballY - 8 < playerOnePosition + paddleHeight) {
|
|
||||||
ballDx = -ballDx + 1; // add some speed to keep it interesting
|
|
||||||
ballDy += playerOneMovement; // and y movement based on your controls too
|
|
||||||
ballX = 24; // move it past the paddle so it doesn't wiggle inside
|
|
||||||
} else {
|
|
||||||
// Missed it
|
|
||||||
playerTwoScore ++;
|
|
||||||
serve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ballX + 7 >= window.width - 16) { // do the same thing but for player 1
|
|
||||||
if(ballY + 7 > playerTwoPosition && ballY - 8 < playerTwoPosition + paddleHeight) {
|
|
||||||
ballDx = -ballDx - 1;
|
|
||||||
ballDy += playerTwoMovement;
|
|
||||||
ballX = window.width - 24;
|
|
||||||
} else {
|
|
||||||
// Missed it
|
|
||||||
playerOneScore ++;
|
|
||||||
serve();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the paddles
|
|
||||||
painter.outlineColor = Color.black;
|
|
||||||
painter.drawLine(Point(16, playerOnePosition), Point(16, playerOnePosition + paddleHeight));
|
|
||||||
painter.drawLine(Point(window.width - 16, playerTwoPosition), Point(window.width - 16, playerTwoPosition + paddleHeight));
|
|
||||||
|
|
||||||
// Draw the ball
|
|
||||||
painter.fillColor = Color.red;
|
|
||||||
painter.outlineColor = Color.yellow;
|
|
||||||
painter.drawEllipse(Point(ballX - 8, ballY - 8), Point(ballX + 7, ballY + 7));
|
|
||||||
|
|
||||||
// Draw the score
|
|
||||||
painter.outlineColor = Color.blue;
|
|
||||||
import std.conv;
|
|
||||||
painter.drawText(Point(64, 4), to!string(playerOneScore));
|
|
||||||
painter.drawText(Point(window.width - 64, 4), to!string(playerTwoScore));
|
|
||||||
|
|
||||||
},
|
|
||||||
delegate (KeyEvent event) {
|
|
||||||
// Player 1's controls are the arrow keys on the keyboard
|
|
||||||
if(event.key == Key.Down)
|
|
||||||
playerOneMovement = event.pressed ? paddleMovementSpeed : 0;
|
|
||||||
if(event.key == Key.Up)
|
|
||||||
playerOneMovement = event.pressed ? -paddleMovementSpeed : 0;
|
|
||||||
|
|
||||||
},
|
|
||||||
delegate (MouseEvent event) {
|
|
||||||
// Player 2's controls are mouse movement while the left button is held down
|
|
||||||
if(event.type == MouseEventType.motion && (event.modifierState & ModifierState.leftButtonDown)) {
|
|
||||||
if(event.dy > 0)
|
|
||||||
playerTwoMovement = paddleMovementSpeed;
|
|
||||||
else if(event.dy < 0)
|
|
||||||
playerTwoMovement = -paddleMovementSpeed;
|
|
||||||
} else {
|
|
||||||
playerTwoMovement = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
If you are interested in more game writing with D, check out my gamehelpers.d which builds upon simpledisplay, and its other stand-alone support modules, simpleaudio.d and joystick.d, too.
|
If you are interested in more game writing with D, check out my gamehelpers.d which builds upon simpledisplay, and its other stand-alone support modules, simpleaudio.d and joystick.d, too.
|
||||||
|
|
||||||
This program displays a pie chart. Clicking on a color will increase its share of the pie.
|
This program displays a pie chart. Clicking on a color will increase its share of the pie.
|
||||||
|
@ -515,6 +415,347 @@
|
||||||
+/
|
+/
|
||||||
module arsd.simpledisplay;
|
module arsd.simpledisplay;
|
||||||
|
|
||||||
|
// FIXME: tetris demo
|
||||||
|
// FIXME: space invaders demo
|
||||||
|
// FIXME: asteroids demo
|
||||||
|
|
||||||
|
/++ $(ID Pong-example)
|
||||||
|
$(H3 Pong)
|
||||||
|
|
||||||
|
This program creates a little Pong-like game. Player one is controlled
|
||||||
|
with the keyboard. Player two is controlled with the mouse. It demos
|
||||||
|
the pulse timer, event handling, and some basic drawing.
|
||||||
|
+/
|
||||||
|
unittest {
|
||||||
|
// dmd example.d simpledisplay.d color.d
|
||||||
|
import arsd.simpledisplay;
|
||||||
|
|
||||||
|
enum paddleMovementSpeed = 8;
|
||||||
|
enum paddleHeight = 48;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
auto window = new SimpleWindow(600, 400, "Pong game!");
|
||||||
|
|
||||||
|
int playerOnePosition, playerTwoPosition;
|
||||||
|
int playerOneMovement, playerTwoMovement;
|
||||||
|
int playerOneScore, playerTwoScore;
|
||||||
|
|
||||||
|
int ballX, ballY;
|
||||||
|
int ballDx, ballDy;
|
||||||
|
|
||||||
|
void serve() {
|
||||||
|
import std.random;
|
||||||
|
|
||||||
|
ballX = window.width / 2;
|
||||||
|
ballY = window.height / 2;
|
||||||
|
ballDx = uniform(-4, 4) * 3;
|
||||||
|
ballDy = uniform(-4, 4) * 3;
|
||||||
|
if(ballDx == 0)
|
||||||
|
ballDx = uniform(0, 2) == 0 ? 3 : -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
serve();
|
||||||
|
|
||||||
|
window.eventLoop(50, // set a 50 ms timer pulls
|
||||||
|
// This runs once per timer pulse
|
||||||
|
delegate () {
|
||||||
|
auto painter = window.draw();
|
||||||
|
|
||||||
|
painter.clear();
|
||||||
|
|
||||||
|
// Update everyone's motion
|
||||||
|
playerOnePosition += playerOneMovement;
|
||||||
|
playerTwoPosition += playerTwoMovement;
|
||||||
|
|
||||||
|
ballX += ballDx;
|
||||||
|
ballY += ballDy;
|
||||||
|
|
||||||
|
// Bounce off the top and bottom edges of the window
|
||||||
|
if(ballY + 7 >= window.height)
|
||||||
|
ballDy = -ballDy;
|
||||||
|
if(ballY - 8 <= 0)
|
||||||
|
ballDy = -ballDy;
|
||||||
|
|
||||||
|
// Bounce off the paddle, if it is in position
|
||||||
|
if(ballX - 8 <= 16) {
|
||||||
|
if(ballY + 7 > playerOnePosition && ballY - 8 < playerOnePosition + paddleHeight) {
|
||||||
|
ballDx = -ballDx + 1; // add some speed to keep it interesting
|
||||||
|
ballDy += playerOneMovement; // and y movement based on your controls too
|
||||||
|
ballX = 24; // move it past the paddle so it doesn't wiggle inside
|
||||||
|
} else {
|
||||||
|
// Missed it
|
||||||
|
playerTwoScore ++;
|
||||||
|
serve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ballX + 7 >= window.width - 16) { // do the same thing but for player 1
|
||||||
|
if(ballY + 7 > playerTwoPosition && ballY - 8 < playerTwoPosition + paddleHeight) {
|
||||||
|
ballDx = -ballDx - 1;
|
||||||
|
ballDy += playerTwoMovement;
|
||||||
|
ballX = window.width - 24;
|
||||||
|
} else {
|
||||||
|
// Missed it
|
||||||
|
playerOneScore ++;
|
||||||
|
serve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the paddles
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.drawLine(Point(16, playerOnePosition), Point(16, playerOnePosition + paddleHeight));
|
||||||
|
painter.drawLine(Point(window.width - 16, playerTwoPosition), Point(window.width - 16, playerTwoPosition + paddleHeight));
|
||||||
|
|
||||||
|
// Draw the ball
|
||||||
|
painter.fillColor = Color.red;
|
||||||
|
painter.outlineColor = Color.yellow;
|
||||||
|
painter.drawEllipse(Point(ballX - 8, ballY - 8), Point(ballX + 7, ballY + 7));
|
||||||
|
|
||||||
|
// Draw the score
|
||||||
|
painter.outlineColor = Color.blue;
|
||||||
|
import std.conv;
|
||||||
|
painter.drawText(Point(64, 4), to!string(playerOneScore));
|
||||||
|
painter.drawText(Point(window.width - 64, 4), to!string(playerTwoScore));
|
||||||
|
|
||||||
|
},
|
||||||
|
delegate (KeyEvent event) {
|
||||||
|
// Player 1's controls are the arrow keys on the keyboard
|
||||||
|
if(event.key == Key.Down)
|
||||||
|
playerOneMovement = event.pressed ? paddleMovementSpeed : 0;
|
||||||
|
if(event.key == Key.Up)
|
||||||
|
playerOneMovement = event.pressed ? -paddleMovementSpeed : 0;
|
||||||
|
|
||||||
|
},
|
||||||
|
delegate (MouseEvent event) {
|
||||||
|
// Player 2's controls are mouse movement while the left button is held down
|
||||||
|
if(event.type == MouseEventType.motion && (event.modifierState & ModifierState.leftButtonDown)) {
|
||||||
|
if(event.dy > 0)
|
||||||
|
playerTwoMovement = paddleMovementSpeed;
|
||||||
|
else if(event.dy < 0)
|
||||||
|
playerTwoMovement = -paddleMovementSpeed;
|
||||||
|
} else {
|
||||||
|
playerTwoMovement = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++ $(ID example-minesweeper)
|
||||||
|
|
||||||
|
This minesweeper demo shows how we can implement another classic
|
||||||
|
game with simpledisplay and shows some mouse input and basic output
|
||||||
|
code.
|
||||||
|
+/
|
||||||
|
unittest {
|
||||||
|
import arsd.simpledisplay;
|
||||||
|
|
||||||
|
enum GameSquare {
|
||||||
|
mine = 0,
|
||||||
|
clear,
|
||||||
|
m1, m2, m3, m4, m5, m6, m7, m8
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UserSquare {
|
||||||
|
unknown,
|
||||||
|
revealed,
|
||||||
|
flagged,
|
||||||
|
questioned
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GameState {
|
||||||
|
inProgress,
|
||||||
|
lose,
|
||||||
|
win
|
||||||
|
}
|
||||||
|
|
||||||
|
GameSquare[] board;
|
||||||
|
UserSquare[] userState;
|
||||||
|
GameState gameState;
|
||||||
|
int boardWidth;
|
||||||
|
int boardHeight;
|
||||||
|
|
||||||
|
bool isMine(int x, int y) {
|
||||||
|
if(x < 0 || y < 0 || x >= boardWidth || y >= boardHeight)
|
||||||
|
return false;
|
||||||
|
return board[y * boardWidth + x] == GameSquare.mine;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameState reveal(int x, int y) {
|
||||||
|
if(board[y * boardWidth + x] == GameSquare.clear) {
|
||||||
|
floodFill(userState, boardWidth, boardHeight,
|
||||||
|
UserSquare.unknown, UserSquare.revealed,
|
||||||
|
x, y,
|
||||||
|
(x, y) {
|
||||||
|
if(board[y * boardWidth + x] == GameSquare.clear)
|
||||||
|
return true;
|
||||||
|
else {
|
||||||
|
userState[y * boardWidth + x] = UserSquare.revealed;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
userState[y * boardWidth + x] = UserSquare.revealed;
|
||||||
|
if(isMine(x, y))
|
||||||
|
return GameState.lose;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(state; userState) {
|
||||||
|
if(state == UserSquare.unknown || state == UserSquare.questioned)
|
||||||
|
return GameState.inProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GameState.win;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeBoard(int width, int height, int numberOfMines) {
|
||||||
|
boardWidth = width;
|
||||||
|
boardHeight = height;
|
||||||
|
board.length = width * height;
|
||||||
|
|
||||||
|
userState.length = width * height;
|
||||||
|
userState[] = UserSquare.unknown;
|
||||||
|
|
||||||
|
import std.algorithm, std.random, std.range;
|
||||||
|
|
||||||
|
board[] = GameSquare.clear;
|
||||||
|
|
||||||
|
foreach(minePosition; randomSample(iota(0, board.length), numberOfMines))
|
||||||
|
board[minePosition] = GameSquare.mine;
|
||||||
|
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
foreach(idx, ref square; board) {
|
||||||
|
if(square == GameSquare.clear) {
|
||||||
|
int danger = 0;
|
||||||
|
danger += isMine(x-1, y-1)?1:0;
|
||||||
|
danger += isMine(x-1, y)?1:0;
|
||||||
|
danger += isMine(x-1, y+1)?1:0;
|
||||||
|
danger += isMine(x, y-1)?1:0;
|
||||||
|
danger += isMine(x, y+1)?1:0;
|
||||||
|
danger += isMine(x+1, y-1)?1:0;
|
||||||
|
danger += isMine(x+1, y)?1:0;
|
||||||
|
danger += isMine(x+1, y+1)?1:0;
|
||||||
|
|
||||||
|
square = cast(GameSquare) (danger + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
x++;
|
||||||
|
if(x == width) {
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void redraw(SimpleWindow window) {
|
||||||
|
import std.conv;
|
||||||
|
|
||||||
|
auto painter = window.draw();
|
||||||
|
|
||||||
|
painter.clear();
|
||||||
|
|
||||||
|
final switch(gameState) with(GameState) {
|
||||||
|
case inProgress:
|
||||||
|
break;
|
||||||
|
case win:
|
||||||
|
painter.fillColor = Color.green;
|
||||||
|
painter.drawRectangle(Point(0, 0), window.width, window.height);
|
||||||
|
return;
|
||||||
|
case lose:
|
||||||
|
painter.fillColor = Color.red;
|
||||||
|
painter.drawRectangle(Point(0, 0), window.width, window.height);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
foreach(idx, square; board) {
|
||||||
|
auto state = userState[idx];
|
||||||
|
|
||||||
|
final switch(state) with(UserSquare) {
|
||||||
|
case unknown:
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.fillColor = Color(128,128,128);
|
||||||
|
|
||||||
|
painter.drawRectangle(
|
||||||
|
Point(x * 20, y * 20),
|
||||||
|
20, 20
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case revealed:
|
||||||
|
if(square == GameSquare.clear) {
|
||||||
|
painter.outlineColor = Color.white;
|
||||||
|
painter.fillColor = Color.white;
|
||||||
|
|
||||||
|
painter.drawRectangle(
|
||||||
|
Point(x * 20, y * 20),
|
||||||
|
20, 20
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.fillColor = Color.white;
|
||||||
|
|
||||||
|
painter.drawText(
|
||||||
|
Point(x * 20, y * 20),
|
||||||
|
to!string(square)[1..2],
|
||||||
|
Point(x * 20 + 20, y * 20 + 20),
|
||||||
|
TextAlignment.Center | TextAlignment.VerticalCenter);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case flagged:
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.fillColor = Color.red;
|
||||||
|
painter.drawRectangle(
|
||||||
|
Point(x * 20, y * 20),
|
||||||
|
20, 20
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case questioned:
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.fillColor = Color.yellow;
|
||||||
|
painter.drawRectangle(
|
||||||
|
Point(x * 20, y * 20),
|
||||||
|
20, 20
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
x++;
|
||||||
|
if(x == boardWidth) {
|
||||||
|
x = 0;
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
auto window = new SimpleWindow(200, 200);
|
||||||
|
|
||||||
|
initializeBoard(10, 10, 10);
|
||||||
|
|
||||||
|
redraw(window);
|
||||||
|
window.eventLoop(0,
|
||||||
|
delegate (MouseEvent me) {
|
||||||
|
if(me.type != MouseEventType.buttonPressed)
|
||||||
|
return;
|
||||||
|
auto x = me.x / 20;
|
||||||
|
auto y = me.y / 20;
|
||||||
|
if(x >= 0 && x < boardWidth && y >= 0 && y < boardHeight) {
|
||||||
|
if(me.button == MouseButton.left) {
|
||||||
|
gameState = reveal(x, y);
|
||||||
|
} else {
|
||||||
|
userState[y*boardWidth+x] = UserSquare.flagged;
|
||||||
|
}
|
||||||
|
redraw(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
version(Windows) {
|
version(Windows) {
|
||||||
import core.sys.windows.windows;
|
import core.sys.windows.windows;
|
||||||
static import gdi = core.sys.windows.wingdi;
|
static import gdi = core.sys.windows.wingdi;
|
||||||
|
@ -1681,22 +1922,22 @@ class Timer {
|
||||||
} else version(linux) {
|
} else version(linux) {
|
||||||
static import ep = core.sys.linux.epoll;
|
static import ep = core.sys.linux.epoll;
|
||||||
|
|
||||||
static import tfd = core.sys.linux.timerfd;
|
import core.sys.linux.timerfd;
|
||||||
|
|
||||||
fd = tfd.timerfd_create(tfd.CLOCK_MONOTONIC, 0);
|
fd = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
throw new Exception("timer create failed");
|
throw new Exception("timer create failed");
|
||||||
|
|
||||||
mapping[fd] = this;
|
mapping[fd] = this;
|
||||||
|
|
||||||
tfd.itimerspec value;
|
itimerspec value;
|
||||||
value.it_value.tv_sec = cast(int) (intervalInMilliseconds / 1000);
|
value.it_value.tv_sec = cast(int) (intervalInMilliseconds / 1000);
|
||||||
value.it_value.tv_nsec = (intervalInMilliseconds % 1000) * 1000_000;
|
value.it_value.tv_nsec = (intervalInMilliseconds % 1000) * 1000_000;
|
||||||
|
|
||||||
value.it_interval.tv_sec = cast(int) (intervalInMilliseconds / 1000);
|
value.it_interval.tv_sec = cast(int) (intervalInMilliseconds / 1000);
|
||||||
value.it_interval.tv_nsec = (intervalInMilliseconds % 1000) * 1000_000;
|
value.it_interval.tv_nsec = (intervalInMilliseconds % 1000) * 1000_000;
|
||||||
|
|
||||||
if(tfd.timerfd_settime(fd, 0, &value, null) == -1)
|
if(timerfd_settime(fd, 0, &value, null) == -1)
|
||||||
throw new Exception("couldn't make pulse timer");
|
throw new Exception("couldn't make pulse timer");
|
||||||
|
|
||||||
version(with_eventloop) {
|
version(with_eventloop) {
|
||||||
|
@ -2815,6 +3056,30 @@ enum MouseEventType : int {
|
||||||
// FIXME: mouse move should be distinct from presses+releases, so we can avoid subscribing to those events in X unnecessarily
|
// FIXME: mouse move should be distinct from presses+releases, so we can avoid subscribing to those events in X unnecessarily
|
||||||
/++
|
/++
|
||||||
Listen for this on your event listeners if you are interested in mouse action.
|
Listen for this on your event listeners if you are interested in mouse action.
|
||||||
|
|
||||||
|
Note that [button] is used on mouse press and release events. If you are curious about which button is being held in during motion, use [modifierState] and check the bitmask for [ModifierState.leftButtonDown], etc.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
This will draw boxes on the window with the mouse as you hold the left button.
|
||||||
|
---
|
||||||
|
import arsd.simpledisplay;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
auto window = new SimpleWindow();
|
||||||
|
|
||||||
|
window.eventLoop(0,
|
||||||
|
(MouseEvent ev) {
|
||||||
|
if(ev.modifierState & ModifierState.leftButtonDown) {
|
||||||
|
auto painter = window.draw();
|
||||||
|
painter.fillColor = Color.red;
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.drawRectangle(Point(ev.x / 16 * 16, ev.y / 16 * 16), 16, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
---
|
||||||
+/
|
+/
|
||||||
struct MouseEvent {
|
struct MouseEvent {
|
||||||
MouseEventType type; /// movement, press, release, double click. See [MouseEventType]
|
MouseEventType type; /// movement, press, release, double click. See [MouseEventType]
|
||||||
|
@ -6203,7 +6468,7 @@ version(X11) {
|
||||||
static import unix = core.sys.posix.unistd;
|
static import unix = core.sys.posix.unistd;
|
||||||
static import err = core.stdc.errno;
|
static import err = core.stdc.errno;
|
||||||
|
|
||||||
static import tfd = core.sys.linux.timerfd;
|
import core.sys.linux.timerfd;
|
||||||
prepareEventLoop();
|
prepareEventLoop();
|
||||||
|
|
||||||
ep.epoll_event[16] events = void;
|
ep.epoll_event[16] events = void;
|
||||||
|
@ -6226,18 +6491,18 @@ version(X11) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pulseTimeout) {
|
if(pulseTimeout) {
|
||||||
pulseFd = tfd.timerfd_create(tfd.CLOCK_MONOTONIC, 0);
|
pulseFd = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||||
if(pulseFd == -1)
|
if(pulseFd == -1)
|
||||||
throw new Exception("pulse timer create failed");
|
throw new Exception("pulse timer create failed");
|
||||||
|
|
||||||
tfd.itimerspec value;
|
itimerspec value;
|
||||||
value.it_value.tv_sec = cast(int) (pulseTimeout / 1000);
|
value.it_value.tv_sec = cast(int) (pulseTimeout / 1000);
|
||||||
value.it_value.tv_nsec = (pulseTimeout % 1000) * 1000_000;
|
value.it_value.tv_nsec = (pulseTimeout % 1000) * 1000_000;
|
||||||
|
|
||||||
value.it_interval.tv_sec = cast(int) (pulseTimeout / 1000);
|
value.it_interval.tv_sec = cast(int) (pulseTimeout / 1000);
|
||||||
value.it_interval.tv_nsec = (pulseTimeout % 1000) * 1000_000;
|
value.it_interval.tv_nsec = (pulseTimeout % 1000) * 1000_000;
|
||||||
|
|
||||||
if(tfd.timerfd_settime(pulseFd, 0, &value, null) == -1)
|
if(timerfd_settime(pulseFd, 0, &value, null) == -1)
|
||||||
throw new Exception("couldn't make pulse timer");
|
throw new Exception("couldn't make pulse timer");
|
||||||
|
|
||||||
ep.epoll_event ev = void;
|
ep.epoll_event ev = void;
|
||||||
|
|
Loading…
Reference in New Issue