Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-2-2
Commits
4b4f62a0
Commit
4b4f62a0
authored
Apr 15, 2013
by
Vianney BOYER
Committed by
Jean-Baptiste Kempf
Apr 30, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Puzzle: main filter update
Signed-off-by:
Jean-Baptiste Kempf
<
jb@videolan.org
>
parent
b9730ca6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
754 additions
and
261 deletions
+754
-261
modules/video_filter/Modules.am
modules/video_filter/Modules.am
+10
-2
modules/video_filter/puzzle.c
modules/video_filter/puzzle.c
+666
-259
modules/video_filter/puzzle.h
modules/video_filter/puzzle.h
+78
-0
No files found.
modules/video_filter/Modules.am
View file @
4b4f62a0
...
...
@@ -52,6 +52,16 @@ if HAVE_GCRYPT
libvlc_LTLIBRARIES += libremoteosd_plugin.la
endif
libpuzzle_plugin_la_SOURCES = \
puzzle.c puzzle.h \
puzzle_bezier.c puzzle_bezier.h \
puzzle_lib.c puzzle_lib.h \
puzzle_mgt.c puzzle_mgt.h \
puzzle_pce.c puzzle_pce.h
libpuzzle_plugin_la_CFLAGS = $(AM_CFLAGS)
libpuzzle_plugin_la_LIBADD = $(AM_LIBADD)
libvlc_LTLIBRARIES += libpuzzle_plugin.la
SOURCES_magnify = magnify.c
SOURCES_wave = wave.c
SOURCES_ripple = ripple.c
...
...
@@ -75,7 +85,6 @@ SOURCES_rotate = \
$(motion_extra) \
$(NULL)
SOURCES_puzzle = puzzle.c
SOURCES_colorthres = colorthres.c
SOURCES_extract = extract.c
SOURCES_sharpen = sharpen.c
...
...
@@ -149,7 +158,6 @@ libvlc_LTLIBRARIES += \
libmotiondetect_plugin.la \
libposterize_plugin.la \
libpsychedelic_plugin.la \
libpuzzle_plugin.la \
libripple_plugin.la \
librotate_plugin.la \
librss_plugin.la \
...
...
modules/video_filter/puzzle.c
View file @
4b4f62a0
...
...
@@ -2,9 +2,11 @@
* puzzle.c : Puzzle game
*****************************************************************************
* Copyright (C) 2005-2009 VLC authors and VideoLAN
* Copyright (C) 2013 Vianney Boyer
* $Id$
*
* Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
* Vianney Boyer <vlcvboyer -at- gmail -dot- com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
...
...
@@ -37,6 +39,12 @@
#include "filter_picture.h"
#include "puzzle.h"
#include "puzzle_bezier.h"
#include "puzzle_lib.h"
#include "puzzle_pce.h"
#include "puzzle_mgt.h"
/*****************************************************************************
* Module descriptor
*****************************************************************************/
...
...
@@ -44,13 +52,32 @@
#define ROWS_LONGTEXT N_("Number of puzzle rows")
#define COLS_TEXT N_("Number of puzzle columns")
#define COLS_LONGTEXT N_("Number of puzzle columns")
#define BLACKSLOT_TEXT N_("Make one tile a black slot")
#define BLACKSLOT_LONGTEXT N_("Make one slot black. Other tiles can only be swapped with the black slot.")
#define MODE_TEXT N_("Game mode")
#define MODE_LONGTEXT N_("Select game mode variation from jigsaw puzzle to sliding puzzle.")
#define BORDER_TEXT N_("Border")
#define BORDER_LONGTEXT N_("Unshuffled Border width.")
#define PREVIEW_TEXT N_("Small preview")
#define PREVIEW_LONGTEXT N_("Show small preview.")
#define PREVIEWSIZE_TEXT N_("Small preview size")
#define PREVIEWSIZE_LONGTEXT N_("Show small preview size (percent of source).")
#define SHAPE_SIZE_TEXT N_("Piece edge shape size")
#define SHAPE_SIZE_LONGTEXT N_("Size of the curve along the piece's edge")
#define AUTO_SHUFFLE_TEXT N_("Auto shuffle")
#define AUTO_SHUFFLE_LONGTEXT N_("Auto shuffle delay during game")
#define AUTO_SOLVE_TEXT N_("Auto solve")
#define AUTO_SOLVE_LONGTEXT N_("Auto solve delay during game")
#define ROTATION_TEXT N_("Rotation")
#define ROTATION_LONGTEXT N_("Rotation parameter: none;180;90-270;mirror")
const
int
pi_mode_values
[]
=
{
(
int
)
0
,
(
int
)
1
,
(
int
)
2
,
(
int
)
3
};
const
char
*
const
ppsz_mode_descriptions
[]
=
{
N_
(
"jigsaw puzzle"
),
N_
(
"sliding puzzle"
),
N_
(
"swap puzzle"
),
N_
(
"exchange puzzle"
)
};
const
int
pi_rotation_values
[]
=
{
(
int
)
0
,
(
int
)
1
,
(
int
)
2
,
(
int
)
3
};
const
char
*
const
ppsz_rotation_descriptions
[]
=
{
N_
(
"0"
),
N_
(
"0/180"
),
N_
(
"0/90/180/270"
),
N_
(
"0/90/180/270/mirror"
)
};
#define CFG_PREFIX "puzzle-"
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
int
Open
(
vlc_object_t
*
);
void
Close
(
vlc_object_t
*
);
vlc_module_begin
()
set_description
(
N_
(
"Puzzle interactive game video filter"
)
)
...
...
@@ -63,107 +90,114 @@ vlc_module_begin()
ROWS_TEXT
,
ROWS_LONGTEXT
,
false
)
add_integer_with_range
(
CFG_PREFIX
"cols"
,
4
,
2
,
16
,
COLS_TEXT
,
COLS_LONGTEXT
,
false
)
add_bool
(
CFG_PREFIX
"black-slot"
,
false
,
BLACKSLOT_TEXT
,
BLACKSLOT_LONGTEXT
,
false
)
add_integer_with_range
(
CFG_PREFIX
"border"
,
3
,
0
,
40
,
BORDER_TEXT
,
BORDER_LONGTEXT
,
false
)
add_bool
(
CFG_PREFIX
"preview"
,
false
,
PREVIEW_TEXT
,
PREVIEW_LONGTEXT
,
false
)
add_integer_with_range
(
CFG_PREFIX
"preview-size"
,
15
,
0
,
100
,
PREVIEWSIZE_TEXT
,
PREVIEWSIZE_LONGTEXT
,
false
)
add_integer_with_range
(
CFG_PREFIX
"shape-size"
,
90
,
0
,
100
,
SHAPE_SIZE_TEXT
,
SHAPE_SIZE_LONGTEXT
,
false
)
add_integer_with_range
(
CFG_PREFIX
"auto-shuffle"
,
0
,
0
,
30000
,
AUTO_SHUFFLE_TEXT
,
AUTO_SHUFFLE_LONGTEXT
,
false
)
add_integer_with_range
(
CFG_PREFIX
"auto-solve"
,
0
,
0
,
30000
,
AUTO_SOLVE_TEXT
,
AUTO_SOLVE_LONGTEXT
,
false
)
add_integer
(
CFG_PREFIX
"rotation"
,
0
,
ROTATION_TEXT
,
ROTATION_LONGTEXT
,
false
)
change_integer_list
(
pi_rotation_values
,
ppsz_rotation_descriptions
)
add_integer
(
CFG_PREFIX
"mode"
,
0
,
MODE_TEXT
,
MODE_LONGTEXT
,
false
)
change_integer_list
(
pi_mode_values
,
ppsz_mode_descriptions
)
set_callbacks
(
Open
,
Close
)
vlc_module_end
()
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
const
char
*
const
ppsz_filter_options
[]
=
{
"rows"
,
"cols"
,
"black-slot"
,
NULL
};
static
picture_t
*
Filter
(
filter_t
*
,
picture_t
*
);
static
int
Mouse
(
filter_t
*
,
vlc_mouse_t
*
,
const
vlc_mouse_t
*
,
const
vlc_mouse_t
*
);
static
bool
IsFinished
(
filter_sys_t
*
);
static
void
Shuffle
(
filter_sys_t
*
);
static
int
PuzzleCallback
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
struct
filter_sys_t
{
/* */
int
i_cols
;
int
i_rows
;
bool
b_blackslot
;
int
*
pi_order
;
int
i_selected
;
bool
b_finished
;
/* */
struct
{
atomic_flag
b_uptodate
;
atomic_bool
b_blackslot
;
atomic_uint
i_cols
;
atomic_uint
i_rows
;
}
change
;
const
char
*
const
ppsz_filter_options
[]
=
{
"rows"
,
"cols"
,
"border"
,
"preview"
,
"preview-size"
,
"mode"
,
"shape-size"
,
"auto-shuffle"
,
"auto-solve"
,
"rotation"
,
NULL
};
#define SHUFFLE_WIDTH 81
#define SHUFFLE_HEIGHT 13
static
const
char
*
shuffle_button
[]
=
{
"................................................................................."
,
".............. ............................ ........ ...... ..............."
,
".............. ........................... ......... ........ ..............."
,
".............. ........................... ......... ........ ..............."
,
".. ....... . ....... .... ...... ...... ...... ........ ..."
,
". .... ...... ... ...... .... ....... ......... ........ ....... .. .."
,
". ........... .... ...... .... ....... ......... ........ ...... .... ."
,
". ....... .... ...... .... ....... ......... ........ ...... ."
,
".. ...... .... ...... .... ....... ......... ........ ...... ......."
,
"...... ...... .... ...... .... ....... ......... ........ ...... ......."
,
". .... ...... .... ...... ... ....... ......... ........ ....... .... ."
,
".. ....... .... ....... . ....... ......... ........ ........ .."
,
"................................................................................."
};
/**
* Open the filter
*/
static
int
Open
(
vlc_object_t
*
p_this
)
int
Open
(
vlc_object_t
*
p_this
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
;
/* */
if
(
!
es_format_IsSimilar
(
&
p_filter
->
fmt_in
,
&
p_filter
->
fmt_out
)
)
{
/* Assert video in match with video out */
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
;
}
/* Allocate structure */
p_filter
->
p_sys
=
p_sys
=
malloc
(
sizeof
(
*
p_sys
)
);
p_filter
->
p_sys
=
p_sys
=
calloc
(
1
,
sizeof
(
*
p_sys
)
);
if
(
!
p_sys
)
return
VLC_ENOMEM
;
config_ChainParse
(
p_filter
,
CFG_PREFIX
,
ppsz_filter_options
,
p_filter
->
p_cfg
);
/* init some values */
p_sys
->
b_shuffle_rqst
=
true
;
p_sys
->
b_change_param
=
true
;
p_sys
->
i_mouse_drag_pce
=
NO_PCE
;
p_sys
->
i_pointed_pce
=
NO_PCE
;
p_sys
->
i_magnet_accuracy
=
3
;
p_sys
->
pi_order
=
NULL
;
/* Generate values of random bezier shapes */
p_sys
->
ps_bezier_pts_H
=
calloc
(
SHAPES_QTY
,
sizeof
(
point_t
*
)
);
if
(
!
p_sys
->
ps_bezier_pts_H
)
{
free
(
p_filter
->
p_sys
);
p_filter
->
p_sys
=
NULL
;
return
VLC_ENOMEM
;
}
for
(
int32_t
i_shape
=
0
;
i_shape
<
SHAPES_QTY
;
i_shape
++
)
p_sys
->
ps_bezier_pts_H
[
i_shape
]
=
puzzle_rand_bezier
(
7
);
atomic_init
(
&
p_sys
->
change
.
i_rows
,
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"rows"
)
);
atomic_init
(
&
p_sys
->
change
.
i_cols
,
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"cols"
)
);
atomic_init
(
&
p_sys
->
change
.
b_blackslot
,
var_CreateGetBoolCommand
(
p_filter
,
CFG_PREFIX
"black-slot"
)
);
p_sys
->
change
.
b_uptodate
=
ATOMIC_FLAG_INIT
;
var_AddCallback
(
p_filter
,
CFG_PREFIX
"rows"
,
PuzzleCallback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"cols"
,
PuzzleCallback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"black-slot"
,
PuzzleCallback
,
p_sys
);
config_ChainParse
(
p_filter
,
CFG_PREFIX
,
ppsz_filter_options
,
p_filter
->
p_cfg
);
vlc_mutex_init
(
&
p_sys
->
lock
);
vlc_mutex_init
(
&
p_sys
->
pce_lock
);
p_sys
->
s_new_param
.
i_rows
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"rows"
);
p_sys
->
s_new_param
.
i_cols
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"cols"
);
p_sys
->
s_new_param
.
i_border
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"border"
);
p_sys
->
s_new_param
.
b_preview
=
var_CreateGetBoolCommand
(
p_filter
,
CFG_PREFIX
"preview"
);
p_sys
->
s_new_param
.
i_preview_size
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"preview-size"
);
p_sys
->
s_new_param
.
i_shape_size
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"shape-size"
);
p_sys
->
s_new_param
.
i_auto_shuffle_speed
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"auto-shuffle"
);
p_sys
->
s_new_param
.
i_auto_solve_speed
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"auto-solve"
);
p_sys
->
s_new_param
.
i_rotate
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"rotation"
);
p_sys
->
s_new_param
.
i_mode
=
var_CreateGetIntegerCommand
(
p_filter
,
CFG_PREFIX
"mode"
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"rows"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"cols"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"border"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"preview"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"preview-size"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"shape-size"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"auto-shuffle"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"auto-solve"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"rotation"
,
puzzle_Callback
,
p_sys
);
var_AddCallback
(
p_filter
,
CFG_PREFIX
"mode"
,
puzzle_Callback
,
p_sys
);
p_filter
->
pf_video_filter
=
Filter
;
p_filter
->
pf_video_mouse
=
M
ouse
;
p_filter
->
pf_video_mouse
=
puzzle_m
ouse
;
return
VLC_SUCCESS
;
}
...
...
@@ -171,271 +205,644 @@ static int Open( vlc_object_t *p_this )
/**
* Close the filter
*/
static
void
Close
(
vlc_object_t
*
p_this
)
{
void
Close
(
vlc_object_t
*
p_this
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
var_DelCallback
(
p_filter
,
CFG_PREFIX
"rows"
,
PuzzleCallback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"cols"
,
PuzzleCallback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"black-slot"
,
PuzzleCallback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"rows"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"cols"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"border"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"preview"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"preview-size"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"shape-size"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"auto-shuffle"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"auto-solve"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"rotation"
,
puzzle_Callback
,
p_sys
);
var_DelCallback
(
p_filter
,
CFG_PREFIX
"mode"
,
puzzle_Callback
,
p_sys
);
vlc_mutex_destroy
(
&
p_sys
->
lock
);
vlc_mutex_destroy
(
&
p_sys
->
pce_lock
);
/* Free allocated memory */
puzzle_free_ps_puzzle_array
(
p_filter
);
puzzle_free_ps_pieces_shapes
(
p_filter
);
puzzle_free_ps_pieces
(
p_filter
);
free
(
p_sys
->
ps_desk_planes
);
free
(
p_sys
->
ps_pict_planes
);
free
(
p_sys
->
pi_order
);
for
(
int32_t
i_shape
=
0
;
i_shape
<
SHAPES_QTY
;
i_shape
++
)
free
(
p_sys
->
ps_bezier_pts_H
[
i_shape
]);
free
(
p_sys
->
ps_bezier_pts_H
);
free
(
p_sys
);
}
/**
* Filter a picture
*/
static
picture_t
*
Filter
(
filter_t
*
p_filter
,
picture_t
*
p_pic
)
{
picture_t
*
Filter
(
filter_t
*
p_filter
,
picture_t
*
p_pic_in
)
{
if
(
!
p_pic_in
||
!
p_filter
)
return
NULL
;
const
video_format_t
*
p_fmt_in
=
&
p_filter
->
fmt_in
.
video
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
picture_t
*
p_outpic
=
filter_NewPicture
(
p_filter
);
if
(
!
p_outpic
)
{
picture_Release
(
p_pic
);
picture_t
*
p_pic_out
=
filter_NewPicture
(
p_filter
);
if
(
!
p_pic_out
)
{
picture_Release
(
p_pic_in
);
return
NULL
;
}
/* */
if
(
!
atomic_flag_test_and_set
(
&
p_sys
->
change
.
b_uptodate
)
)
{
p_sys
->
i_rows
=
atomic_load
(
&
p_sys
->
change
.
i_rows
);
p_sys
->
i_cols
=
atomic_load
(
&
p_sys
->
change
.
i_cols
);
p_sys
->
b_blackslot
=
atomic_load
(
&
p_sys
->
change
.
b_blackslot
);
Shuffle
(
p_sys
);
int
i_ret
=
0
;
p_sys
->
b_bake_request
=
false
;
if
((
p_sys
->
pi_order
==
NULL
)
||
(
p_sys
->
ps_desk_planes
==
NULL
)
||
(
p_sys
->
ps_pict_planes
==
NULL
)
||
(
p_sys
->
ps_puzzle_array
==
NULL
)
||
(
p_sys
->
ps_pieces
==
NULL
))
p_sys
->
b_init
=
false
;
if
((
p_sys
->
ps_pieces_shapes
==
NULL
)
&&
p_sys
->
s_current_param
.
b_advanced
&&
(
p_sys
->
s_current_param
.
i_shape_size
!=
0
))
p_sys
->
b_init
=
false
;
/* assert initialized & allocated data match with current frame characteristics */
if
(
p_sys
->
s_allocated
.
i_planes
!=
p_pic_out
->
i_planes
)
p_sys
->
b_init
=
false
;
p_sys
->
s_current_param
.
i_planes
=
p_pic_out
->
i_planes
;
if
(
p_sys
->
ps_pict_planes
!=
NULL
)
{
for
(
uint8_t
i_plane
=
0
;
i_plane
<
p_sys
->
s_allocated
.
i_planes
;
i_plane
++
)
{
if
(
(
p_sys
->
ps_pict_planes
[
i_plane
].
i_lines
!=
p_pic_in
->
p
[
i_plane
].
i_visible_lines
)
||
(
p_sys
->
ps_pict_planes
[
i_plane
].
i_width
!=
p_pic_in
->
p
[
i_plane
].
i_visible_pitch
/
p_pic_in
->
p
[
i_plane
].
i_pixel_pitch
)
||
(
p_sys
->
ps_desk_planes
[
i_plane
].
i_lines
!=
p_pic_out
->
p
[
i_plane
].
i_visible_lines
)
||
(
p_sys
->
ps_desk_planes
[
i_plane
].
i_width
!=
p_pic_out
->
p
[
i_plane
].
i_visible_pitch
/
p_pic_out
->
p
[
i_plane
].
i_pixel_pitch
)
)
p_sys
->
b_init
=
false
;
}
}
/* */
const
int
i_rows
=
p_sys
->
i_rows
;
const
int
i_cols
=
p_sys
->
i_cols
;
p_sys
->
s_current_param
.
i_pict_width
=
(
int
)
p_pic_in
->
p
[
0
].
i_visible_pitch
/
p_pic_in
->
p
[
0
].
i_pixel_pitch
;
p_sys
->
s_current_param
.
i_pict_height
=
(
int
)
p_pic_in
->
p
[
0
].
i_visible_lines
;
p_sys
->
s_current_param
.
i_desk_width
=
(
int
)
p_pic_out
->
p
[
0
].
i_visible_pitch
/
p_pic_out
->
p
[
0
].
i_pixel_pitch
;
p_sys
->
s_current_param
.
i_desk_height
=
(
int
)
p_pic_out
->
p
[
0
].
i_visible_lines
;
/* 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
];
plane_t
*
p_out
=
&
p_outpic
->
p
[
i_plane
];
for
(
int
i
=
0
;
i
<
i_cols
*
i_rows
;
i
++
)
{
int
i_piece_height
=
p_out
->
i_visible_lines
/
i_rows
;
int
i_piece_width
=
p_out
->
i_visible_pitch
/
i_cols
;
/* assert no mismatch between sizes */
if
(
p_sys
->
s_current_param
.
i_pict_width
!=
p_sys
->
s_current_param
.
i_desk_width
||
p_sys
->
s_current_param
.
i_pict_height
!=
p_sys
->
s_current_param
.
i_desk_height
||
p_sys
->
s_current_param
.
i_pict_width
!=
(
int
)
p_fmt_in
->
i_width
||
p_sys
->
s_current_param
.
i_pict_height
!=
(
int
)
p_fmt_in
->
i_height
)
return
NULL
;
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
;
vlc_mutex_lock
(
&
p_sys
->
lock
);
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
;
/* check if we have to compute initial data */
if
(
p_sys
->
b_change_param
||
p_sys
->
b_bake_request
||
!
p_sys
->
b_init
)
{
if
(
p_sys
->
s_allocated
.
i_rows
!=
p_sys
->
s_new_param
.
i_rows
||
p_sys
->
s_allocated
.
i_cols
!=
p_sys
->
s_new_param
.
i_cols
||
p_sys
->
s_allocated
.
i_rotate
!=
p_sys
->
s_new_param
.
i_rotate
||
p_sys
->
s_allocated
.
i_mode
!=
p_sys
->
s_new_param
.
i_mode
||
p_sys
->
b_bake_request
||
!
p_sys
->
b_init
)
{
p_sys
->
b_bake_request
=
true
;
p_sys
->
b_init
=
false
;
p_sys
->
b_shuffle_rqst
=
true
;
p_sys
->
b_shape_init
=
false
;
}
if
(
p_sys
->
b_blackslot
&&
!
p_sys
->
b_finished
&&
i
==
p_sys
->
i_selected
)
{
uint8_t
color
=
(
i_plane
==
Y_PLANE
?
0x0
:
0x80
);
for
(
int
r
=
i_row
;
r
<
i_last_row
;
r
++
)
{
memset
(
p_out
->
p_pixels
+
r
*
p_out
->
i_pitch
+
i_col
,
color
,
i_piece_width
);
}
}
else
{
for
(
int
r
=
i_row
,
or
=
i_orow
;
r
<
i_last_row
;
r
++
,
or
++
)
{
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
->
s_current_param
.
i_border
!=
p_sys
->
s_new_param
.
i_border
||
p_sys
->
s_current_param
.
i_shape_size
!=
p_sys
->
s_new_param
.
i_shape_size
)
{
p_sys
->
b_bake_request
=
true
;
p_sys
->
b_shape_init
=
false
;
}
/* 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
);
}
/* depending on the game selected, set associated internal flags */
switch
(
p_sys
->
s_new_param
.
i_mode
)
{
case
0
:
/* jigsaw puzzle */
p_sys
->
s_new_param
.
b_advanced
=
true
;
p_sys
->
s_new_param
.
b_blackslot
=
false
;
p_sys
->
s_new_param
.
b_near
=
false
;
break
;
case
1
:
/* sliding puzzle */
p_sys
->
s_new_param
.
b_advanced
=
false
;
p_sys
->
s_new_param
.
b_blackslot
=
true
;
p_sys
->
s_new_param
.
b_near
=
true
;
break
;
case
2
:
/* swap puzzle */
p_sys
->
s_new_param
.
b_advanced
=
false
;
p_sys
->
s_new_param
.
b_blackslot
=
false
;
p_sys
->
s_new_param
.
b_near
=
true
;
break
;
case
3
:
/* exchange puzzle */
p_sys
->
s_new_param
.
b_advanced
=
false
;
p_sys
->
s_new_param
.
b_blackslot
=
false
;
p_sys
->
s_new_param
.
b_near
=
false
;
break
;
}
p_sys
->
s_current_param
.
i_mode
=
p_sys
->
s_new_param
.
i_mode
;
if
(
p_sys
->
s_current_param
.
b_blackslot
!=
p_sys
->
s_new_param
.
b_blackslot
&&
p_sys
->
i_selected
==
NO_PCE
&&
p_sys
->
s_current_param
.
b_blackslot
)
p_sys
->
i_selected
=
0
;
if
(
p_sys
->
s_current_param
.
i_auto_shuffle_speed
!=
p_sys
->
s_new_param
.
i_auto_shuffle_speed
)
p_sys
->
i_auto_shuffle_countdown_val
=
init_countdown
(
p_sys
->
s_new_param
.
i_auto_shuffle_speed
);
if
(
p_sys
->
s_current_param
.
i_auto_solve_speed
!=
p_sys
->
s_new_param
.
i_auto_solve_speed
)
p_sys
->
i_auto_solve_countdown_val
=
init_countdown
(
p_sys
->
s_current_param
.
i_auto_solve_speed
);
p_sys
->
s_current_param
.
i_rows
=
p_sys
->
s_new_param
.
i_rows
;
p_sys
->
s_current_param
.
i_cols
=
p_sys
->
s_new_param
.
i_cols
;
p_sys
->
s_current_param
.
i_pieces_nbr
=
p_sys
->
s_current_param
.
i_rows
*
p_sys
->
s_current_param
.
i_cols
;
p_sys
->
s_current_param
.
b_advanced
=
p_sys
->
s_new_param
.
b_advanced
;
if
(
!
p_sys
->
s_new_param
.
b_advanced
)
{
p_sys
->
s_current_param
.
b_blackslot
=
p_sys
->
s_new_param
.
b_blackslot
;
p_sys
->
s_current_param
.
b_near
=
p_sys
->
s_new_param
.
b_near
||
p_sys
->
s_new_param
.
b_blackslot
;
p_sys
->
s_current_param
.
i_border
=
0
;
p_sys
->
s_current_param
.
b_preview
=
false
;
p_sys
->
s_current_param
.
i_preview_size
=
0
;
p_sys
->
s_current_param
.
i_shape_size
=
0
;
p_sys
->
s_current_param
.
i_auto_shuffle_speed
=
0
;
p_sys
->
s_current_param
.
i_auto_solve_speed
=
0
;
p_sys
->
s_current_param
.
i_rotate
=
0
;
}
else
{
p_sys
->
s_current_param
.
b_blackslot
=
false
;
p_sys
->
s_current_param
.
b_near
=
false
;
p_sys
->
s_current_param
.
i_border
=
p_sys
->
s_new_param
.
i_border
;
p_sys
->
s_current_param
.
b_preview
=
p_sys
->
s_new_param
.
b_preview
;
p_sys
->
s_current_param
.
i_preview_size
=
p_sys
->
s_new_param
.
i_preview_size
;
p_sys
->
s_current_param
.
i_shape_size
=
p_sys
->
s_new_param
.
i_shape_size
;
p_sys
->
s_current_param
.
i_auto_shuffle_speed
=
p_sys
->
s_new_param
.
i_auto_shuffle_speed
;
p_sys
->
s_current_param
.
i_auto_solve_speed
=
p_sys
->
s_new_param
.
i_auto_solve_speed
;
p_sys
->
s_current_param
.
i_rotate
=
p_sys
->
s_new_param
.
i_rotate
;
}
p_sys
->
b_change_param
=
false
;
}
/* Draw the 'Shuffle' button if the puzzle is finished */
if
(
p_sys
->
b_finished
)
{
plane_t
*
p_out
=
&
p_outpic
->
p
[
Y_PLANE
];
for
(
int
i
=
0
;
i
<
SHUFFLE_HEIGHT
;
i
++
)
{
for
(
int
j
=
0
;
j
<
SHUFFLE_WIDTH
;
j
++
)
vlc_mutex_unlock
(
&
p_sys
->
lock
);
/* generate initial puzzle data when needed */
if
(
p_sys
->
b_bake_request
)
{
if
(
!
p_sys
->
b_shuffle_rqst
)
{
/* here we have to keep the same position
* we have to save locations before generating new data
*/
save_game_t
*
ps_save_game
=
puzzle_save
(
p_filter
);
if
(
!
ps_save_game
)
return
CopyInfoAndRelease
(
p_pic_out
,
p_pic_in
);
i_ret
=
puzzle_bake
(
p_filter
,
p_pic_out
,
p_pic_in
);
if
(
i_ret
!=
VLC_SUCCESS
)
{
if
(
shuffle_button
[
i
][
j
]
==
'.'
)
p_out
->
p_pixels
[
i
*
p_out
->
i_pitch
+
j
]
=
0xff
;
free
(
ps_save_game
->
ps_pieces
);
free
(
ps_save_game
);
return
CopyInfoAndRelease
(
p_pic_out
,
p_pic_in
);
}
puzzle_load
(
p_filter
,
ps_save_game
);
free
(
ps_save_game
->
ps_pieces
);
free
(
ps_save_game
);
}
else
{
i_ret
=
puzzle_bake
(
p_filter
,
p_pic_out
,
p_pic_in
);
if
(
i_ret
!=
VLC_SUCCESS
)
return
CopyInfoAndRelease
(
p_pic_out
,
p_pic_in
);
}
}
return
CopyInfoAndRelease
(
p_outpic
,
p_pic
);
}
/* shuffle the desk and generate pieces data */
if
(
p_sys
->
b_shuffle_rqst
&&
p_sys
->
b_init
)
{
i_ret
=
puzzle_bake_piece
(
p_filter
);
if
(
i_ret
!=
VLC_SUCCESS
)
return
CopyInfoAndRelease
(
p_pic_out
,
p_pic_in
);
}
static
int
Mouse
(
filter_t
*
p_filter
,
vlc_mouse_t
*
p_mouse
,
const
vlc_mouse_t
*
p_old
,
const
vlc_mouse_t
*
p_new
)
{
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
const
video_format_t
*
p_fmt
=
&
p_filter
->
fmt_in
.
video
;
/* preset output pic */
if
(
!
p_sys
->
b_bake_request
&&
!
p_sys
->
b_shuffle_rqst
&&
p_sys
->
b_init
&&
!
p_sys
->
b_finished
)
puzzle_preset_desk_background
(
p_pic_out
,
0
,
127
,
127
);
else
{
/* copy src to dst during init & bake process */
for
(
uint8_t
i_plane
=
0
;
i_plane
<
p_pic_out
->
i_planes
;
i_plane
++
)
memcpy
(
p_pic_out
->
p
[
i_plane
].
p_pixels
,
p_pic_in
->
p
[
i_plane
].
p_pixels
,
p_pic_in
->
p
[
i_plane
].
i_pitch
*
(
int32_t
)
p_pic_in
->
p
[
i_plane
].
i_visible_lines
);
}
/* 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
;
vlc_mutex_lock
(
&
p_sys
->
pce_lock
);
/* */
const
bool
b_clicked
=
vlc_mouse_HasPressed
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
);
/* manage the game, adjust locations, groups and regenerate some corrupted data if any */
for
(
uint32_t
i
=
0
;
i
<
__MAX
(
4
,
p_sys
->
s_allocated
.
i_pieces_nbr
/
4
)
&&
(
!
p_sys
->
b_bake_request
&&
!
p_sys
->
b_mouse_drag
&&
p_sys
->
b_init
&&
p_sys
->
s_current_param
.
b_advanced
);
i
++
)
{
puzzle_solve_pces_accuracy
(
p_filter
);
}
/* If the puzzle is finished, shuffle it if needed */
if
(
p_sys
->
b_finished
)
for
(
uint32_t
i
=
0
;
i
<
__MAX
(
4
,
p_sys
->
s_allocated
.
i_pieces_nbr
/
4
)
&&
(
!
p_sys
->
b_bake_request
&&
!
p_sys
->
b_mouse_drag
&&
p_sys
->
b_init
&&
p_sys
->
s_current_param
.
b_advanced
);
i
++
)
{
if
(
b_clicked
&&
p_new
->
i_x
<
SHUFFLE_WIDTH
&&
p_new
->
i_y
<
SHUFFLE_HEIGHT
)
{
atomic_flag_clear
(
&
p_sys
->
change
.
b_uptodate
);
return
VLC_EGENERIC
;
}
else
{
/* This is the only case where we can forward the mouse */
*
p_mouse
=
*
p_new
;
return
VLC_SUCCESS
;
}
puzzle_solve_pces_group
(
p_filter
);
}
if
(
!
b_clicked
)
return
VLC_EGENERIC
;
/* */
const
int
i_pos_x
=
p_new
->
i_x
*
p_sys
->
i_cols
/
p_fmt
->
i_width
;
const
int
i_pos_y
=
p_new
->
i_y
*
p_sys
->
i_rows
/
p_fmt
->
i_height
;
const
int
i_pos
=
i_pos_y
*
p_sys
->
i_cols
+
i_pos_x
;
if
(
!
p_sys
->
b_bake_request
&&
!
p_sys
->
b_mouse_drag
&&
p_sys
->
b_init
&&
p_sys
->
s_current_param
.
b_advanced
)
puzzle_count_pce_group
(
p_filter
);
if
(
!
p_sys
->
b_bake_request
&&
!
p_sys
->
b_mouse_drag
&&
p_sys
->
b_init
&&
p_sys
->
s_current_param
.
b_advanced
)
{
i_ret
=
puzzle_sort_layers
(
p_filter
);
if
(
i_ret
!=
VLC_SUCCESS
)
return
CopyInfoAndRelease
(
p_pic_out
,
p_pic_in
);
}
if
(
p_sys
->
i_selected
==
-
1
)
for
(
uint32_t
i
=
0
;
i
<
__MAX
(
4
,
p_sys
->
s_allocated
.
i_pieces_nbr
/
24
)
&&
(
!
p_sys
->
b_bake_request
&&
!
p_sys
->
b_mouse_drag
&&
p_sys
->
b_init
&&
p_sys
->
s_current_param
.
b_advanced
);
i
++
)
{
p_sys
->
i_selected
=
i_pos
;
p_sys
->
i_calc_corn_loop
++
;
p_sys
->
i_calc_corn_loop
%=
p_sys
->
s_allocated
.
i_pieces_nbr
;
puzzle_calculate_corners
(
p_filter
,
p_sys
->
i_calc_corn_loop
);
}
else
if
(
p_sys
->
i_selected
==
i_pos
&&
!
p_sys
->
b_blackslot
)
/* computer moves some piece depending on auto_solve and auto_shuffle param */
if
(
!
p_sys
->
b_bake_request
&&
!
p_sys
->
b_mouse_drag
&&
p_sys
->
b_init
&&
p_sys
->
ps_puzzle_array
!=
NULL
&&
p_sys
->
s_current_param
.
b_advanced
)
{
p_sys
->
i_selected
=
-
1
;
puzzle_auto_shuffle
(
p_filter
);
puzzle_auto_solve
(
p_filter
);
}
else
if
(
(
p_sys
->
i_selected
==
i_pos
+
1
&&
p_sys
->
i_selected
%
p_sys
->
i_cols
!=
0
)
||
(
p_sys
->
i_selected
==
i_pos
-
1
&&
i_pos
%
p_sys
->
i_cols
!=
0
)
||
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
;
p_sys
->
i_selected
=
p_sys
->
b_blackslot
?
i_pos
:
-
1
;
p_sys
->
b_finished
=
IsFinished
(
p_sys
);
vlc_mutex_unlock
(
&
p_sys
->
pce_lock
);
/* draw output pic */
if
(
!
p_sys
->
b_bake_request
&&
p_sys
->
b_init
&&
p_sys
->
ps_puzzle_array
!=
NULL
)
{
puzzle_draw_borders
(
p_filter
,
p_pic_in
,
p_pic_out
);
p_sys
->
i_pointed_pce
=
NO_PCE
;
puzzle_draw_pieces
(
p_filter
,
p_pic_in
,
p_pic_out
);
/* when puzzle_draw_pieces() has not updated p_sys->i_pointed_pce,
* use puzzle_find_piece to define the piece pointed by the mouse
*/
if
(
p_sys
->
i_pointed_pce
==
NO_PCE
)
p_sys
->
i_mouse_drag_pce
=
puzzle_find_piece
(
p_filter
,
p_sys
->
i_mouse_x
,
p_sys
->
i_mouse_y
,
-
1
);
else
p_sys
->
i_mouse_drag_pce
=
p_sys
->
i_pointed_pce
;
if
(
p_sys
->
s_current_param
.
b_preview
)
puzzle_draw_preview
(
p_filter
,
p_pic_in
,
p_pic_out
);
/* highlight the selected piece when not playing jigsaw mode */
if
(
p_sys
->
i_selected
!=
NO_PCE
&&
!
p_sys
->
s_current_param
.
b_blackslot
&&
!
p_sys
->
s_current_param
.
b_advanced
)
{
int32_t
c
=
(
p_sys
->
i_selected
%
p_sys
->
s_allocated
.
i_cols
);
int32_t
r
=
(
p_sys
->
i_selected
/
p_sys
->
s_allocated
.
i_cols
);
puzzle_draw_rectangle
(
p_pic_out
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_x
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_y
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_width
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_lines
,
255
,
127
,
127
);
}
/* draw the blackslot when playing sliding puzzle mode */
if
(
p_sys
->
i_selected
!=
NO_PCE
&&
p_sys
->
s_current_param
.
b_blackslot
&&
!
p_sys
->
s_current_param
.
b_advanced
)
{
int32_t
c
=
(
p_sys
->
i_selected
%
p_sys
->
s_allocated
.
i_cols
);
int32_t
r
=
(
p_sys
->
i_selected
/
p_sys
->
s_allocated
.
i_cols
);
puzzle_fill_rectangle
(
p_pic_out
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_x
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_y
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_width
,
p_sys
->
ps_puzzle_array
[
r
][
c
][
0
].
i_lines
,
0
,
127
,
127
);
}
/* Draw the 'puzzle_shuffle' button if the puzzle is finished */
if
(
p_sys
->
b_finished
)
puzzle_draw_sign
(
p_pic_out
,
0
,
0
,
SHUFFLE_WIDTH
,
SHUFFLE_LINES
,
ppsz_shuffle_button
,
false
);
/* draw an arrow at mouse pointer to indicate current action (rotation...) */
if
((
p_sys
->
i_mouse_drag_pce
!=
NO_PCE
)
&&
!
p_sys
->
b_mouse_drag
&&
!
p_sys
->
b_finished
&&
p_sys
->
s_current_param
.
b_advanced
)
{
vlc_mutex_lock
(
&
p_sys
->
pce_lock
);
int32_t
i_delta_x
;
if
(
p_sys
->
s_current_param
.
i_rotate
!=
3
)
i_delta_x
=
0
;
else
if
(
(
p_sys
->
ps_pieces
[
p_sys
->
i_mouse_drag_pce
].
i_actual_angle
&
1
)
==
0
)
i_delta_x
=
p_sys
->
ps_desk_planes
[
0
].
i_pce_max_width
/
6
;
else
i_delta_x
=
p_sys
->
ps_desk_planes
[
0
].
i_pce_max_lines
/
6
;
if
(
p_sys
->
s_current_param
.
i_rotate
==
0
)
p_sys
->
i_mouse_action
=
0
;
else
if
(
p_sys
->
s_current_param
.
i_rotate
==
1
)
p_sys
->
i_mouse_action
=
2
;
else
if
(
p_sys
->
i_mouse_x
>=
(
p_sys
->
ps_pieces
[
p_sys
->
i_mouse_drag_pce
].
i_center_x
+
i_delta_x
)
)
p_sys
->
i_mouse_action
=
-
1
;
/* rotate counterclockwise */
else
if
(
p_sys
->
i_mouse_x
<=
(
p_sys
->
ps_pieces
[
p_sys
->
i_mouse_drag_pce
].
i_center_x
-
i_delta_x
)
)
p_sys
->
i_mouse_action
=
+
1
;
else
p_sys
->
i_mouse_action
=
4
;
/* center click: only mirror */
if
(
p_sys
->
i_mouse_action
==
+
1
)
puzzle_draw_sign
(
p_pic_out
,
p_sys
->
i_mouse_x
-
ARROW_WIDTH
,
p_sys
->
i_mouse_y
,
ARROW_WIDTH
,
ARROW_LINES
,
ppsz_rot_arrow_sign
,
false
);
else
if
(
p_sys
->
i_mouse_action
==
-
1
)
puzzle_draw_sign
(
p_pic_out
,
p_sys
->
i_mouse_x
-
ARROW_WIDTH
,
p_sys
->
i_mouse_y
,
ARROW_WIDTH
,
ARROW_LINES
,
ppsz_rot_arrow_sign
,
true
);
else
if
(
p_sys
->
i_mouse_action
==
4
)
puzzle_draw_sign
(
p_pic_out
,
p_sys
->
i_mouse_x
-
ARROW_WIDTH
,
p_sys
->
i_mouse_y
,
ARROW_WIDTH
,
ARROW_LINES
,
ppsz_mir_arrow_sign
,
false
);
vlc_mutex_unlock
(
&
p_sys
->
pce_lock
);
}
}
return
VLC_EGENERIC
;
return
CopyInfoAndRelease
(
p_pic_out
,
p_pic_in
);
}
/*****************************************************************************
* Misc stuff...
*****************************************************************************/
static
int
Puzzle
Callback
(
vlc_object_t
*
p_this
,
char
const
*
psz_var
,
int
puzzle_
Callback
(
vlc_object_t
*
p_this
,
char
const
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
VLC_UNUSED
(
p_this
);
VLC_UNUSED
(
oldval
);
filter_sys_t
*
p_sys
=
p_data
;
filter_sys_t
*
p_sys
=
(
filter_sys_t
*
)
p_data
;
vlc_mutex_lock
(
&
p_sys
->
lock
);
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"rows"
)
)
{
p_sys
->
s_new_param
.
i_rows
=
__MAX
(
1
,
newval
.
i_int
);
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"cols"
)
)
{
p_sys
->
s_new_param
.
i_cols
=
__MAX
(
1
,
newval
.
i_int
);
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"border"
)
)
{
p_sys
->
s_new_param
.
i_border
=
__MAX
(
0
,
newval
.
i_int
);
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"preview"
)
)
{
p_sys
->
s_new_param
.
b_preview
=
newval
.
b_bool
;
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"preview-size"
)
)
{
p_sys
->
s_new_param
.
i_preview_size
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"shape-size"
)
)
{
p_sys
->
s_new_param
.
i_shape_size
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"auto-shuffle"
)
)
{
p_sys
->
s_new_param
.
i_auto_shuffle_speed
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"auto-solve"
)
)
{
p_sys
->
s_new_param
.
i_auto_solve_speed
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"rotation"
)
)
{
p_sys
->
s_new_param
.
i_rotate
=
newval
.
i_int
;
}
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"mode"
)
)
{
p_sys
->
s_new_param
.
i_mode
=
newval
.
i_int
;
}
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"rows"
)
)
atomic_store
(
&
p_sys
->
change
.
i_rows
,
__MAX
(
2
,
newval
.
i_int
)
);
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"cols"
)
)
atomic_store
(
&
p_sys
->
change
.
i_cols
,
__MAX
(
2
,
newval
.
i_int
)
);
else
if
(
!
strcmp
(
psz_var
,
CFG_PREFIX
"black-slot"
)
)
atomic_store
(
&
p_sys
->
change
.
b_blackslot
,
newval
.
b_bool
);
atomic_flag_clear
(
&
p_sys
->
change
.
b_uptodate
);
p_sys
->
b_change_param
=
true
;
vlc_mutex_unlock
(
&
p_sys
->
lock
);
return
VLC_SUCCESS
;
}
static
bool
IsFinished
(
filter_sys_t
*
p_sys
)
/* mouse callback */
int
puzzle_mouse
(
filter_t
*
p_filter
,
vlc_mouse_t
*
p_mouse
,
const
vlc_mouse_t
*
p_old
,
const
vlc_mouse_t
*
p_new
)
{
for
(
int
i
=
0
;
i
<
p_sys
->
i_cols
*
p_sys
->
i_rows
;
i
++
)
{
if
(
i
!=
p_sys
->
pi_order
[
i
]
)
return
false
;
}
return
true
;
}
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
const
video_format_t
*
p_fmt_in
=
&
p_filter
->
fmt_in
.
video
;
static
bool
IsValid
(
filter_sys_t
*
p_sys
)
{
const
int
i_count
=
p_sys
->
i_cols
*
p_sys
->
i_rows
;
/* Only take events inside the puzzle area */
if
(
p_new
->
i_x
<
0
||
p_new
->
i_x
>=
(
int
)
p_fmt_in
->
i_width
||
p_new
->
i_y
<
0
||
p_new
->
i_y
>=
(
int
)
p_fmt_in
->
i_height
)
return
VLC_EGENERIC
;
if
(
!
p_sys
->
b_blackslot
)
return
true
;
if
(
!
p_sys
->
b_init
||
p_sys
->
b_change_param
)
{
*
p_mouse
=
*
p_new
;
return
VLC_SUCCESS
;
}
int
d
=
0
;
for
(
int
i
=
0
;
i
<
i_count
;
i
++
)
{
if
(
p_sys
->
pi_order
[
i
]
==
i_count
-
1
)
p_sys
->
i_mouse_x
=
p_new
->
i_x
;
p_sys
->
i_mouse_y
=
p_new
->
i_y
;
/* If the puzzle is finished, shuffle it if needed */
if
(
p_sys
->
b_finished
)
{
p_sys
->
b_mouse_drag
=
false
;
p_sys
->
b_mouse_mvt
=
false
;
if
(
vlc_mouse_HasPressed
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
)
&&
p_new
->
i_x
<
SHUFFLE_WIDTH
&&
p_new
->
i_y
<
SHUFFLE_LINES
)
{
d
+=
i
/
p_sys
->
i_cols
+
1
;
continue
;
p_sys
->
b_shuffle_rqst
=
true
;
return
VLC_EGENERIC
;
}
for
(
int
j
=
i
+
1
;
j
<
i_count
;
j
++
)
else
{
if
(
p_sys
->
pi_order
[
j
]
==
i_count
-
1
)
continue
;
if
(
p_sys
->
pi_order
[
i
]
>
p_sys
->
pi_order
[
j
]
)
d
++
;
/* otherwise we can forward the mouse */
*
p_mouse
=
*
p_new
;
return
VLC_SUCCESS
;
}
}
return
(
d
%
2
)
==
0
;
}
static
void
Shuffle
(
filter_sys_t
*
p_sys
)
{
const
unsigned
i_count
=
p_sys
->
i_cols
*
p_sys
->
i_rows
;
if
(
!
p_sys
->
s_current_param
.
b_advanced
)
{
/* "square" game mode (sliding puzzle, swap...) */
const
bool
b_clicked
=
vlc_mouse_HasPressed
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
)
;
free
(
p_sys
->
pi_order
);
if
(
b_clicked
)
{
/* */
const
int32_t
i_border_width
=
p_fmt_in
->
i_width
*
p_sys
->
s_current_param
.
i_border
/
100
/
2
;
const
int32_t
i_border_height
=
p_fmt_in
->
i_height
*
p_sys
->
s_current_param
.
i_border
/
100
/
2
;
const
int32_t
i_pos_x
=
(
p_new
->
i_x
-
i_border_width
)
*
p_sys
->
s_allocated
.
i_cols
/
(
p_fmt_in
->
i_width
-
2
*
i_border_width
);
const
int32_t
i_pos_y
=
(
p_new
->
i_y
-
i_border_height
)
*
p_sys
->
s_allocated
.
i_rows
/
(
p_fmt_in
->
i_height
-
2
*
i_border_height
);
const
int32_t
i_pos
=
i_pos_y
*
p_sys
->
s_allocated
.
i_cols
+
i_pos_x
;
p_sys
->
i_mouse_drag_pce
=
i_pos
;
p_sys
->
pi_order
=
calloc
(
i_count
,
sizeof
(
*
p_sys
->
pi_order
)
);
do
/* do not take into account if border clicked */
if
((
p_new
->
i_x
<=
i_border_width
)
||
(
p_new
->
i_y
<=
i_border_height
)
||
(
p_new
->
i_x
>=
(
int
)
p_fmt_in
->
i_width
-
i_border_width
)
||
(
p_new
->
i_y
>=
(
int
)
p_fmt_in
->
i_height
-
i_border_height
)
)
{
*
p_mouse
=
*
p_new
;
return
VLC_SUCCESS
;
}
else
if
(
p_sys
->
i_selected
==
NO_PCE
)
p_sys
->
i_selected
=
i_pos
;
else
if
(
p_sys
->
i_selected
==
i_pos
&&
!
p_sys
->
s_current_param
.
b_blackslot
)
p_sys
->
i_selected
=
-
1
;
else
if
(
(
p_sys
->
i_selected
==
i_pos
+
1
&&
p_sys
->
i_selected
%
p_sys
->
s_allocated
.
i_cols
!=
0
)
||
(
p_sys
->
i_selected
==
i_pos
-
1
&&
i_pos
%
p_sys
->
s_allocated
.
i_cols
!=
0
)
||
p_sys
->
i_selected
==
i_pos
+
p_sys
->
s_allocated
.
i_cols
||
p_sys
->
i_selected
==
i_pos
-
p_sys
->
s_allocated
.
i_cols
||
!
p_sys
->
s_current_param
.
b_near
)
{
/* Swap two pieces */
int32_t
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
;
/* regen piece location from updated pi_order */
if
(
p_sys
->
ps_pieces
!=
NULL
&&
p_sys
->
pi_order
!=
NULL
)
{
int32_t
i
=
0
;
for
(
int32_t
row
=
0
;
row
<
p_sys
->
s_allocated
.
i_rows
;
row
++
)
{
for
(
int32_t
col
=
0
;
col
<
p_sys
->
s_allocated
.
i_cols
;
col
++
)
{
int32_t
orow
=
p_sys
->
pi_order
[
i
]
/
(
p_sys
->
s_allocated
.
i_cols
);
int32_t
ocol
=
p_sys
->
pi_order
[
i
]
%
(
p_sys
->
s_allocated
.
i_cols
);
p_sys
->
ps_pieces
[
i
].
i_original_row
=
orow
;
p_sys
->
ps_pieces
[
i
].
i_original_col
=
ocol
;
p_sys
->
ps_pieces
[
i
].
i_top_shape
=
0
;
p_sys
->
ps_pieces
[
i
].
i_btm_shape
=
0
;
p_sys
->
ps_pieces
[
i
].
i_right_shape
=
0
;
p_sys
->
ps_pieces
[
i
].
i_left_shape
=
0
;
p_sys
->
ps_pieces
[
i
].
i_actual_angle
=
0
;
p_sys
->
ps_pieces
[
i
].
i_actual_mirror
=
+
1
;
p_sys
->
ps_pieces
[
i
].
b_overlap
=
false
;
p_sys
->
ps_pieces
[
i
].
b_finished
=
false
;
p_sys
->
ps_pieces
[
i
].
i_group_ID
=
i
;
for
(
uint8_t
i_plane
=
0
;
i_plane
<
p_sys
->
s_allocated
.
i_planes
;
i_plane
++
)
{
p_sys
->
ps_pieces
[
i
].
ps_piece_in_plane
[
i_plane
].
i_width
=
p_sys
->
ps_puzzle_array
[
row
][
col
][
i_plane
].
i_width
;
p_sys
->
ps_pieces
[
i
].
ps_piece_in_plane
[
i_plane
].
i_lines
=
p_sys
->
ps_puzzle_array
[
row
][
col
][
i_plane
].
i_lines
;
p_sys
->
ps_pieces
[
i
].
ps_piece_in_plane
[
i_plane
].
i_original_x
=
p_sys
->
ps_puzzle_array
[
orow
][
ocol
][
i_plane
].
i_x
;
p_sys
->
ps_pieces
[
i
].
ps_piece_in_plane
[
i_plane
].
i_original_y
=
p_sys
->
ps_puzzle_array
[
orow
][
ocol
][
i_plane
].
i_y
;
p_sys
->
ps_pieces
[
i
].
ps_piece_in_plane
[
i_plane
].
i_actual_x
=
p_sys
->
ps_puzzle_array
[
row
][
col
][
i_plane
].
i_x
;
p_sys
->
ps_pieces
[
i
].
ps_piece_in_plane
[
i_plane
].
i_actual_y
=
p_sys
->
ps_puzzle_array
[
row
][
col
][
i_plane
].
i_y
;
}
i
++
;
}
}
}
p_sys
->
i_selected
=
p_sys
->
s_current_param
.
b_blackslot
?
i_pos
:
NO_PCE
;
p_sys
->
b_finished
=
puzzle_is_finished
(
p_sys
,
p_sys
->
pi_order
);
}
}
}
else
/* jigsaw puzzle mode */
{
for
(
unsigned
i
=
0
;
i
<
i_count
;
i
++
)
p_sys
->
pi_order
[
i
]
=
-
1
;
if
((
p_sys
->
ps_desk_planes
==
NULL
)
||
(
p_sys
->
ps_pict_planes
==
NULL
)
||
(
p_sys
->
ps_puzzle_array
==
NULL
)
||
(
p_sys
->
ps_pieces
==
NULL
))
{
*
p_mouse
=
*
p_new
;
return
VLC_SUCCESS
;
}
for
(
unsigned
c
=
0
;
c
<
i_count
;
)
if
(
vlc_mouse_HasPressed
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
)
)
{
unsigned
i
=
((
unsigned
)
vlc_mrand48
())
%
i_count
;
if
(
p_sys
->
pi_order
[
i
]
==
-
1
)
p_sys
->
pi_order
[
i
]
=
c
++
;
vlc_mutex_lock
(
&
p_sys
->
pce_lock
);
if
(
p_sys
->
i_mouse_drag_pce
!=
NO_PCE
)
{
int
i_ret
=
puzzle_piece_foreground
(
p_filter
,
p_sys
->
i_mouse_drag_pce
);
if
(
i_ret
!=
VLC_SUCCESS
)
return
i_ret
;
p_sys
->
i_mouse_drag_pce
=
0
;
uint32_t
i_group_ID
=
p_sys
->
ps_pieces
[
0
].
i_group_ID
;
for
(
uint32_t
i
=
0
;
i
<
p_sys
->
s_allocated
.
i_pieces_nbr
;
i
++
)
{
if
(
i_group_ID
==
p_sys
->
ps_pieces
[
i
].
i_group_ID
)
{
p_sys
->
ps_pieces
[
i
].
b_finished
=
false
;
}
else
{
break
;
}
}
p_sys
->
b_mouse_drag
=
true
;
p_sys
->
b_mouse_mvt
=
false
;
}
else
{
/* player click an empty area then search a piece which is overlapping another one and place it here */
p_sys
->
b_mouse_drag
=
false
;
for
(
uint32_t
i
=
0
;
i
<
p_sys
->
s_allocated
.
i_pieces_nbr
;
i
++
)
if
(
p_sys
->
ps_pieces
[
i
].
b_overlap
)
{
puzzle_move_group
(
p_filter
,
i
,
p_new
->
i_x
-
p_sys
->
ps_pieces
[
i
].
i_center_x
,
p_new
->
i_y
-
p_sys
->
ps_pieces
[
i
].
i_center_y
);
p_sys
->
ps_pieces
[
i
].
b_overlap
=
false
;
break
;
}
p_sys
->
b_mouse_drag
=
false
;
}
vlc_mutex_unlock
(
&
p_sys
->
pce_lock
);
}
p_sys
->
b_finished
=
IsFinished
(
p_sys
);
else
if
(
vlc_mouse_HasReleased
(
p_old
,
p_new
,
MOUSE_BUTTON_LEFT
)
)
{
if
(
!
p_sys
->
b_mouse_mvt
&&
p_sys
->
b_mouse_drag
)
{
/* piece clicked without any mouse mvt => rotate it or mirror */
if
(
p_sys
->
s_current_param
.
i_rotate
!=
0
)
{
vlc_mutex_lock
(
&
p_sys
->
pce_lock
);
}
while
(
p_sys
->
b_finished
||
!
IsValid
(
p_sys
)
)
;
uint32_t
i_group_ID
=
p_sys
->
ps_pieces
[
0
].
i_group_ID
;
if
(
p_sys
->
b_blackslot
)
{
for
(
unsigned
i
=
0
;
i
<
i_count
;
i
++
)
for
(
uint32_t
i
=
0
;
i
<
p_sys
->
s_allocated
.
i_pieces_nbr
;
i
++
)
if
(
i_group_ID
==
p_sys
->
ps_pieces
[
i
].
i_group_ID
)
puzzle_rotate_pce
(
p_filter
,
i
,
p_sys
->
i_mouse_action
,
p_sys
->
ps_pieces
[
0
].
i_center_x
,
p_sys
->
ps_pieces
[
0
].
i_center_y
,
p_sys
->
i_mouse_action
!=
4
?
true
:
false
);
vlc_mutex_unlock
(
&
p_sys
->
pce_lock
);
}
}
p_sys
->
b_mouse_drag
=
false
;
p_sys
->
b_mouse_mvt
=
false
;
}
else
/* no action on left button */
{
if
(
p_sys
->
pi_order
[
i
]
==
(
int
)
i_count
-
1
)
/* check if the mouse is in the preview area */
switch
(
p_sys
->
i_preview_pos
)
{
p_sys
->
i_selected
=
i
;
case
0
:
if
(
p_new
->
i_x
<
(
int
)
p_fmt_in
->
i_width
/
2
&&
p_new
->
i_y
<
(
int
)
p_fmt_in
->
i_height
/
2
)
p_sys
->
i_preview_pos
++
;
break
;
case
1
:
if
(
p_new
->
i_x
>
(
int
)
p_fmt_in
->
i_width
/
2
&&
p_new
->
i_y
<
(
int
)
p_fmt_in
->
i_height
/
2
)
p_sys
->
i_preview_pos
++
;
break
;
case
2
:
if
(
p_new
->
i_x
>
(
int
)
p_fmt_in
->
i_width
/
2
&&
p_new
->
i_y
>
(
int
)
p_fmt_in
->
i_height
/
2
)
p_sys
->
i_preview_pos
++
;
break
;
case
3
:
if
(
p_new
->
i_x
<
(
int
)
p_fmt_in
->
i_width
/
2
&&
p_new
->
i_y
>
(
int
)
p_fmt_in
->
i_height
/
2
)
p_sys
->
i_preview_pos
++
;
break
;
}
p_sys
->
i_preview_pos
%=
4
;
if
(
!
vlc_mouse_IsLeftPressed
(
p_new
)
)
p_sys
->
b_mouse_drag
=
false
;
int
i_dx
,
i_dy
;
vlc_mouse_GetMotion
(
&
i_dx
,
&
i_dy
,
p_old
,
p_new
);
if
(
i_dx
!=
0
||
i_dy
!=
0
)
p_sys
->
b_mouse_mvt
=
true
;
if
(
p_sys
->
b_mouse_drag
)
{
if
(
(
p_new
->
i_x
<=
0
)
||
(
p_new
->
i_y
<=
0
)
||
(
p_new
->
i_x
>=
(
int
)
p_fmt_in
->
i_width
)
||
(
p_new
->
i_y
>=
(
int
)
p_fmt_in
->
i_height
)
)
{
/* if the mouse is outside the window, stop moving the piece/group */
p_sys
->
b_mouse_drag
=
false
;
p_sys
->
b_mouse_mvt
=
true
;
}
else
if
(
i_dx
!=
0
||
i_dy
!=
0
)
{
vlc_mutex_lock
(
&
p_sys
->
pce_lock
);
puzzle_move_group
(
p_filter
,
p_sys
->
i_mouse_drag_pce
,
i_dx
,
i_dy
);
vlc_mutex_unlock
(
&
p_sys
->
pce_lock
);
}
}
}
}
else
{
p_sys
->
i_selected
=
-
1
;
}
return
VLC_EGENERIC
;
}
modules/video_filter/puzzle.h
0 → 100644
View file @
4b4f62a0
/*****************************************************************************
* puzzle.h : Puzzle game
*****************************************************************************
* Copyright (C) 2005-2009 VLC authors and VideoLAN
* Copyright (C) 2013 Vianney Boyer
* $Id$
*
* Authors: Vianney Boyer <vlcvboyer -at- gmail -dot- com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VLC_PUZZLE_H
#define VLC_PUZZLE_H 1
#include "puzzle_mgt.h"
struct
filter_sys_t
{
bool
b_init
;
bool
b_bake_request
;
bool
b_shape_init
;
bool
b_change_param
;
bool
b_finished
;
bool
b_shuffle_rqst
;
bool
b_mouse_drag
;
bool
b_mouse_mvt
;
param_t
s_allocated
;
param_t
s_current_param
;
param_t
s_new_param
;
uint32_t
i_done_count
,
i_tmp_done_count
;
int32_t
i_mouse_drag_pce
;
int32_t
i_mouse_x
,
i_mouse_y
;
int16_t
i_pointed_pce
;
int8_t
i_mouse_action
;
uint32_t
i_solve_acc_loop
,
i_solve_grp_loop
,
i_calc_corn_loop
;
int32_t
i_magnet_accuracy
;
int32_t
*
pi_group_qty
;
int32_t
*
pi_order
;
/* array which contains final pieces location (used in BASIC GAME MODE) */
puzzle_array_t
***
ps_puzzle_array
;
/* array [row][col][plane] preset of location & size of each piece in the original image */
piece_shape_t
**
ps_pieces_shapes
;
/* array [each piece type (PCE_TYPE_NBR * negative * 4: top...)][each plane] of piece definition */
piece_t
*
ps_pieces
;
/* list [piece] of pieces data. */
piece_t
*
ps_pieces_tmp
;
/* used when sorting layers */
puzzle_plane_t
*
ps_desk_planes
;
puzzle_plane_t
*
ps_pict_planes
;
uint8_t
i_preview_pos
;
int32_t
i_selected
;
vlc_mutex_t
lock
,
pce_lock
;
int32_t
i_auto_shuffle_countdown_val
,
i_auto_solve_countdown_val
;
point_t
**
ps_bezier_pts_H
;
};
picture_t
*
Filter
(
filter_t
*
,
picture_t
*
);
int
puzzle_Callback
(
vlc_object_t
*
,
char
const
*
,
vlc_value_t
,
vlc_value_t
,
void
*
);
int
puzzle_mouse
(
filter_t
*
,
vlc_mouse_t
*
,
const
vlc_mouse_t
*
,
const
vlc_mouse_t
*
);
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment