Hi, Great ! If you need any advice for the Cicm Wrapper, feel free to ask. We can also think to include your objects in the Cream library if you want. In this case, I can give you the access to the GitHub repository.
Cheers, Pierre
Hi,
For the curious, I added a screenshot of the help-patch: http://puredata.info/Members/fjkraan/software/wavesel-help/view and an ogg movie (http://puredata.info/Members/fjkraan/software/wavesel-demo/at_download/file), alas without sound. This version 0.6 works better than 0.5, but still is not based on the Cicm Wrapper.
Hi, Great ! If you need any advice for the Cicm Wrapper, feel free to ask. We can
Well, I was wondering how modifying a fixed set of graphical objects is handled. The wavesel object is made up out of a range of vertical lines, representing the maximum value of the samples they represent. Selecting them is changing the color and moving and resizing a rectangle behind them.
The Cream examples I looked at, only used create, not move and color. Are these supported?
also think to include your objects in the Cream library if you want. In this case, I can give you the access to the GitHub repository.
If the object gets reasonable complete, I will rename it waveform~, and add it to cyclone. But it still can be added to other libraries too.
Cheers, Pierre
Greetings,
Fred Jan
The Cream examples I looked at, only used create, not move and color.
Indeed, you can't change the color or move a graphical object like tk does. In fact I'm not sure that this operations are really optimized (it depends on the OS) and I think this is mostly a kind of "shortcut" (whatever you do, tk has to redraw all the changed area). I've try wavesel~, and my approach would be to create a layer for the rectangle selection, a layer for the whole waveform, a layer for the colored (selected) waveform. If you change the buffer, you have to invalidate all the layers but if you change only the selection, you just have to redraw the selection rectangle and the selected waveform. You can use translation (with matrix) to facilitate and perhaps optimize the drawing. One thing that can be useful is to save paths but it isn't already implemented in the Cicm Wrapper (I'll try to look at it if you want).
If the object gets reasonable complete, I will rename it waveform~, and add it to cyclone. But it still can be added to other libraries too.
This is only a suggestion, I was thinking of making Cream a GUI library only. That why wavesel~ and filterview~ would have been a really good addition to the library. Perhaps a duplicate would bring confusing for users and since Deken has been published I use cyclone so I will be able to enjoy your externals even if they're not in the cream library :)
Cheers
2015-07-07 22:12 GMT+02:00 Fred Jan Kraan fjkraan@xs4all.nl:
Hi,
For the curious, I added a screenshot of the help-patch: http://puredata.info/Members/fjkraan/software/wavesel-help/view and an ogg movie ( http://puredata.info/Members/fjkraan/software/wavesel-demo/at_download/file ), alas without sound. This version 0.6 works better than 0.5, but still is not based on the Cicm Wrapper.
Hi, Great ! If you need any advice for the Cicm Wrapper, feel free to ask. We can
Well, I was wondering how modifying a fixed set of graphical objects is handled. The wavesel object is made up out of a range of vertical lines, representing the maximum value of the samples they represent. Selecting them is changing the color and moving and resizing a rectangle behind them.
The Cream examples I looked at, only used create, not move and color. Are these supported?
also think to include your objects in the Cream library if you want. In this case, I can give you the access to the GitHub repository.
If the object gets reasonable complete, I will rename it waveform~, and add it to cyclone. But it still can be added to other libraries too.
Cheers, Pierre
Greetings,
Fred Jan
Hi Pierre,
The code draws a rectangle and a waveform. See: http://puredata.info/Members/fjkraan/software/cwavesel0.1/image_view.
That is all it does at the moment, it took a while to get some hang of the layer-technology. Currently I invalidate a layer and start by greating a new one. Is this the correct way, or are they reusable in a way?
Greetings,
Fred Jan
Hi Pierre,
Currently, graphics data is drawn to the canvas, but nothing is erased. If I specify a new waveform, it is drawn over the previous one, instead of removing it first.
The real code is a bit messy due to the implementation details, but below is the skeleton, containing the framework interactions and key data. The paint function is called at startup from the framework (via eclass_guiinit?). The redraw function is called when the waveform is changed (manual at the moment).
draw_background function:
draw_waveform function:
paint function:
redraw function:
You can look at the current code in my toy github repository: https://github.com/electrickery/pd-playground/tree/cicm/cicm-wavesel
Greetings,
Fred Jan
Hi,
Currently I invalidate a layer and start by greating a new one. Is this the correct way, or are they reusable in a
way?
Yes, in fact when you create a layer for the 1st time, the function allocates a layer. If the layer already exists but has been invalidated the function returns the old pointer with empty paths. Otherwise, the function returns NULL. If you have a "circle_layer" and a "rectangle_layer" and you want to change the color or the size of the "circle_layer", you have to invalidate the "circle_layer" then when you call ebox_draw, you have to redraw the "circle_layer" but you don't have to redraw the "rectangle_layer".
The paint function is called at startup from the framework (via eclass_guiinit?).
No, eclass_guiinit initializes the class for GUI behavior (the paint function can't be called because there isn't any object allocated).
The redraw function is called when the waveform is changed (manual at the moment).
Yes, when you want to change a layer, you have to invalidate this layer (you don't have to invalidate all the layers if some of them don't need to be redrawn) and then call ebox_redraw().
There's no "redraw", "invalidate", "state" method so eclass_addmethod(c, (method) wavesel_invalidate, "invalidate", A_SYMBOL, 0); eclass_addmethod(c, (method) wavesel_state, "state", A_NULL, 0); eclass_addmethod(c, (method) wavesel_redraw, "redraw", A_NULL, 0); are useless methods. I think you use the c.blackboard as a template but you should prefer to use c.bang or something simpler. c.blackboard is a little bit tricky.
Now I'll try to explain everything better : When the object is allocated in the patch, the method paint is called :
static void wavesel_paint(t_wavesel *x, t_object *view) { t_rect bg_rect; ebox_get_rect_for_view((t_ebox *)x, &bg_rect);
t_elayer *g = ebox_start_layer((t_ebox *)x, bg_layer_name, rect->width,
rect->height); if (g) { Here you can draw what you want in the "bg_layer_name" layer. Then you finish your layer with
} ebox_paint_layer((t_ebox *)x, bg_layer_name, 0.f, 0.f); }
2015-07-10 14:33 GMT+02:00 Fred Jan Kraan fjkraan@xs4all.nl:
Hi Pierre,
Currently, graphics data is drawn to the canvas, but nothing is erased. If I specify a new waveform, it is drawn over the previous one, instead of removing it first.
The real code is a bit messy due to the implementation details, but below is the skeleton, containing the framework interactions and key data. The paint function is called at startup from the framework (via eclass_guiinit?). The redraw function is called when the waveform is changed (manual at the moment).
draw_background function:
- ebox_start_layer(background_layer)
- ebox_paint_layer()
draw_waveform function:
- ebox_start_layer(waveform_layer)
- egraphics_line_fast(... here the waveform is defined ...)
- ebox_end_layer()
- ebox_paint_layer()
paint function:
- draw_background()
- draw_waveform()
redraw function:
- ebox_invalidate_layer(background_layer)
- ebox_invalidate_layer(waveform_layer)
- paint()
- ebox_redraw()
You can look at the current code in my toy github repository: https://github.com/electrickery/pd-playground/tree/cicm/cicm-wavesel
Greetings,
Fred Jan
Hi (sorry the message wasn't finished....),
Currently I invalidate a layer and start by greating a new one. Is this the correct way, or are they reusable in a
way?
Yes, in fact when you create a layer for the 1st time, the function allocates a layer. If the layer already exists but has been invalidated the function returns the old pointer with empty paths. Otherwise, the function returns NULL. If you have a "circle_layer" and a "rectangle_layer" and you want to change the color or the size of the "circle_layer", you have to invalidate the "circle_layer" then when you call ebox_draw, you have to redraw the "circle_layer" but you don't have to redraw the "rectangle_layer".
The paint function is called at startup from the framework (via eclass_guiinit?).
No, eclass_guiinit initializes the class for GUI behavior (the paint function can't be called because there isn't any object allocated).
The redraw function is called when the waveform is changed (manual at the moment).
Yes, when you want to change a layer, you have to invalidate this layer (you don't have to invalidate all the layers if some of themdon't need to be redrawn) and then call ebox_redraw().
There's no "redraw", "invalidate", "state" method so eclass_addmethod(c, (method) wavesel_invalidate, "invalidate", A_SYMBOL, 0); eclass_addmethod(c, (method) wavesel_state, "state", A_NULL, 0); eclass_addmethod(c, (method) wavesel_redraw, "redraw", A_NULL, 0); are useless methods. I think you use the c.blackboard as a template but you should prefer to use c.bang or something simpler. c.blackboard is a little bit tricky.
Now I'll try to explain everything better :
static void wavesel_paint(t_wavesel *x, t_object *view) { t_rect bg_rect; ebox_get_rect_for_view((t_ebox *)x, &bg_rect);
// Background layer t_elayer *g = ebox_start_layer((t_ebox *)x, bg_layer_name, rect->width, rect->height); if (g) { Here you can draw what you want in the "bg_layer_name" layer. Then you finish your layer with : ebox_end_layer((t_ebox*)x, bg_layer_name); } ebox_paint_layer((t_ebox *)x, bg_layer_name, 0.f, 0.f); // The box paint the layer
// Waveform layer t_elayer *g = ebox_start_layer((t_ebox *)x, fg_layer_name, rect->width, rect->height); if (g) { Here you can draw what you want in the "fg_layer_name" layer. Then you finish your layer with : ebox_end_layer((t_ebox*)x, fg_layer_name); } ebox_paint_layer((t_ebox *)x, fg_layer_name, 0.f, 0.f); // The box paint the layer }
Now you want to change the "fg_layer_name" layer when the buffer has changed for example :
static void wavesel_setarray(t_wavesel *x, t_symbol *s) { // Load the new buffer ebox_invalidate_layer((t_ebox *)x, fg_layer_name); << invalidate "fg_layer_name" the layer (the "bg_layer_name" doesn't change so you don't have to invalidate the layer) ebox_redraw((t_ebox *)x); // the function calls the paint method of the object (and some other stuff) // // You don't have to call wavesel_paint(x, 0); }
The Graphic API is very similar to the Max's Graphical API so you can also have a look at it but a lot of thing are explained here : http://cicm.github.io/CicmWrapper/a00002.html
Cheers
2015-07-11 16:18 GMT+02:00 Pierre Guillot guillotpierre6@gmail.com:
Hi,
Currently I invalidate a layer and start by greating a new one. Is this the correct way, or are they reusable in a
way?
Yes, in fact when you create a layer for the 1st time, the function allocates a layer. If the layer already exists but has been invalidated the function returns the old pointer with empty paths. Otherwise, the function returns NULL. If you have a "circle_layer" and a "rectangle_layer" and you want to change the color or the size of the "circle_layer", you have to invalidate the "circle_layer" then when you call ebox_draw, you have to redraw the "circle_layer" but you don't have to redraw the "rectangle_layer".
The paint function is called at startup from the framework (via eclass_guiinit?).
No, eclass_guiinit initializes the class for GUI behavior (the paint function can't be called because there isn't any object allocated).
The redraw function is called when the waveform is changed (manual at the moment).
Yes, when you want to change a layer, you have to invalidate this layer (you don't have to invalidate all the layers if some of them don't need to be redrawn) and then call ebox_redraw().
There's no "redraw", "invalidate", "state" method so eclass_addmethod(c, (method) wavesel_invalidate, "invalidate", A_SYMBOL, 0 ); eclass_addmethod(c, (method) wavesel_state, "state", A_NULL, 0); eclass_addmethod(c, (method) wavesel_redraw, "redraw", A_NULL, 0); are useless methods. I think you use the c.blackboard as a template but you should prefer to use c.bang or something simpler. c.blackboard is a little bit tricky.
Now I'll try to explain everything better : When the object is allocated in the patch, the method paint is called :
static void wavesel_paint(t_wavesel *x, t_object *view) { t_rect bg_rect; ebox_get_rect_for_view((t_ebox *)x, &bg_rect);
t_elayer *g = ebox_start_layer((t_ebox *)x, bg_layer_name,
rect->width, rect->height); if (g) { Here you can draw what you want in the "bg_layer_name" layer. Then you finish your layer with
} ebox_paint_layer((t_ebox *)x, bg_layer_name, 0.f, 0.f); }
2015-07-10 14:33 GMT+02:00 Fred Jan Kraan fjkraan@xs4all.nl:
Hi Pierre,
Currently, graphics data is drawn to the canvas, but nothing is erased. If I specify a new waveform, it is drawn over the previous one, instead of removing it first.
The real code is a bit messy due to the implementation details, but below is the skeleton, containing the framework interactions and key data. The paint function is called at startup from the framework (via eclass_guiinit?). The redraw function is called when the waveform is changed (manual at the moment).
draw_background function:
- ebox_start_layer(background_layer)
- ebox_paint_layer()
draw_waveform function:
- ebox_start_layer(waveform_layer)
- egraphics_line_fast(... here the waveform is defined ...)
- ebox_end_layer()
- ebox_paint_layer()
paint function:
- draw_background()
- draw_waveform()
redraw function:
- ebox_invalidate_layer(background_layer)
- ebox_invalidate_layer(waveform_layer)
- paint()
- ebox_redraw()
You can look at the current code in my toy github repository: https://github.com/electrickery/pd-playground/tree/cicm/cicm-wavesel
Greetings,
Fred Jan
Hi Pierre,
Hi,
Currently I invalidate a layer and start by greating a new one. Is this the correct way, or are they reusable in a way?
Yes, in fact when you create a layer for the 1st time, the function allocates a layer. If the layer already exists but has been invalidated the function returns the old pointer with empty paths. Otherwise, the function returns NULL. If you have a "circle_layer" and a "rectangle_layer" and you want to change the color or the size of the "circle_layer", you have to invalidate the "circle_layer" then when you call ebox_draw, you have to redraw the "circle_layer" but you don't have to redraw the "rectangle_layer".
In th emean time, I found the problem with superimposed waveforms is elsewhere, not the object code. With minimize and restore only the latest waveform is rendered*. So I expect it is in the Tk or g_canvas code, as the non-cicm version of wavesel~ has the similar problem (not properly updating the screen, fixed with minimize and restore the window). It might be the platform: Xubuntu 14.04 with Tk 8.5.
The paint function is called at startup from the framework (via eclass_guiinit?).
No, eclass_guiinit initializes the class for GUI behavior (the paint function can't be called because there isn't any object allocated).
The redraw function is called when the waveform is changed (manual at the moment).
Yes, when you want to change a layer, you have to invalidate this layer (you don't have to invalidate all the layers if some of them don't need to be redrawn) and then call ebox_redraw().
There's no "redraw", "invalidate", "state" method so eclass_addmethod(c, (method) wavesel_invalidate, "invalidate", A_SYMBOL, 0); eclass_addmethod(c, (method) wavesel_state, "state", A_NULL, 0); eclass_addmethod(c, (method) wavesel_redraw, "redraw", A_NULL, 0); are useless methods.
Not in my object. I try to understand what is happening and why it doesn't do what I want to, so I cut the proces into small steps and check the in-between status (this is what state does).
They are useless in the sense that they have no function in a properly working object. The object isn't there yet, but in the process of debugging and adding functionality.
I think you use the c.blackboard as a template but you should prefer to use c.bang or something simpler. c.blackboard is a little bit tricky.
Yes, I started with c.blackboard but moved elsewhere. c.bang surely has a lot more comments!
Now I'll try to explain everything better : When the object is allocated in the patch, the method paint is called :
static void wavesel_paint(t_wavesel *x, t_object *view) { t_rect bg_rect; ebox_get_rect_for_view((t_ebox *)x, &bg_rect);
t_elayer *g = ebox_start_layer((t_ebox *)x, bg_layer_name,
rect->width, rect->height); if (g) { Here you can draw what you want in the "bg_layer_name" layer. Then you finish your layer with
} ebox_paint_layer((t_ebox *)x, bg_layer_name, 0.f, 0.f); }
This is more or less what is happening, and it works. Apart from the update issue described above.
Currently the waveform is drawn and the layer state is EGRAPHICS_CLOSE as expected. But after minimize and restore it is EGRAPHICS_TODRAW again! I cannot see how the paint function causes this.
I will change the platform and see what happens.
Greetings,
Fred Jan
*) Somewhere in the code cleanup, the waveform restore doesn't happen anymore.
Hi Fred Jan,
When you minimize a patch, It seems that the canvas doesn't send any notification. But when you restore a patch the canvas calls the visible method (with the argument visible 1). So my temporary solution (because the call of the visible function seems also to be platform specific) is to recreate the object's widget each time the function is called (the precedent widget should already be destroyed, you shouldn't have to take care of this).
I'm going to pull your code and make some tests. It will be easier for me to see if something strange happens.
Cheers
2015-07-12 12:08 GMT+02:00 Fred Jan Kraan fjkraan@xs4all.nl:
Hi Pierre,
Hi,
Currently I invalidate a layer and start by greating a new one. Is this the correct way, or are they reusable in a
way?
Yes, in fact when you create a layer for the 1st time, the function allocates a layer. If the layer already exists but has been invalidated the function returns the old pointer with empty paths. Otherwise, the function returns NULL. If you have a "circle_layer" and a "rectangle_layer" and you want to change the color or the size of the "circle_layer", you have to invalidate the "circle_layer" then when you call ebox_draw, you have to redraw the "circle_layer" but you don't have to redraw the "rectangle_layer".
In th emean time, I found the problem with superimposed waveforms is elsewhere, not the object code. With minimize and restore only the latest waveform is rendered*. So I expect it is in the Tk or g_canvas code, as the non-cicm version of wavesel~ has the similar problem (not properly updating the screen, fixed with minimize and restore the window). It might be the platform: Xubuntu 14.04 with Tk 8.5.
The paint function is called at startup from the framework (via eclass_guiinit?).
No, eclass_guiinit initializes the class for GUI behavior (the paint function can't be called because there isn't any object allocated).
The redraw function is called when the waveform is changed (manual at the moment).
Yes, when you want to change a layer, you have to invalidate this layer (you don't have to invalidate all the layers if some of them don't need to be redrawn) and then call ebox_redraw().
There's no "redraw", "invalidate", "state" method so eclass_addmethod(c, (method) wavesel_invalidate, "invalidate", A_SYMBOL,
0);
eclass_addmethod(c, (method) wavesel_state, "state", A_NULL, 0); eclass_addmethod(c, (method) wavesel_redraw, "redraw", A_NULL, 0); are useless methods.
Not in my object. I try to understand what is happening and why it doesn't do what I want to, so I cut the proces into small steps and check the in-between status (this is what state does).
They are useless in the sense that they have no function in a properly working object. The object isn't there yet, but in the process of debugging and adding functionality.
I think you use the c.blackboard as a template but you should prefer to use c.bang or something simpler. c.blackboard is a little bit tricky.
Yes, I started with c.blackboard but moved elsewhere. c.bang surely has a lot more comments!
Now I'll try to explain everything better : When the object is allocated in the patch, the method paint is called :
static void wavesel_paint(t_wavesel *x, t_object *view) { t_rect bg_rect; ebox_get_rect_for_view((t_ebox *)x, &bg_rect);
t_elayer *g = ebox_start_layer((t_ebox *)x, bg_layer_name,
rect->width, rect->height); if (g) { Here you can draw what you want in the "bg_layer_name" layer. Then you finish your layer with
} ebox_paint_layer((t_ebox *)x, bg_layer_name, 0.f, 0.f); }
This is more or less what is happening, and it works. Apart from the update issue described above.
Currently the waveform is drawn and the layer state is EGRAPHICS_CLOSE as expected. But after minimize and restore it is EGRAPHICS_TODRAW again! I cannot see how the paint function causes this.
I will change the platform and see what happens.
Greetings,
Fred Jan
*) Somewhere in the code cleanup, the waveform restore doesn't happen anymore.
Hi Pierre,
Thank you for your fast response.
I did some more testing; a 32-bit Xubuntu works exactly like the 64-bit variant, so no 64-bit related issues here.
Compiling on my old Mac (10.5) fails. At first it complains about the combination of several flags and multiple architectures, and after reducing these to just -arch i386, the Cream library fails on compile errors in Deprecated/AudioFFT.cpp.
But with some extra post messages, I traced the development of the state of the foreground layer (= waveform layer).
number),
This is with the help patch, eventually the setarray should include redraw.
Fred Jan