For a project, I need to do a processing code able to switch between two completely different states. There is a default state and it switches to the special state when the mouse is pressed. The special state have an initialization phase. It also have an end and when it reaches it, the program switches back to the normal state. The way I would implement this is the following :
boolean isNormal;
void setup(){
//setup things...
isNormal = true;
}
void draw(){
if(isNormal){
normal();
}
else{
special();
if (endReached){
isNormal = true;
}
}
}
void mousePressed(){
specialSetup();
isNormal = false;
}
void normal(){
//normal routine...
}
void special(){
//special routine...
}
Is there a better way to do it (more efficient, cleaner, ...) ?
Related
QUESTION
I've noticed that draw() cycle is interrupted by events elaboration.
In the following example the circle animation will stop at mouse click until the elaborating_function() ends.
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
}
void draw(){
background(#818B95);
//simple animation
fill(0,116,217);
circle(circle_x, 200, 50);
circle_x += animation_speed;
if(circle_x>800){ circle_x = 0; }
}
void mouseClicked() {
elaborating_function();
}
void elaborating_function(){
println("elaboration start");
delay(1000);
println("elaboration end");
}
Of course, a simple solution to run the elaboration without stopping the animation could be to thread("elaborating_function");
But my question is: if it is possible to run the draw cycle into an independent thread instead?
SOLUTION
I've found a possible solution inverting my problem and creating an "independent cycle" parallel to the draw one. Within this cycle is possible to run any function and it will not interfere with the draw execution. Every event triggered by the user needs only to set a specific variable in order to activate (once or more time) the function within the cycle.
int circle_x = 0;
int animation_speed = 5;
boolean call_elaborating_function = false;
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
IndependentCycle independentCycle = new IndependentCycle();
independentCycle.setFrequency(1);
new Thread(independentCycle).start();
}
void draw(){
background(#818B95);
//simple animation
fill(0,116,217);
circle(circle_x, 200, 50);
circle_x += animation_speed;
if(circle_x>800){ circle_x = 0; }
}
public class IndependentCycle implements Runnable{
private int frequency; //execution per seconds
public IndependentCycle(){
frequency = 0;
}
public void setFrequency(int frequency){
this.frequency = 1000/frequency;
println(this.frequency);
}
public void run(){
while(true){
print(".");
delay(this.frequency);
//DO STUFF HERE
//WITH IF EVENT == ture IN ORDER TO RUN JUST ONCE !!
if(call_elaborating_function){
call_elaborating_function = false;
elaborating_function();
}
}
}
}
void mouseClicked() {
call_elaborating_function = true;
}
void elaborating_function(){
println("elaboration start");
delay(1000);
println("elaboration end");
}
As far as I know Processing has it's own AnimationThread.
Your proposed solution to thread elaborating_function() is great.
You could have a basic class that implements Runnable if you need a bit more control. With this thread running in parallel, Processing's main animation thread should run along side it just fine without pausing rendering.
This options sounds much simpler than trying to mess with Processing's AnimationThread and potentially have to deal with unexpected behaviour.
What is the actual goal you're trying achieve ?
Following this answer, I'm doing consecutive ray casts:
m_rayCaster = new Qt3DRender::QRayCaster(m_scene->rootEntity());
m_rayCaster->setRunMode(Qt3DRender::QAbstractRayCaster::SingleShot);
m_scene->rootEntity()->addComponent(m_rayCaster);
I have these slots to handle whether and when next consecutive ray cast test should be done:
QObject::connect(m_rayCaster, &Qt3DRender::QRayCaster::hitsChanged, this, &RayCastHandler::handleRayCasterHits);
QObject::connect(m_rayCaster, &Qt3DCore::QNode::enabledChanged, this, &RayCastHandler::handleRayCasterEnabledChange);
QObject::connect(this, &RayCastHandler::isPreviousTestDoneChanged, this, &RayCastHandler::handleIsPreviousTestDoneChange);
QObject::connect(this, &RayCastHandler::isNextTestRequiredChanged, this, &RayCastHandler::handleIsNextTestRequiredChange);
The slots set the conditions and check them:
void RayCastHandler::handleRayCasterHits(const Qt3DRender::QAbstractRayCaster::Hits hits)
{
analyzeHits(hits);
bool required = isNextTestRequired(/* according to m_testCounter, m_testsTotal, ... */);
emit isNextTestRequiredChanged(required);
emit isPreviousTestDoneChanged(true);
return;
}
void RayCastHandler::handleRayCasterEnabledChange(const bool enabled)
{
m_isRayCasterEnabled = enabled;
triggerNextTestIfAllConditionsAreTrue();
return;
}
void RayCastHandler::handleIsPreviousTestDoneChange(const bool done)
{
m_isPreviousTestDone = done;
triggerNextTestIfAllConditionsAreTrue();
return;
}
void RayCastHandler::handleIsNextTestRequiredChange(const bool required)
{
m_isNextTestRequired = required;
if (!m_isNextTestRequired)
emit rayCastResultsChanged(m_collisions);
triggerNextTestIfAllConditionsAreTrue();
return;
}
The code which checks if next ray cast test is required:
bool RayCastHandler::isNextTestRequired(int &testCounter, const int &testsTotal)
{
testCounter++;
if (testCounter >= testsTotal) {
return false;
}
return true;
}
And finally, the function which checks all the conditions to trigger next ray cast test is:
bool RayCastHandler::triggerNextTestIfAllConditionsAreTrue()
{
if (m_isPreviousTestDone && m_isNextTestRequired && m_isRayCasterEnabled) {
triggerTest(/* Will trigger next ray cast test */);
m_isPreviousTestDone = false;
m_isNextTestRequired = false;
m_isRayCasterEnabled = false;
}
}
The code works fine, but after casting a few consecutive rays, it stops.
By logging to console, I observe that the m_rayCaster looks to be enabled/disabled randomly. I mean sometimes after finishing a ray cast test, it disables itself, and sometimes it enables itself! I wonder if anybody can introduce a reference on Qt3DRender::QRayCaster enabling/disabling logic. I looked at its source code a bit, I wonder which section of source code might help me to figure out.
Just wanted to share my observations:
I simplified the code by keeping only two signal-slot connections:
QObject::connect(m_rayCaster, &Qt3DRender::QRayCaster::hitsChanged, this, &RayCastHandler::handleRayCasterHits);
QObject::connect(m_rayCaster, &Qt3DCore::QNode::enabledChanged, this, &RayCastHandler::handleRayCasterEnabledChange);
One slot analyzes the hits of ray-caster:
void RayCastHandler::handleRayCasterHits(const Qt3DRender::QAbstractRayCaster::Hits hits)
{
analyzeHits( ... , hits);
return;
}
The other slot runs the next consecutive ray-cast test, if ray-caster has disabled itself:
void RayCastHandler::handleRayCasterEnabledChange(const bool enabled)
{
// When the component disables itself, it is ready for the next ray-cast test
if (!enabled) {
bool required = isNextTestRequired( ... );
if (required)
triggerTest( ... );
else
// Send final ray-cast results by a signal, if next test is NOT needed
emit rayCastResultsChanged( ... );
}
return;
}
The above code works as long as I trigger ray-cast tests with a time-delay. Sometimes I have to increase the above delay time to make it work. But at least it works. Although it is painful since it is NOT reliable:
void RayCastHandler::triggerTest( ... )
{
...
// 1 millisecond delay time
QTimer::singleShot(1, [rayCaster, origin, direction, length](){rayCaster->trigger(origin, direction, length);});
...
}
However, if I use no delay time, at some point, the ray caster stops unexpectedly, without sending any signal containing hit results, and ray caster stays enabled forever. Looks like ray-caster gets stuck:
void RayCastHandler::triggerTest( ... )
{
...
// No delay
rayCaster->trigger(origin, direction, length);
...
}
I am trying to make a calculator in processing. My thought process for how this is going to work is to make a function for if a certain number is pressed on the keyboard. So I would create some sort of for loop or array even that would sense when a number is pressed, and then return true if it goes through the if statements, however, in order for this to work, I would need to put a variable in the place of a specific key on the keyboard. Is this possible?
Code (so far):
void setup() {
size(800,600);
}
void draw() {
background(0);
Nums.create();
}
class Nums {
void create() {
for (int i = 0; i < 9; i++) {
zero(i);
}
}
boolean zero(int amnt) {
if (keyPressed) {
if (key == amnt) {
return true;
} else {
return false;
}
}
}
}
They keyPressed variable and the functions like keyPressed() and keyReleased() are specifically for keyboard input. They don't, and shouldn't, be concerned with on-screen buttons that you click with the mouse.
Instead, you should probably use the mousePressed() function to detect when the mouse is clicked, and then use if statements to figure out which button was clicked. You can use point-rectangle collision detection to detect which button was clicked. There's also a button sketch in the examples that come with the Processing editor.
I'm using Processing 3.0.1 which is the latest version.
I successed to display the image when I pressed a certain key.
For example, when I press key 'a', then the image will be displayed.
I also want to make the image disappear when I press another key.
However, I can't find a way to do this.
If anyone knows how to do this, please help me
Here is the code
PImage Onepiece1, Onepiece2;
void setup(){
size(600,600);
Onepiece1 = loadImage("Onepiece1.jpg");
Onepiece2 = loadImage("Onepiece2.jpg");
}
void draw(){
}
void showimage1(){
image(Onepiece1,10,10);
}
void keyPressed(){
if(key == 'a'){
showimage1();
}
else if(key == 'b'){
// I want to make the image disappear when I press 'b'
}
println(key);
}
For this simple scenario #Majlik suggestion is ok, but usually it's not a good idea to draw in callback functions like keyPressed(). Instead use a flag to drive drawings in draw(), like:
Untested
PImage Onepiece1, Onepiece2;
boolean showimage = false;
void setup(){
size(600,600);
Onepiece1 = loadImage("Onepiece1.jpg");
Onepiece2 = loadImage("Onepiece2.jpg");
background (255);
}
void draw(){
background (255);
if(showImage){
showImage1();
}
}
void showimage1(){
image(Onepiece1,10,10);
}
void keyPressed(){
if(key == 'a'){
showImage = true;
}
else if(key == 'b'){
showImage = false;
}
println(key);
}
For the simple scenario like this you just need to redraw image with anything. Best practice is to use background() function. So your reaction to pressing b could look like:
if(key == 'b'){
background(99);
}
Also it is good practice to have specified same background color at the beginning inside setup() function:
void setup(){
size(600,600);
...
background(99);
}
I am trying to create a class called InputManager to handle mouse events. This requires that mousePressed be contained within the InputManager class.
like so
class InputManager{
void mousePressed(){
print(hit);
}
}
problem is, that doesn't work. mousePressed() only seems to work when it's outside the class.
How can I get these functions nicely contained in a class?
Try this:
in main sketch:
InputManager im;
void setup() {
im = new InputManager(this);
registerMethod("mouseEvent", im);
}
in InputManager Class:
class InputManager {
void mousePressed(MouseEvent e) {
// mousepressed handling code here...
}
void mouseEvent(MouseEvent e) {
switch(e.getAction()) {
case (MouseEvent.PRESS) :
mousePressed();
break;
case (MouseEvent.CLICK) :
mouseClicked();
break;
// other mouse events cases here...
}
}
}
Once you registered InputManger mouseEvent in PApplet you don't need to call it and it will be called each loop at the end of draw().
Most certainly, but you are responsible for ensuring it gets called:
interface P5EventClass {
void mousePressed();
void mouseMoved();
// ...
}
class InputManager implements P5EventClass {
// we MUST implement mousePressed, and any other interface method
void mousePressed() {
// do things here
}
}
// we're going to hand off all events to things in this list
ArrayList<P5EventClass> eventlisteners = new ArrayList<P5EventClass>();
void setup() {
// bind at least one input manager, but maybe more later on.
eventlisteners.add(new InputManager());
}
void draw() {
// ...
}
void mousePressed() {
// instead of handling input globally, we let
// the event handling obejct(s) take care of it
for(P5EventClass p5ec: eventlisteners) {
p5ec.mousePressed();
}
}
I would personally make it a bit tighter by also passing the event variables explicitly, so "void mousePressed(int x, int y);" in the interface and then calling "p5ec.mousePressed(mouseX, mouseY);" in the sketch body, simply because relying on globals rather than local variables makes your code prone to concurrency bugs.
The easiest way to do so would be:
class InputManager{
void mousePressed(){
print(hit);
}
}
InputManager im = new InputManager();
void setup() {
// ...
}
void draw() {
// ...
}
void mousePressed() {
im.mousePressed();
}
This should solve any problems you were having with variable scoping in your class.
Note: In the class, it doesn't even have to be named mousePressed, you can name it anything you wish, as long as you call it inside of the main mousePressed method.