From: Good Guy Date: Mon, 28 Aug 2023 17:19:52 +0000 (-0600) Subject: Anonymous Contribution of new Mirror plugin X-Git-Tag: 2023-08~4 X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=commitdiff_plain;h=07a0e1f6f49dc7c4229a3a296b722a0571c17e81 Anonymous Contribution of new Mirror plugin --- diff --git a/cinelerra-5.1/expanders.txt b/cinelerra-5.1/expanders.txt index a255de99..0e3ae841 100644 --- a/cinelerra-5.1/expanders.txt +++ b/cinelerra-5.1/expanders.txt @@ -134,6 +134,7 @@ Video Effects Crop & Position Flip Lens + Mirror Perspective Polar Rotate diff --git a/cinelerra-5.1/plugin_defs b/cinelerra-5.1/plugin_defs index 9f7d5396..cb3c700a 100644 --- a/cinelerra-5.1/plugin_defs +++ b/cinelerra-5.1/plugin_defs @@ -76,6 +76,7 @@ video := \ liveaudio \ livevideo \ loopvideo \ + mirror \ motion \ motion2 \ motion51 \ diff --git a/cinelerra-5.1/plugins/Makefile b/cinelerra-5.1/plugins/Makefile index 40d50c12..22aaf433 100644 --- a/cinelerra-5.1/plugins/Makefile +++ b/cinelerra-5.1/plugins/Makefile @@ -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 index 00000000..1df0b5be --- /dev/null +++ b/cinelerra-5.1/plugins/mirror/Makefile @@ -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 index 00000000..847e587a --- /dev/null +++ b/cinelerra-5.1/plugins/mirror/mirror.C @@ -0,0 +1,644 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 +#include +#include + +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 index 00000000..5836a418 --- /dev/null +++ b/cinelerra-5.1/plugins/mirror/mirror.h @@ -0,0 +1,77 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 index 00000000..9cfb7440 --- /dev/null +++ b/cinelerra-5.1/plugins/mirror/mirrorwindow.C @@ -0,0 +1,424 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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 index 00000000..efd4ec13 --- /dev/null +++ b/cinelerra-5.1/plugins/mirror/mirrorwindow.h @@ -0,0 +1,188 @@ + +/* + * CINELERRA + * Copyright (C) 2008 Adam Williams + * + * 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