Anonymous Contribution of new Mirror plugin
authorGood Guy <[email protected]>
Mon, 28 Aug 2023 17:19:52 +0000 (11:19 -0600)
committerGood Guy <[email protected]>
Mon, 28 Aug 2023 17:19:52 +0000 (11:19 -0600)
cinelerra-5.1/expanders.txt
cinelerra-5.1/plugin_defs
cinelerra-5.1/plugins/Makefile
cinelerra-5.1/plugins/mirror/Makefile [new file with mode: 0644]
cinelerra-5.1/plugins/mirror/mirror.C [new file with mode: 0644]
cinelerra-5.1/plugins/mirror/mirror.h [new file with mode: 0644]
cinelerra-5.1/plugins/mirror/mirrorwindow.C [new file with mode: 0644]
cinelerra-5.1/plugins/mirror/mirrorwindow.h [new file with mode: 0644]

index a255de993b1eba7ea0d099ec73c319ee46b92a3f..0e3ae8418ca1b4203e53916579493d4862438b20 100644 (file)
@@ -134,6 +134,7 @@ Video Effects
                Crop & Position
                Flip
                Lens
+               Mirror
                Perspective
                Polar
                Rotate
index 9f7d5396de3cbbd2a30a19b377127a07de9c8bd9..cb3c700a90ce5ab280a6229909b2bad5db39182f 100644 (file)
@@ -76,6 +76,7 @@ video := \
        liveaudio \
        livevideo \
        loopvideo \
+       mirror \
        motion \
        motion2 \
        motion51 \
index 40d50c129a8b0739bb96a0acb9f36989e7ac5497..22aaf43374cbde791029ebd6a5623c46e13becbc 100644 (file)
@@ -98,6 +98,7 @@ DIRS = $(OPENCV_OBJS) \
        $(LIVEDVB) \
        loopaudio \
        loopvideo \
+       mirror \
        motion \
        motion51 \
        motion2point \
