#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_filter.h>
+#include <vlc_rand.h>
#include "filter_picture.h"
set_category( CAT_VIDEO )
set_subcategory( SUBCAT_VIDEO_VFILTER )
- add_integer_with_range( CFG_PREFIX "rows", 4, 1, 128, NULL,
+ add_integer_with_range( CFG_PREFIX "rows", 4, 2, 16, NULL,
ROWS_TEXT, ROWS_LONGTEXT, false )
- add_integer_with_range( CFG_PREFIX "cols", 4, 1, 128, NULL,
+ add_integer_with_range( CFG_PREFIX "cols", 4, 2, 16, NULL,
COLS_TEXT, COLS_LONGTEXT, false )
- add_bool( CFG_PREFIX "black-slot", 0, NULL,
+ add_bool( CFG_PREFIX "black-slot", false, NULL,
BLACKSLOT_TEXT, BLACKSLOT_LONGTEXT, false )
set_callbacks( Open, Close )
filter_sys_t *p_sys;
/* */
- if( memcmp( &p_filter->fmt_in, &p_filter->fmt_out, sizeof(p_filter->fmt_in) ) )
+ if( !es_format_IsSimilar( &p_filter->fmt_in, &p_filter->fmt_out ) )
{
msg_Err( p_filter, "Input and output format does not match" );
return VLC_EGENERIC;
var_AddCallback( p_filter, CFG_PREFIX "black-slot", PuzzleCallback, p_sys );
p_filter->pf_video_filter = Filter;
- p_filter->pf_mouse = Mouse;
+ p_filter->pf_video_mouse = Mouse;
return VLC_SUCCESS;
}
const int i_rows = p_sys->i_rows;
const int i_cols = p_sys->i_cols;
- /* */
+ /* Draw each piece of the puzzle at the right place */
for( int i_plane = 0; i_plane < p_outpic->i_planes; i_plane++ )
{
const plane_t *p_in = &p_pic->p[i_plane];
- const int i_pitch = p_in->i_pitch;
plane_t *p_out = &p_outpic->p[i_plane];
for( int i = 0; i < i_cols * i_rows; i++ )
{
- int i_col = i % i_cols;
- int i_row = i / i_cols;
- int i_ocol = p_sys->pi_order[i] % i_cols;
- int i_orow = p_sys->pi_order[i] / i_cols;
- int i_last_row = i_row + 1;
- i_orow *= p_in->i_lines / i_rows;
- i_row *= p_in->i_lines / i_rows;
- i_last_row *= p_in->i_lines / i_rows;
-
- if( p_sys->b_blackslot && p_sys->b_finished && i == p_sys->i_selected )
+ int i_piece_height = p_out->i_visible_lines / i_rows;
+ int i_piece_width = p_out->i_visible_pitch / i_cols;
+
+ int i_col = (i % i_cols) * i_piece_width;
+ int i_row = (i / i_cols) * i_piece_height;
+ int i_last_row = i_row + i_piece_height;
+
+ int i_ocol = (p_sys->pi_order[i] % i_cols) * i_piece_width;
+ int i_orow = (p_sys->pi_order[i] / i_cols) * i_piece_height;
+
+ if( p_sys->b_blackslot && !p_sys->b_finished && i == p_sys->i_selected )
{
uint8_t color = ( i_plane == Y_PLANE ? 0x0 : 0x80 );
- for( ; i_row < i_last_row; i_row++, i_orow++ )
+ for( int r = i_row; r < i_last_row; r++ )
{
- memset( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols,
- color, i_pitch / i_cols );
+ memset( p_out->p_pixels + r * p_out->i_pitch + i_col,
+ color, i_piece_width );
}
}
else
{
- for( ; i_row < i_last_row; i_row++, i_orow++ )
+ for( int r = i_row, or = i_orow; r < i_last_row; r++, or++ )
{
- memcpy( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols,
- p_in->p_pixels + i_orow * i_pitch + i_ocol * i_pitch / i_cols,
- i_pitch / i_cols );
+ memcpy( p_out->p_pixels + r * p_out->i_pitch + i_col,
+ p_in->p_pixels + or * p_in->i_pitch + i_ocol,
+ i_piece_width );
}
}
- }
- }
-
- if( p_sys->i_selected != -1 && !p_sys->b_blackslot )
- {
- const plane_t *p_in = &p_pic->p[Y_PLANE];
- const int i_pitch = p_in->i_pitch;
- plane_t *p_out = &p_outpic->p[Y_PLANE];
- int i_col = p_sys->i_selected % i_cols;
- int i_row = p_sys->i_selected / i_cols;
- int i_last_row = i_row + 1;
- i_row *= p_in->i_lines / i_rows;
- i_last_row *= p_in->i_lines / i_rows;
- memset( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols,
- 0xff, i_pitch / i_cols );
- for( ; i_row < i_last_row; i_row++ )
- {
- p_out->p_pixels[ i_row * i_pitch
- + i_col * i_pitch / i_cols ] = 0xff;
- p_out->p_pixels[ i_row * i_pitch
- + (i_col+1) * i_pitch / i_cols - 1 ] = 0xff;
+ /* Draw the borders of the selected slot */
+ if( i_plane == 0 && !p_sys->b_blackslot && p_sys->i_selected == i )
+ {
+ memset( p_out->p_pixels + i_row * p_out->i_pitch + i_col,
+ 0xff, i_piece_width );
+ for( int r = i_row; r < i_last_row; r++ )
+ {
+ p_out->p_pixels[r * p_out->i_pitch + i_col + 0 + 0 ] = 0xff;
+ p_out->p_pixels[r * p_out->i_pitch + i_col + i_piece_width - 1 ] = 0xff;
+ }
+ memset( p_out->p_pixels + (i_last_row - 1) * p_out->i_pitch + i_col,
+ 0xff, i_piece_width );
+ }
}
- i_row--;
- memset( p_out->p_pixels + i_row * i_pitch + i_col * i_pitch / i_cols,
- 0xff, i_pitch / i_cols );
}
+ /* Draw the 'Shuffle' button if the puzzle is finished */
if( p_sys->b_finished )
{
plane_t *p_out = &p_outpic->p[Y_PLANE];
filter_sys_t *p_sys = p_filter->p_sys;
const video_format_t *p_fmt = &p_filter->fmt_in.video;
+ /* Only take events inside the puzzle erea */
if( p_new->i_x < 0 || p_new->i_x >= (int)p_fmt->i_width ||
p_new->i_y < 0 || p_new->i_y >= (int)p_fmt->i_height )
return VLC_EGENERIC;
/* */
const bool b_clicked = vlc_mouse_HasPressed( p_old, p_new, MOUSE_BUTTON_LEFT );
+ /* If the puzzle is finished, shuffle it if needed */
if( p_sys->b_finished )
{
if( b_clicked &&
|| p_sys->i_selected == i_pos + p_sys->i_cols
|| p_sys->i_selected == i_pos - p_sys->i_cols )
{
+ /* Swap two pieces */
int a = p_sys->pi_order[ p_sys->i_selected ];
p_sys->pi_order[ p_sys->i_selected ] = p_sys->pi_order[ i_pos ];
p_sys->pi_order[ i_pos ] = a;
- if( p_sys->b_blackslot )
- p_sys->i_selected = i_pos;
- else
- p_sys->i_selected = -1;
-
+ p_sys->i_selected = p_sys->b_blackslot ? i_pos : -1;
p_sys->b_finished = IsFinished( p_sys );
}
return VLC_EGENERIC;
{
const int i_count = p_sys->i_cols * p_sys->i_rows;
- if( p_sys->b_blackslot )
+ if( !p_sys->b_blackslot )
return true;
int d = 0;
static void Shuffle( filter_sys_t *p_sys )
{
- const int i_count = p_sys->i_cols * p_sys->i_rows;
+ const unsigned i_count = p_sys->i_cols * p_sys->i_rows;
free( p_sys->pi_order );
p_sys->pi_order = calloc( i_count, sizeof(*p_sys->pi_order) );
do
{
- for( int i = 0; i < i_count; i++ )
+ for( unsigned i = 0; i < i_count; i++ )
p_sys->pi_order[i] = -1;
- for( int c = 0; c < i_count; )
+ for( unsigned c = 0; c < i_count; )
{
- int i = rand() % i_count;
+ unsigned i = ((unsigned)vlc_mrand48()) % i_count;
if( p_sys->pi_order[i] == -1 )
p_sys->pi_order[i] = c++;
}
p_sys->b_finished = IsFinished( p_sys );
- } while( p_sys->b_finished || IsValid( p_sys ) );
+ } while( p_sys->b_finished || !IsValid( p_sys ) );
if( p_sys->b_blackslot )
{
- for( int i = 0; i < i_count; i++ )
+ for( unsigned i = 0; i < i_count; i++ )
{
if( p_sys->pi_order[i] == i_count - 1 )
{