diff --git a/cinelerra-5.1/plugins/mirror/Makefile b/cinelerra-5.1/plugins/mirror/Makefile
new file mode 100644 (file)
index 0000000..1df0b5b
--- /dev/null
@@ -0,0 +1,11 @@
+include ../../plugin_defs
+
+OBJS = $(OBJDIR)/mirror.o \
+       $(OBJDIR)/mirrorwindow.o
+
+PLUGIN = mirror
+
+include ../../plugin_config
+
+$(OBJDIR)/mirror.o: mirror.C
+$(OBJDIR)/mirror.o: mirrorwindow.C
diff --git a/cinelerra-5.1/plugins/mirror/mirror.C b/cinelerra-5.1/plugins/mirror/mirror.C
new file mode 100644 (file)
index 0000000..847e587
--- /dev/null
@@ -0,0 +1,644 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * 2023. Derivative by Flip plugin.
+*/
+
+#include "clip.h"
+#include "bccmodels.h"
+#include "bchash.h"
+#include "filexml.h"
+#include "mirror.h"
+#include "mirrorwindow.h"
+#include "language.h"
+#include "mwindow.h"
+
+#include <stdint.h>
+#include <string.h>
+#include <math.h>
+
+REGISTER_PLUGIN(MirrorMain)
+
+
+
+
+
+
+MirrorConfig::MirrorConfig()
+{
+       reset(RESET_DEFAULT_SETTINGS);
+}
+
+void MirrorConfig::reset(int clear)
+{
+       switch(clear) {
+               case RESET_REFLECTION_CENTER_X :
+                       reflection_center_x = 50.00;
+                       mirror_horizontal = 1;
+                       mirror_swaphorizontal = 0;
+                       break;
+               case RESET_REFLECTION_CENTER_Y :
+                       reflection_center_y = 50.00;
+                       mirror_vertical = 1;
+                       mirror_swapvertical = 0;
+                       break;
+               case RESET_ALL :
+               case RESET_DEFAULT_SETTINGS :
+               default:
+                       mirror_horizontal = 1;
+                       mirror_swaphorizontal = 0;
+                       mirror_vertical = 0;
+                       mirror_swapvertical = 0;
+                       reflection_center_enable = 0;
+                       reflection_center_x = 50.00;
+                       reflection_center_y = 50.00;
+                       break;
+       }
+}
+
+void MirrorConfig::copy_from(MirrorConfig &that)
+{
+       mirror_horizontal = that.mirror_horizontal;
+       mirror_swaphorizontal = that.mirror_swaphorizontal;
+       mirror_vertical = that.mirror_vertical;
+       mirror_swapvertical = that.mirror_swapvertical;
+       reflection_center_enable = that.reflection_center_enable;
+       reflection_center_x = that.reflection_center_x;
+       reflection_center_y = that.reflection_center_y;
+}
+
+int MirrorConfig::equivalent(MirrorConfig &that)
+{
+       return EQUIV(mirror_horizontal, that.mirror_horizontal) &&
+                EQUIV(mirror_swaphorizontal, that.mirror_swaphorizontal) &&
+               EQUIV(mirror_vertical, that.mirror_vertical) && 
+                EQUIV(mirror_swapvertical, that.mirror_swapvertical) &&
+                EQUIV(reflection_center_enable, that.reflection_center_enable) &&
+               EQUIV(reflection_center_x, that.reflection_center_x) &&
+               EQUIV(reflection_center_y, that.reflection_center_y);
+}
+
+void MirrorConfig::interpolate(MirrorConfig &prev,
+       MirrorConfig &next,
+       int64_t prev_frame,
+       int64_t next_frame,
+       int64_t current_frame)
+{
+       double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
+       double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
+
+       this->mirror_horizontal = prev.mirror_horizontal;
+        this->mirror_swaphorizontal = prev.mirror_swaphorizontal;
+       this->mirror_vertical = prev.mirror_vertical;
+        this->mirror_swapvertical = prev.mirror_swapvertical;
+       this->reflection_center_enable = prev.reflection_center_enable;
+       this->reflection_center_x = prev.reflection_center_x * prev_scale + next.reflection_center_x * next_scale;
+       this->reflection_center_y = prev.reflection_center_y * prev_scale + next.reflection_center_y * next_scale;
+}
+
+
+
+
+
+
+
+
+
+
+MirrorMain::MirrorMain(PluginServer *server)
+ : PluginVClient(server)
+{
+
+}
+
+MirrorMain::~MirrorMain()
+{
+
+}
+
+const char* MirrorMain::plugin_title() { return N_("Mirror"); }
+int MirrorMain::is_realtime() { return 1; }
+
+
+#define SWAPCOPY_PIXELS(components, in, out) \
+{ \
+       in[0] = out[0]; \
+       in[1] = out[1]; \
+       in[2] = out[2]; \
+       if(components == 4) \
+       { \
+               in[3] = out[3]; \
+       } \
+}
+
+
+#define MIRROR_MACRO(type, components) \
+{ \
+       type **input_rows, **output_rows; \
+       type *input_row, *output_row; \
+       input_rows = ((type**)frame->get_rows()); \
+       output_rows = ((type**)frame->get_rows()); \
+ \
+       if (!config.reflection_center_enable) \
+       { \
+               /* HORIZONTAL ONLY */ \
+               if(config.mirror_horizontal && !config.mirror_vertical && !config.mirror_swaphorizontal) \
+               { \
+                       for(i = 0; i < h; i++) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[i] + (w - 1) * components; \
+                               for(k = 0; k < w / 2; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                       input_row += components; \
+                                       output_row -= components; \
+                               } \
+                       } \
+               } \
+               /* HORIZONTAL SWAP ONLY */ \
+               else if(config.mirror_horizontal && !config.mirror_vertical && config.mirror_swaphorizontal) \
+               { \
+                       for(i = 0; i < h; i++) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[i] + (w - 1) * components; \
+                               for(k = 0; k < w / 2; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, input_row, output_row); \
+                                       input_row += components; \
+                                       output_row -= components; \
+                               } \
+                       } \
+               } \
+               /* VERTICAL ONLY */ \
+               else if(config.mirror_vertical && !config.mirror_horizontal && !config.mirror_swapvertical) \
+               { \
+                       for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[j]; \
+                               for(k = 0; k < w; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                       output_row += components; \
+                                       input_row += components; \
+                               } \
+                       } \
+               } \
+               /* VERTICAL SWAP ONLY */ \
+               else if(config.mirror_vertical && !config.mirror_horizontal && config.mirror_swapvertical) \
+               { \
+                       for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[j]; \
+                               for(k = 0; k < w; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, input_row, output_row); \
+                                       output_row += components; \
+                                       input_row += components; \
+                               } \
+                       } \
+               } \
+               /* HORIZONTAL and VERTICAL */ \
+               else if(config.mirror_horizontal && config.mirror_vertical && !config.mirror_swaphorizontal && !config.mirror_swapvertical) \
+               { \
+                       /* HORIZONTAL ONLY */ \
+                       for(i = 0; i < h; i++) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[i] + (w - 1) * components; \
+                               for(k = 0; k < w / 2; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                       input_row += components; \
+                                       output_row -= components; \
+                               } \
+                       } \
+                       /* VERTICAL ONLY */ \
+                       for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[j]; \
+                               for(k = 0; k < w; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                       output_row += components; \
+                                       input_row += components; \
+                               } \
+                       } \
+               } \
+               /* HORIZONTAL with SWAP and VERTICAL with SWAP */ \
+               else if(config.mirror_horizontal && config.mirror_vertical && config.mirror_swaphorizontal && config.mirror_swapvertical) \
+               { \
+                       /* HORIZONTAL SWAP ONLY */ \
+                       for(i = 0; i < h; i++) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[i] + (w - 1) * components; \
+                               for(k = 0; k < w / 2; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, input_row, output_row); \
+                                       input_row += components; \
+                                       output_row -= components; \
+                               } \
+                       } \
+                       /* VERTICAL SWAP ONLY */ \
+                       for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[j]; \
+                               for(k = 0; k < w; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, input_row, output_row); \
+                                       output_row += components; \
+                                       input_row += components; \
+                               } \
+                       } \
+               } \
+               /* HORIZONTAL with SWAP and VERTICAL ONLY */ \
+               else if(config.mirror_horizontal && config.mirror_vertical && config.mirror_swaphorizontal && !config.mirror_swapvertical) \
+               { \
+                       /* HORIZONTAL SWAP ONLY */ \
+                       for(i = 0; i < h; i++) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[i] + (w - 1) * components; \
+                               for(k = 0; k < w / 2; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, input_row, output_row); \
+                                       input_row += components; \
+                                       output_row -= components; \
+                               } \
+                       } \
+                       /* VERTICAL ONLY */ \
+                       for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[j]; \
+                               for(k = 0; k < w; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                       output_row += components; \
+                                       input_row += components; \
+                               } \
+                       } \
+               } \
+               /* HORIZONTAL ONLY and VERTICAL with SWAP */ \
+               else if(config.mirror_horizontal && config.mirror_vertical && !config.mirror_swaphorizontal && config.mirror_swapvertical) \
+               { \
+                       /* HORIZONTAL ONLY */ \
+                       for(i = 0; i < h; i++) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[i] + (w - 1) * components; \
+                               for(k = 0; k < w / 2; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                       input_row += components; \
+                                       output_row -= components; \
+                               } \
+                       } \
+                       /* VERTICAL SWAP ONLY */ \
+                       for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+                       { \
+                               input_row = input_rows[i]; \
+                               output_row = output_rows[j]; \
+                               for(k = 0; k < w; k++) \
+                               { \
+                                       SWAPCOPY_PIXELS(components, input_row, output_row); \
+                                       output_row += components; \
+                                       input_row += components; \
+                               } \
+                       } \
+               } \
+       } \
+ \
+       else if(config.reflection_center_enable) \
+       { \
+               if(config.mirror_vertical) \
+               { \
+                       int y_pixel = (int)round(config.reflection_center_y / 100.00 * h); \
+                       if(config.reflection_center_y < 50.00) \
+                       { \
+                               int valueY_source = y_pixel + 1; \
+                               int valueY_destination = y_pixel - 1; \
+                               for(int i = 0; i < y_pixel; i++) \
+                               { \
+                                       input_row = input_rows[valueY_source]; \
+                                       output_row = output_rows[valueY_destination]; \
+                                       for(k = 0; k < w; k++) \
+                                       { \
+                                               SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                               output_row += components; \
+                                               input_row += components; \
+                                       } \
+                                       valueY_source += 1; \
+                                       valueY_destination -= 1; \
+                               } \
+                       } \
+                       else if(config.reflection_center_y > 50.00) \
+                       { \
+                               int valueY_source = y_pixel - 1; \
+                               int valueY_destination = y_pixel + 1; \
+                               for(int i = 0; i < (h - y_pixel - 1); i++) \
+                               { \
+                                       input_row = input_rows[valueY_source]; \
+                                       output_row = output_rows[valueY_destination]; \
+                                       for(k = 0; k < w; k++) \
+                                       { \
+                                               SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                               output_row += components; \
+                                               input_row += components; \
+                                       } \
+                                       valueY_source -= 1; \
+                                       valueY_destination += 1; \
+                               } \
+                       } \
+                       else /* Y_PERCENT == 50.00 */ \
+                       { \
+                               for(i = 0, j = h - 1; i < h / 2; i++, j--) \
+                               { \
+                                       input_row = input_rows[i]; \
+                                       output_row = output_rows[j]; \
+                                       for(k = 0; k < w; k++) \
+                                       { \
+                                               SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                               output_row += components; \
+                                               input_row += components; \
+                                       } \
+                               } \
+                       } \
+               } \
+ \
+               if(config.mirror_horizontal) \
+               { \
+                       int x_pixel = (int)round(config.reflection_center_x / 100.00 * w); \
+                       if(config.reflection_center_x < 50.00) \
+                       { \
+                               int valueX_source = x_pixel + 1; \
+                               int valueX_destination = x_pixel - 1; \
+                               for(i = 0; i < h; i++) \
+                               { \
+                                       input_row = input_rows[i] + valueX_source * components; \
+                                       output_row = output_rows[i] + valueX_destination * components; \
+                                       for(k = 0; k < x_pixel; k++) \
+                                       { \
+                                               SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                               output_row -= components; \
+                                               input_row += components; \
+                                       } \
+                               } \
+                       } \
+                       else if(config.reflection_center_x > 50.00) \
+                       { \
+                               int valueX_source = x_pixel - 1; \
+                               int valueX_destination = x_pixel + 1; \
+                               for(i = 0; i < h; i++) \
+                               { \
+                                       input_row = input_rows[i] + valueX_source * components; \
+                                       output_row = output_rows[i] + valueX_destination * components; \
+                                       for(k = 0; k < (w - x_pixel - 1); k++) \
+                                       { \
+                                               SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                               output_row += components; \
+                                               input_row -= components; \
+                                       } \
+                               } \
+                       } \
+                       else /* X_PERCENT == 50.00 */ \
+                       { \
+                               for(i = 0; i < h; i++) \
+                               { \
+                                       input_row = input_rows[i]; \
+                                       output_row = output_rows[i] + (w - 1) * components; \
+                                       for(k = 0; k < w / 2; k++) \
+                                       { \
+                                               SWAPCOPY_PIXELS(components, output_row, input_row); \
+                                               input_row += components; \
+                                               output_row -= components; \
+                                       } \
+                               } \
+                       } \
+               } \
+       } \
+}
+
+int MirrorMain::process_buffer(VFrame *frame,
+               int64_t start_position,
+               double frame_rate)
+{
+       int i, j, k;
+       int w = frame->get_w();
+       int h = frame->get_h();
+       int colormodel = frame->get_color_model();
+
+       load_configuration();
+
+// THIS CODE WAS FOR the FLIP Plugin!!!
+/*
+       read_frame(frame,
+               0,
+               get_source_position(),
+               get_framerate(),
+               get_use_opengl());
+
+       if(get_use_opengl())
+       {
+               if(config.mirror_vertical || config.mirror_horizontal)
+                       return run_opengl();
+               else
+                       return 0;
+       }
+*/
+       read_frame(frame,
+               0,
+               start_position,
+               frame_rate,
+               get_use_opengl());
+
+       if(config.mirror_vertical || config.mirror_horizontal)
+               {
+               switch(colormodel)
+               {
+                       case BC_RGB888:
+                       case BC_YUV888:
+                               MIRROR_MACRO(unsigned char, 3);
+                               break;
+                       case BC_RGB_FLOAT:
+                               MIRROR_MACRO(float, 3);
+                               break;
+                       case BC_RGB161616:
+                       case BC_YUV161616:
+                               MIRROR_MACRO(uint16_t, 3);
+                               break;
+                       case BC_RGBA8888:
+                       case BC_YUVA8888:
+                               MIRROR_MACRO(unsigned char, 4);
+                               break;
+                       case BC_RGBA_FLOAT:
+                               MIRROR_MACRO(float, 4);
+                               break;
+                       case BC_RGBA16161616:
+                       case BC_YUVA16161616:
+                               MIRROR_MACRO(uint16_t, 4);
+                               break;
+               }
+       }
+       return 0;
+}
+
+
+NEW_WINDOW_MACRO(MirrorMain, MirrorWindow)
+LOAD_CONFIGURATION_MACRO(MirrorMain, MirrorConfig)
+
+void MirrorMain::update_gui()
+{
+       if(thread)
+       {
+               load_configuration();
+               thread->window->lock_window();
+               ((MirrorWindow*)thread->window)->mirror_horizontal->update((int)config.mirror_horizontal);
+               ((MirrorWindow*)thread->window)->mirror_swaphorizontal->update((int)config.mirror_swaphorizontal);
+               ((MirrorWindow*)thread->window)->mirror_vertical->update((int)config.mirror_vertical);
+               ((MirrorWindow*)thread->window)->mirror_swapvertical->update((int)config.mirror_swapvertical);
+               ((MirrorWindow*)thread->window)->reflection_center_enable->update(config.reflection_center_enable);
+               ((MirrorWindow*)thread->window)->reflection_center_x_text->update(config.reflection_center_x);
+               ((MirrorWindow*)thread->window)->reflection_center_x_slider->update(config.reflection_center_x);
+               ((MirrorWindow*)thread->window)->reflection_center_y_text->update(config.reflection_center_y);
+               ((MirrorWindow*)thread->window)->reflection_center_y_slider->update(config.reflection_center_y);
+               // Needed to update Enable-Disable GUI when "Show controls" is pressed.
+               ((MirrorWindow*)thread->window)->update_reflection_center_enable();
+               thread->window->unlock_window();
+       }
+}
+
+void MirrorMain::save_data(KeyFrame *keyframe)
+{
+       FileXML output;
+
+// cause data to be stored directly in text
+       output.set_shared_output(keyframe->xbuf);
+
+// Store data
+       output.tag.set_title("MIRROR");
+       output.tag.set_property("HORIZONTAL", config.mirror_horizontal);
+       output.tag.set_property("SWAP_HORIZONTAL", config.mirror_swaphorizontal);
+       output.tag.set_property("VERTICAL", config.mirror_vertical);
+       output.tag.set_property("SWAP_VERTICAL", config.mirror_swapvertical);
+       output.tag.set_property("REFLECTION_CENTER_ENABLE", config.reflection_center_enable);
+       output.tag.set_property("REFLECTION_CENTER_X", config.reflection_center_x);
+       output.tag.set_property("REFLECTION_CENTER_Y", config.reflection_center_y);
+       output.append_tag();
+       output.tag.set_title("/MIRROR");
+       output.append_tag();
+       output.append_newline();
+       output.terminate_string();
+// data is now in *text
+}
+
+void MirrorMain::read_data(KeyFrame *keyframe)
+{
+       FileXML input;
+
+       input.set_shared_input(keyframe->xbuf);
+
+       int result = 0;
+       config.mirror_vertical = config.mirror_horizontal = 0;
+       config.mirror_swapvertical = config.mirror_swaphorizontal = 0;
+
+       while(!result)
+       {
+               result = input.read_tag();
+
+               if(!result)
+               {
+                       if(input.tag.title_is("MIRROR"))
+                       {
+                               config.mirror_horizontal = input.tag.get_property("HORIZONTAL", config.mirror_horizontal);
+                               config.mirror_swaphorizontal = input.tag.get_property("SWAP_HORIZONTAL", config.mirror_swaphorizontal);
+                               config.mirror_vertical = input.tag.get_property("VERTICAL", config.mirror_vertical);
+                               config.mirror_swapvertical = input.tag.get_property("SWAP_VERTICAL", config.mirror_swapvertical);
+                               config.reflection_center_enable = input.tag.get_property("REFLECTION_CENTER_ENABLE", config.reflection_center_enable);
+                               config.reflection_center_x = input.tag.get_property("REFLECTION_CENTER_X", config.reflection_center_x);
+                               config.reflection_center_y = input.tag.get_property("REFLECTION_CENTER_Y", config.reflection_center_y);
+                       }
+               }
+       }
+}
+
+
+int MirrorMain::handle_opengl()
+{
+#ifdef HAVE_GL
+// FIXIT. When?! ... THIS CODE WAS FOR the FLIP Plugin!!!
+/*
+       get_output()->to_texture();
+       get_output()->enable_opengl();
+       get_output()->init_screen();
+       get_output()->bind_texture(0);
+
+       if(config.mirror_vertical && !config.mirror_horizontal)
+       {
+               get_output()->draw_texture(0,
+                       0,
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       0,
+                       get_output()->get_h(),
+                       get_output()->get_w(),
+                       0);
+       }
+
+       if(config.mirror_horizontal && !config.mirror_vertical)
+       {
+               get_output()->draw_texture(0,
+                       0,
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       get_output()->get_w(),
+                       0,
+                       0,
+                       get_output()->get_h());
+       }
+
+       if(config.mirror_vertical && config.mirror_horizontal)
+       {
+               get_output()->draw_texture(0,
+                       0,
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       get_output()->get_w(),
+                       get_output()->get_h(),
+                       0,
+                       0);
+       }
+
+       get_output()->set_opengl_state(VFrame::SCREEN);
+*/
+#endif
+       return 0;
+}
+
+
+
diff --git a/cinelerra-5.1/plugins/mirror/mirror.h b/cinelerra-5.1/plugins/mirror/mirror.h
new file mode 100644 (file)
index 0000000..5836a41
--- /dev/null
@@ -0,0 +1,77 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * 2023. Derivative by Flip plugin.
+*/
+
+#ifndef MIRROR_H
+#define MIRROR_H
+
+
+class MirrorMain;
+
+#include "filexml.h"
+#include "mirrorwindow.h"
+#include "guicast.h"
+#include "pluginvclient.h"
+
+class MirrorConfig
+{
+public:
+       MirrorConfig();
+       void reset(int clear);
+       void copy_from(MirrorConfig &that);
+       int equivalent(MirrorConfig &that);
+       void interpolate(MirrorConfig &prev,
+               MirrorConfig &next,
+               int64_t prev_frame,
+               int64_t next_frame,
+               int64_t current_frame);
+       int mirror_horizontal;
+       int mirror_swaphorizontal;
+       int mirror_vertical;
+       int mirror_swapvertical;
+       int reflection_center_enable;
+       float reflection_center_x, reflection_center_y;
+};
+
+class MirrorMain : public PluginVClient
+{
+public:
+       MirrorMain(PluginServer *server);
+       ~MirrorMain();
+
+       PLUGIN_CLASS_MEMBERS(MirrorConfig);
+
+// required for all realtime plugins
+       int process_buffer(VFrame *frame,
+               int64_t start_position,
+               double frame_rate);
+       int is_realtime();
+       void update_gui();
+       void save_data(KeyFrame *keyframe);
+       void read_data(KeyFrame *keyframe);
+       int handle_opengl();
+};
+
+
+#endif
diff --git a/cinelerra-5.1/plugins/mirror/mirrorwindow.C b/cinelerra-5.1/plugins/mirror/mirrorwindow.C
new file mode 100644 (file)
index 0000000..9cfb744
--- /dev/null
@@ -0,0 +1,424 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * 2023. Derivative by Flip plugin.
+*/
+
+#include "bcdisplayinfo.h"
+#include "mirrorwindow.h"
+#include "language.h"
+#include "theme.h"
+
+
+
+
+
+
+
+MirrorWindow::MirrorWindow(MirrorMain *client)
+ : PluginClientWindow(client, xS(420), yS(270), xS(420), yS(270), 0)
+{
+       this->client = client;
+}
+
+MirrorWindow::~MirrorWindow()
+{
+       delete mirror_horizontal;
+       delete mirror_swaphorizontal;
+       delete mirror_vertical;
+       delete mirror_swapvertical;
+       delete reflection_center_enable;
+       delete reflection_center_x_text;
+       delete reflection_center_x_slider;
+       delete reflection_center_y_text;
+       delete reflection_center_y_slider;
+       delete reflection_center_x_clr;
+       delete reflection_center_y_clr;
+       delete reset;
+}
+
+void MirrorWindow::create_objects()
+{
+       int xs10 = xS(10), xs20 = xS(20), xs200 = xS(200);
+       int ys10 = yS(10), ys20 = yS(20), ys30 = yS(30), ys40 = yS(40);
+       int x2 = xS(60), x3 = xS(180);
+       int x = xs10, y = ys10;
+       int clr_x = get_w()-x - xS(22); // note: clrBtn_w = 22
+
+       BC_TitleBar *title_bar;
+       BC_Bar *bar;
+
+
+// Direction section
+       add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xs20, xs10, _("Direction")));
+       y += ys20;
+       add_tool(mirror_horizontal = new MirrorToggle(client,
+               &(client->config.mirror_horizontal),
+               _("Horizontal"),
+               x,
+               y));
+       add_tool(mirror_swaphorizontal = new MirrorSwapSide(client,
+               &(client->config.mirror_swaphorizontal),
+               _("Swap LEFT-RIGHT side"),
+               (get_w() / 2),
+               y));
+       y += ys30;
+       add_tool(mirror_vertical = new MirrorToggle(client,
+               &(client->config.mirror_vertical),
+               _("Vertical"),
+               x,
+               y));
+       add_tool(mirror_swapvertical = new MirrorSwapSide(client,
+               &(client->config.mirror_swapvertical),
+               _("Swap TOP-BOTTOM side"),
+               (get_w() / 2),
+               y));
+       y += ys40;
+       add_tool(reflection_center_enable = new MirrorReflectionCenter(this, client, x, y));
+       y += ys40;
+
+// Reflection Center section
+       add_subwindow(title_bar = new BC_TitleBar(x, y, get_w()-2*x, xs20, xs10, _("Reflection Center")));
+       y += ys20;
+       add_tool(new BC_Title(x, y, _("X")));
+       add_tool(new BC_Title((x2-x), y, _("%")));
+       reflection_center_x_text = new MirrorReflectionCenterXText(this, client, (x + x2), y);
+       reflection_center_x_text->create_objects();
+       reflection_center_x_slider = new MirrorReflectionCenterXSlider(this, client, x3, y, xs200);
+       add_subwindow(reflection_center_x_slider);
+       add_subwindow(reflection_center_x_clr = new MirrorReflectionCenterClr(this, client,
+               clr_x, y, RESET_REFLECTION_CENTER_X));
+       y += ys30;
+       add_tool(new BC_Title(x, y, _("Y")));
+       add_tool(new BC_Title((x2-x), y, _("%")));
+       reflection_center_y_text = new MirrorReflectionCenterYText(this, client, (x + x2), y);
+       reflection_center_y_text->create_objects();
+       reflection_center_y_slider = new MirrorReflectionCenterYSlider(this, client, x3, y, xs200);
+       add_subwindow(reflection_center_y_slider);
+       add_subwindow(reflection_center_y_clr = new MirrorReflectionCenterClr(this, client,
+               clr_x, y, RESET_REFLECTION_CENTER_Y));
+       y += ys40;
+
+// Reset section
+       add_subwindow(bar = new BC_Bar(x, y, get_w()-2*x));
+       y += ys10;
+       add_tool(reset = new MirrorReset(client, this, x, y));
+       show_window();
+       flush();
+
+// Needed to update Enable-Disable GUI when "Show controls" is pressed.
+       update_reflection_center_enable();
+}
+
+
+void MirrorWindow::update_reflection_center_enable()
+{
+       if(client->config.reflection_center_enable)
+       {
+               reflection_center_x_text->enable();
+               reflection_center_x_slider->enable();
+               reflection_center_x_clr->enable();
+               reflection_center_y_text->enable();
+               reflection_center_y_slider->enable();
+               reflection_center_y_clr->enable();
+               mirror_swaphorizontal->disable();
+               mirror_swaphorizontal->hide_window();
+               mirror_swapvertical->disable();
+               mirror_swapvertical->hide_window();
+       }
+       else
+       {
+               reflection_center_x_text->disable();
+               reflection_center_x_slider->disable();
+               reflection_center_x_clr->disable();
+               reflection_center_y_text->disable();
+               reflection_center_y_slider->disable();
+               reflection_center_y_clr->disable();
+               mirror_swaphorizontal->enable();
+               mirror_swaphorizontal->show_window();
+               mirror_swapvertical->enable();
+               mirror_swapvertical->show_window();
+       }
+}
+
+void MirrorWindow::update(int clear)
+{
+       switch(clear) {
+               case RESET_REFLECTION_CENTER_X :
+                       reflection_center_x_text->update((float)client->config.reflection_center_x);
+                       reflection_center_x_slider->update((float)client->config.reflection_center_x);
+                       mirror_horizontal->update(client->config.mirror_horizontal);
+                       mirror_swaphorizontal->update(client->config.mirror_swaphorizontal);
+                       break;
+               case RESET_REFLECTION_CENTER_Y :
+                       reflection_center_y_text->update((float)client->config.reflection_center_y);
+                       reflection_center_y_slider->update((float)client->config.reflection_center_y);
+                       mirror_vertical->update(client->config.mirror_vertical);
+                       mirror_swapvertical->update(client->config.mirror_swapvertical);
+                       break;
+               case RESET_ALL :
+               case RESET_DEFAULT_SETTINGS :
+               default:
+                       mirror_horizontal->update(client->config.mirror_horizontal);
+                       mirror_swaphorizontal->update(client->config.mirror_swaphorizontal);
+                       mirror_vertical->update(client->config.mirror_vertical);
+                       mirror_swapvertical->update(client->config.mirror_swapvertical);
+                       reflection_center_enable->update(client->config.reflection_center_enable);
+                       reflection_center_x_text->update((float)client->config.reflection_center_x);
+                       reflection_center_x_slider->update((float)client->config.reflection_center_x);
+                       reflection_center_y_text->update((float)client->config.reflection_center_y);
+                       reflection_center_y_slider->update((float)client->config.reflection_center_y);
+                       break;
+       }
+}
+
+MirrorToggle::MirrorToggle(MirrorMain *client, int *output, char *string, int x, int y)
+ : BC_CheckBox(x, y, *output, string)
+{
+       this->client = client;
+       this->output = output;
+}
+MirrorToggle::~MirrorToggle()
+{
+}
+int MirrorToggle::handle_event()
+{
+       *output = get_value();
+       client->send_configure_change();
+       return 1;
+}
+
+MirrorSwapSide::MirrorSwapSide(MirrorMain *client, int *output, char *string, int x, int y)
+ : BC_CheckBox(x, y, *output, string)
+{
+       this->client = client;
+       this->output = output;
+}
+MirrorSwapSide::~MirrorSwapSide()
+{
+}
+int MirrorSwapSide::handle_event()
+{
+       *output = get_value();
+       client->send_configure_change();
+       return 1;
+}
+
+MirrorReflectionCenter::MirrorReflectionCenter(MirrorWindow *window, MirrorMain *client, int x, int y)
+ : BC_CheckBox(x, y, client->config.reflection_center_enable, _("Enable Reflection Center"))
+{
+        this->window = window;
+       this->client = client;
+}
+MirrorReflectionCenter::~MirrorReflectionCenter()
+{
+}
+int MirrorReflectionCenter::handle_event()
+{
+       client->config.reflection_center_enable = get_value();
+
+       if(client->config.reflection_center_enable)
+       {
+               window->reflection_center_x_text->enable();
+               window->reflection_center_x_slider->enable();
+               window->reflection_center_x_clr->enable();
+               window->reflection_center_y_text->enable();
+               window->reflection_center_y_slider->enable();
+               window->reflection_center_y_clr->enable();
+
+               window->mirror_swaphorizontal->disable();
+               window->mirror_swaphorizontal->hide_window();
+               window->mirror_swapvertical->disable();
+               window->mirror_swapvertical->hide_window();
+
+               window->reflection_center_x_text->update(client->config.reflection_center_x);
+               window->reflection_center_x_slider->update(client->config.reflection_center_x);
+               window->reflection_center_y_text->update(client->config.reflection_center_y);
+               window->reflection_center_y_slider->update(client->config.reflection_center_y);
+               window->mirror_swaphorizontal->update(client->config.mirror_swaphorizontal);
+               window->mirror_swapvertical->update(client->config.mirror_swapvertical);
+       }
+       else
+       {
+               window->reflection_center_x_text->disable();
+               window->reflection_center_x_slider->disable();
+               window->reflection_center_x_clr->disable();
+               window->reflection_center_y_text->disable();
+               window->reflection_center_y_slider->disable();
+               window->reflection_center_y_clr->disable();
+
+               window->mirror_swaphorizontal->enable();
+               window->mirror_swaphorizontal->show_window();
+               window->mirror_swapvertical->enable();
+               window->mirror_swapvertical->show_window();
+
+               window->reflection_center_x_text->update(client->config.reflection_center_x);
+               window->reflection_center_x_slider->update(client->config.reflection_center_x);
+               window->reflection_center_y_text->update(client->config.reflection_center_y);
+               window->reflection_center_y_slider->update(client->config.reflection_center_y);
+               window->mirror_swaphorizontal->update(client->config.mirror_swaphorizontal);
+               window->mirror_swapvertical->update(client->config.mirror_swapvertical);
+       }
+       client->send_configure_change();
+       return 1;
+}
+
+/* ********************************************** */
+/* **** MIRROR REFLECTION CENTER X ************** */
+MirrorReflectionCenterXText::MirrorReflectionCenterXText(MirrorWindow *window, MirrorMain *client,
+       int x,
+       int y)
+ : BC_TumbleTextBox(window, client->config.reflection_center_x,
+       (float)0.00, (float)100.00, x, y, xS(60), 2)
+{
+       this->window = window;
+       this->client = client;
+}
+
+MirrorReflectionCenterXText::~MirrorReflectionCenterXText()
+{
+}
+
+int MirrorReflectionCenterXText::handle_event()
+{
+       client->config.reflection_center_x = atof(get_text());
+       if(client->config.reflection_center_x > 100.00) client->config.reflection_center_x = 100.00;
+       else if(client->config.reflection_center_x < 0.00) client->config.reflection_center_x = 0.00;
+       window->reflection_center_x_text->update(client->config.reflection_center_x);
+       window->reflection_center_x_slider->update(client->config.reflection_center_x);
+       client->send_configure_change();
+       return 1;
+}
+
+MirrorReflectionCenterXSlider::MirrorReflectionCenterXSlider(MirrorWindow *window, MirrorMain *client,
+       int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, 0.00, 100.00, client->config.reflection_center_x)
+{
+       this->window = window;
+       this->client = client;
+       enable_show_value(0); // Hide caption
+       set_precision(0.01);
+}
+
+MirrorReflectionCenterXSlider::~MirrorReflectionCenterXSlider()
+{
+}
+
+int MirrorReflectionCenterXSlider::handle_event()
+{
+       client->config.reflection_center_x = get_value();
+       window->reflection_center_x_text->update(client->config.reflection_center_x);
+       window->update(RESET_ALL);
+       client->send_configure_change();
+       return 1;
+}
+/* ********************************************** */
+
+/* ********************************************** */
+/* **** MIRROR REFLECTION CENTER Y ************** */
+MirrorReflectionCenterYText::MirrorReflectionCenterYText(MirrorWindow *window, MirrorMain *client,
+       int x,
+       int y)
+ : BC_TumbleTextBox(window, client->config.reflection_center_y,
+       (float)0.00, (float)100.00, x, y, xS(60), 2)
+{
+       this->window = window;
+       this->client = client;
+}
+
+MirrorReflectionCenterYText::~MirrorReflectionCenterYText()
+{
+}
+
+int MirrorReflectionCenterYText::handle_event()
+{
+       client->config.reflection_center_y = atof(get_text());
+       if(client->config.reflection_center_y > 100.00) client->config.reflection_center_y = 100.00;
+       else if(client->config.reflection_center_y < 0.00) client->config.reflection_center_y = 0.00;
+       window->reflection_center_y_text->update(client->config.reflection_center_y);
+       window->reflection_center_y_slider->update(client->config.reflection_center_y);
+       client->send_configure_change();
+       return 1;
+}
+
+MirrorReflectionCenterYSlider::MirrorReflectionCenterYSlider(MirrorWindow *window, MirrorMain *client,
+       int x, int y, int w)
+ : BC_FSlider(x, y, 0, w, w, 0.00, 100.00, client->config.reflection_center_y)
+{
+       this->window = window;
+       this->client = client;
+       enable_show_value(0); // Hide caption
+       set_precision(0.01);
+}
+
+MirrorReflectionCenterYSlider::~MirrorReflectionCenterYSlider()
+{
+}
+
+int MirrorReflectionCenterYSlider::handle_event()
+{
+       client->config.reflection_center_y = get_value();
+       window->reflection_center_y_text->update(client->config.reflection_center_y);
+       window->update(RESET_ALL);
+       client->send_configure_change();
+       return 1;
+}
+/* ********************************************** */
+
+
+MirrorReflectionCenterClr::MirrorReflectionCenterClr(MirrorWindow *window, MirrorMain *client, int x, int y, int clear)
+ : BC_Button(x, y, client->get_theme()->get_image_set("reset_button"))
+{
+       this->window = window;
+       this->client = client;
+       this->clear = clear;
+}
+MirrorReflectionCenterClr::~MirrorReflectionCenterClr()
+{
+}
+int MirrorReflectionCenterClr::handle_event()
+{
+       client->config.reset(clear);
+       window->update(clear);
+       client->send_configure_change();
+       return 1;
+}
+
+MirrorReset::MirrorReset(MirrorMain *client, MirrorWindow *window, int x, int y)
+ : BC_GenericButton(x, y, _("Reset"))
+{
+       this->client = client;
+       this->window = window;
+}
+
+MirrorReset::~MirrorReset()
+{
+}
+
+int MirrorReset::handle_event()
+{
+       client->config.reset(RESET_ALL);
+       window->update_reflection_center_enable();
+       window->update(RESET_ALL);
+       client->send_configure_change();
+       return 1;
+}
diff --git a/cinelerra-5.1/plugins/mirror/mirrorwindow.h b/cinelerra-5.1/plugins/mirror/mirrorwindow.h
new file mode 100644 (file)
index 0000000..efd4ec1
--- /dev/null
@@ -0,0 +1,188 @@
+
+/*
+ * CINELERRA
+ * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+ * 2023. Derivative by Flip plugin.
+*/
+
+#ifndef MIRRORWINDOW_H
+#define MIRRORWINDOW_H
+
+
+class MirrorThread;
+class MirrorWindow;
+class MirrorToggle;
+class MirrorSwapSide;
+class MirrorReflectionCenter;
+class MirrorReflectionCenterXText;
+class MirrorReflectionCenterXSlider;
+class MirrorReflectionCenterYText;
+class MirrorReflectionCenterYSlider;
+class MirrorReflectionCenterClr;
+class MirrorReset;
+
+
+
+#include "filexml.inc"
+#include "mirror.h"
+#include "mutex.h"
+#include "pluginvclient.h"
+
+#define RESET_DEFAULT_SETTINGS 10
+#define RESET_ALL    0
+#define RESET_REFLECTION_CENTER_X 1
+#define RESET_REFLECTION_CENTER_Y 2
+
+
+class MirrorWindow : public PluginClientWindow
+{
+public:
+       MirrorWindow(MirrorMain *client);
+       ~MirrorWindow();
+
+       void create_objects();
+       void update(int clear);
+
+       void update_reflection_center_enable();
+
+       MirrorMain *client;
+       MirrorToggle *mirror_vertical;
+       MirrorToggle *mirror_horizontal;
+        MirrorSwapSide *mirror_swapvertical;
+        MirrorSwapSide *mirror_swaphorizontal;
+       MirrorReflectionCenter *reflection_center_enable;
+
+       // Mirror Reflection Center X, Y
+       MirrorReflectionCenterXText *reflection_center_x_text;
+       MirrorReflectionCenterXSlider *reflection_center_x_slider;
+       MirrorReflectionCenterClr *reflection_center_x_clr;
+
+       MirrorReflectionCenterYText *reflection_center_y_text;
+       MirrorReflectionCenterYSlider *reflection_center_y_slider;
+       MirrorReflectionCenterClr *reflection_center_y_clr;
+
+       MirrorReset *reset;
+};
+
+class MirrorToggle : public BC_CheckBox
+{
+public:
+       MirrorToggle(MirrorMain *client, int *output, char *string, int x, int y);
+       ~MirrorToggle();
+       int handle_event();
+
+       MirrorMain *client;
+       int *output;
+};
+
+class MirrorSwapSide : public BC_CheckBox
+{
+public:
+       MirrorSwapSide(MirrorMain *client, int *output, char *string, int x, int y);
+       ~MirrorSwapSide();
+       int handle_event();
+
+       MirrorMain *client;
+       int *output;
+};
+
+class MirrorReflectionCenter : public BC_CheckBox
+{
+public:
+       MirrorReflectionCenter(MirrorWindow *window, MirrorMain *client, int x, int y);
+       ~MirrorReflectionCenter();
+       int handle_event();
+
+       MirrorMain *client;
+       MirrorWindow *window;
+};
+
+class MirrorReflectionCenterXText : public BC_TumbleTextBox
+{
+public:
+       MirrorReflectionCenterXText(MirrorWindow *window,
+               MirrorMain *client,
+               int x,
+               int y);
+       ~MirrorReflectionCenterXText();
+       int handle_event();
+       MirrorMain *client;
+       MirrorWindow *window;
+};
+
+class MirrorReflectionCenterXSlider : public BC_FSlider
+{
+public:
+       MirrorReflectionCenterXSlider(MirrorWindow *window, MirrorMain *client,
+               int x, int y, int w);
+       ~MirrorReflectionCenterXSlider();
+       int handle_event();
+       MirrorWindow *window;
+       MirrorMain *client;
+};
+
+class MirrorReflectionCenterYText : public BC_TumbleTextBox
+{
+public:
+       MirrorReflectionCenterYText(MirrorWindow *window,
+               MirrorMain *client,
+               int x,
+               int y);
+       ~MirrorReflectionCenterYText();
+       int handle_event();
+       MirrorMain *client;
+       MirrorWindow *window;
+};
+
+class MirrorReflectionCenterYSlider : public BC_FSlider
+{
+public:
+       MirrorReflectionCenterYSlider(MirrorWindow *window, MirrorMain *client,
+               int x, int y, int w);
+       ~MirrorReflectionCenterYSlider();
+       int handle_event();
+       MirrorWindow *window;
+       MirrorMain *client;
+};
+
+class MirrorReflectionCenterClr : public BC_Button
+{
+public:
+       MirrorReflectionCenterClr(MirrorWindow *window, MirrorMain *client,
+               int x, int y, int clear);
+       ~MirrorReflectionCenterClr();
+       int handle_event();
+       MirrorWindow *window;
+       MirrorMain *client;
+       int clear;
+};
+
+class MirrorReset : public BC_GenericButton
+{
+public:
+       MirrorReset(MirrorMain *client, MirrorWindow *window, int x, int y);
+       ~MirrorReset();
+       int handle_event();
+       MirrorMain *client;
+       MirrorWindow *window;
+};
+
+#endif