X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fguicast%2Fbcpan.C;fp=cinelerra-5.1%2Fguicast%2Fbcpan.C;h=7af2d1eb3591ce18080de6a74cdbb4376e38ba70;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/guicast/bcpan.C b/cinelerra-5.1/guicast/bcpan.C new file mode 100644 index 00000000..7af2d1eb --- /dev/null +++ b/cinelerra-5.1/guicast/bcpan.C @@ -0,0 +1,587 @@ + +/* + * 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 + * + */ + +#include "bcpan.h" +#include "bcpixmap.h" +#include "bcpopup.h" +#include "bcresources.h" +#include "clip.h" +#include "colors.h" +#include "fonts.h" +#include "rotateframe.h" +#include "units.h" +#include "vframe.h" + +#include +#include + +BC_Pan::BC_Pan(int x, + int y, + int virtual_r, + float maxvalue, + int total_values, + int *value_positions, + int stick_x, + int stick_y, + float *values) + : BC_SubWindow(x, y, -1, -1, -1) +{ + this->virtual_r = virtual_r; + this->maxvalue = maxvalue; + this->total_values = total_values; + this->values = new float[total_values]; + memcpy(this->values, values, sizeof(float) * total_values); + this->value_positions = new int[total_values]; + memcpy(this->value_positions, value_positions, sizeof(int) * total_values); + this->value_x = new int[total_values]; + this->value_y = new int[total_values]; + this->stick_x = stick_x; + this->stick_y = stick_y; + get_channel_positions(value_x, + value_y, + value_positions, + virtual_r, + total_values); + if(stick_x < 0 || stick_y < 0) + calculate_stick_position(total_values, + value_positions, + values, + maxvalue, + virtual_r, + this->stick_x, + this->stick_y); + highlighted = 0; + popup = 0; + active = 0; + memset(images, 0, sizeof(BC_Pixmap*) * PAN_IMAGES); +} + +BC_Pan::~BC_Pan() +{ +//printf("BC_Pan::~BC_Pan 1\n"); + delete [] values; +//printf("BC_Pan::~BC_Pan 1\n"); + delete [] value_positions; +//printf("BC_Pan::~BC_Pan 1\n"); + delete [] value_x; +//printf("BC_Pan::~BC_Pan 1\n"); + delete [] value_y; +//printf("BC_Pan::~BC_Pan 1\n"); + if(popup) delete popup; +//printf("BC_Pan::~BC_Pan 1\n"); + delete temp_channel; +//printf("BC_Pan::~BC_Pan 1\n"); + delete rotater; + for(int i = 0; i < PAN_IMAGES; i++) + if(images[i]) delete images[i]; +//printf("BC_Pan::~BC_Pan 2\n"); +} + +int BC_Pan::initialize() +{ + set_images(get_resources()->pan_data); + + BC_SubWindow::initialize(); + temp_channel = new VFrame; + temp_channel->set_use_shm(0); + temp_channel->reallocate(0, + -1, + 0, + 0, + 0, + get_resources()->pan_data[PAN_CHANNEL]->get_w(), + get_resources()->pan_data[PAN_CHANNEL]->get_h(), + get_resources()->pan_data[PAN_CHANNEL]->get_color_model(), + -1); + rotater = new RotateFrame(1, + get_resources()->pan_data[PAN_CHANNEL]->get_w(), + get_resources()->pan_data[PAN_CHANNEL]->get_h()); + draw(1, 0); + return 0; +} + +void BC_Pan::set_images(VFrame **data) +{ + for(int i = 0; i < PAN_IMAGES; i++) + { + if(images[i]) delete images[i]; + images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA); + } + w = images[PAN_UP]->get_w(); + h = images[PAN_UP]->get_h(); +} + +int BC_Pan::button_press_event() +{ + // there are two modes of operation... + if (popup) + { if (popup->is_event_win() && get_button_down() && get_buttonpress() == 1) + { + active = 1; + x_origin = popup->get_cursor_x(); + y_origin = popup->get_cursor_y(); + stick_x_origin = stick_x; + stick_y_origin = stick_y; + return 1; + } else + { + deactivate(); + return 0; + } + } + if(is_event_win() && get_button_down() && get_buttonpress() == 1) + { + hide_tooltip(); + activate(); + active = 1; + x_origin = get_cursor_x(); + y_origin = get_cursor_y(); + stick_x_origin = stick_x; + stick_y_origin = stick_y; + draw_popup(); + return 1; + } + return 0; +} + +int BC_Pan::cursor_motion_event() +{ + if(popup && get_button_down() && get_buttonpress() == 1) + { + stick_x = stick_x_origin + get_cursor_x() - x_origin; + stick_y = stick_y_origin + get_cursor_y() - y_origin; + CLAMP(stick_x, 0, virtual_r * 2); + CLAMP(stick_y, 0, virtual_r * 2); + stick_to_values(); + draw_popup(); + handle_event(); + return 1; + } + return 0; +} + +int BC_Pan::button_release_event() +{ + if(popup) + { + hide_tooltip(); + deactivate(); + draw(1, 1); + return 1; + } + return 0; +} + +int BC_Pan::repeat_event(int64_t duration) +{ + if( highlighted && !active && !tooltip_done && + tooltip_text && tooltip_text[0] != 0 && + duration == top_level->get_resources()->tooltip_delay ) + { + show_tooltip(); + tooltip_done = 1; + return 1; + } + return 0; +} + +int BC_Pan::cursor_enter_event() +{ + if(is_event_win() && !highlighted) + { + tooltip_done = 0; + highlighted = 1; + draw(1, 1); + } + return 0; +} + +int BC_Pan::cursor_leave_event() +{ + if(highlighted) + { + highlighted = 0; + hide_tooltip(); + draw(1, 1); + } + return 0; +} + + + +int BC_Pan::deactivate() +{ + if(popup) delete popup; + popup = 0; + active = 0; + return 0; +} + +int BC_Pan::activate(int popup_x, int popup_y) +{ + int x, y; + Window tempwin; + + active = 0; + if (popup_x < 0 || popup_y < 0) + { + XTranslateCoordinates(top_level->display, + win, + top_level->rootwin, + 0, + 0, + &x, + &y, + &tempwin); + + x -= (images[PAN_POPUP]->get_w() - get_w()) / 2; + y -= (images[PAN_POPUP]->get_h() - get_h()) / 2; + if (x < 0) x = 0; + } + else { + XTranslateCoordinates(top_level->display, + top_level->win, top_level->rootwin, + popup_x, popup_y, &x, &y, &tempwin); + x -= images[PAN_POPUP]->get_w() / 2; + y -= images[PAN_POPUP]->get_h() / 2; + if (x < 0) x = 0; + } + + delete popup; + popup = new BC_Popup(this, x, y, + images[PAN_POPUP]->get_w(), + images[PAN_POPUP]->get_h(), + 0, 0, images[PAN_POPUP]); + draw_popup(); + flush(); + return 0; +} + +int BC_Pan::update(int x, int y) +{ + if(x != stick_x || y != stick_y) + { + stick_x = x; + stick_y = y; + stick_to_values(); + draw(1, 1); + } + return 0; +} + +void BC_Pan::draw_popup() +{ + popup->draw_background(0, 0, popup->get_w(), popup->get_h()); + + int x1, y1; + float rotate_angle; + float scale = (float)(popup->get_w() - + get_resources()->pan_data[PAN_CHANNEL]->get_w()) / + (virtual_r * 2); + set_color(get_resources()->pan_text_color); + set_font(SMALLFONT); + + for(int i = 0; i < total_values; i++) + { + x1 = (int)(value_x[i] * scale); + y1 = (int)(value_y[i] * scale); + rotate_angle = value_positions[i]; + rotate_angle = -rotate_angle; + while(rotate_angle < 0) rotate_angle += 360; + rotater->rotate(temp_channel, + get_resources()->pan_data[PAN_CHANNEL], + rotate_angle, + 0); + BC_Pixmap *temp_pixmap = new BC_Pixmap(popup, + temp_channel, + PIXMAP_ALPHA); + popup->draw_pixmap(temp_pixmap, x1, y1); + delete temp_pixmap; + + char string[BCTEXTLEN]; + float value = values[i] + 0.005; + sprintf(string, "%.1f", value); + popup->draw_text(x1, y1 + get_text_height(SMALLFONT), string); + } + + x1 = (int)(stick_x * scale); + y1 = (int)(stick_y * scale); + popup->draw_pixmap(images[PAN_STICK], x1, y1); + popup->flash(); +} + +#define PICON_W 6 +#define PICON_H 6 + +void BC_Pan::draw(int flash, int flush) +{ + draw_top_background(parent_window, 0, 0, w, h); + + draw_pixmap(images[highlighted ? PAN_HI : PAN_UP]); + get_channel_positions(value_x, + value_y, + value_positions, + virtual_r, + total_values); + +// draw channels + int x1, y1; + float scale = (float)(get_w() - PICON_W) / (virtual_r * 2); + set_color(RED); + + for(int i = 0; i < total_values; i++) + { +// printf("BC_Pan::draw 1 %d %d %d %d\n", +// i, +// value_positions[i], +// value_x[i], +// value_y[i]); + x1 = (int)(value_x[i] * scale); + y1 = (int)(value_y[i] * scale); +//printf("BC_Pan::draw 2 %d %d\n", x1, y1); + CLAMP(x1, 0, get_w() - PICON_W); + CLAMP(y1, 0, get_h() - PICON_H); + draw_pixmap(images[PAN_CHANNEL_SMALL], x1, y1); +// draw_box(x1, y1, PICON_W, PICON_H); + } + +// draw stick + set_color(GREEN); + x1 = (int)(stick_x * scale); + y1 = (int)(stick_y * scale); + +//printf("BC_Pan::draw 2 %d %d\n", x1, y1); + CLAMP(x1, 0, get_w() - PICON_W); + CLAMP(y1, 0, get_h() - PICON_H); + + draw_pixmap(images[PAN_STICK_SMALL], x1, y1); +// x2 = x1 + PICON_W; +// y2 = y1 + PICON_H; +// draw_line(x1, y1, x2, y2); +// draw_line(x2, y1, x1, y2); + + if(flash) this->flash(0); + if(flush) this->flush(); +} + +int BC_Pan::stick_to_values() +{ + return stick_to_values(values, + total_values, + value_positions, + stick_x, + stick_y, + virtual_r, + maxvalue); +} + +int BC_Pan::stick_to_values(float *values, + int total_values, + int *value_positions, + int stick_x, + int stick_y, + int virtual_r, + float maxvalue) +{ +// find shortest distance to a channel + float shortest = 2 * virtual_r, test_distance; + int i; + int *value_x = new int[total_values]; + int *value_y = new int[total_values]; + + get_channel_positions(value_x, value_y, value_positions, virtual_r, total_values); + for(i = 0; i < total_values; i++) + { + if((test_distance = distance(stick_x, + value_x[i], + stick_y, + value_y[i])) < shortest) + shortest = test_distance; + } + +// get values for channels + if(shortest == 0) + { + for(i = 0; i < total_values; i++) + { + if(distance(stick_x, value_x[i], stick_y, value_y[i]) == shortest) + values[i] = maxvalue; + else + values[i] = 0; + } + } + else + { + for(i = 0; i < total_values; i++) + { + values[i] = shortest; + values[i] -= (float)(distance(stick_x, + value_x[i], + stick_y, + value_y[i]) - shortest); + if(values[i] < 0) values[i] = 0; + values[i] = values[i] / shortest * maxvalue; + } + } + + for(i = 0; i < total_values; i++) + { + values[i] = Units::quantize10(values[i]); + } + + delete [] value_x; + delete [] value_y; + return 0; +} + + +float BC_Pan::distance(int x1, int x2, int y1, int y2) +{ + return hypot(x2 - x1, y2 - y1); +} + +int BC_Pan::change_channels(int new_channels, int *value_positions) +{ + delete values; + delete this->value_positions; + delete value_x; + delete value_y; + + values = new float[new_channels]; + this->value_positions = new int[new_channels]; + value_x = new int[new_channels]; + value_y = new int[new_channels]; + total_values = new_channels; + for(int i = 0; i < new_channels; i++) + { + this->value_positions[i] = value_positions[i]; + } + get_channel_positions(value_x, + value_y, + value_positions, + virtual_r, + total_values); + stick_to_values(); + draw(1, 1); + return 0; +} + +int BC_Pan::get_channel_positions(int *value_x, + int *value_y, + int *value_positions, + int virtual_r, + int total_values) +{ + for(int i = 0; i < total_values; i++) + { + rdtoxy(value_x[i], value_y[i], value_positions[i], virtual_r); + } + return 0; +} + +int BC_Pan::get_total_values() +{ + return total_values; +} + +float BC_Pan::get_value(int channel) +{ + return values[channel]; +} + +int BC_Pan::get_stick_x() +{ + return stick_x; +} + +int BC_Pan::get_stick_y() +{ + return stick_y; +} + +float* BC_Pan::get_values() +{ + return values; +} + +int BC_Pan::rdtoxy(int &x, int &y, int a, int virtual_r) +{ + float radians = (float)a / 360 * 2 * M_PI; + + y = (int)(sin(radians) * virtual_r); + x = (int)(cos(radians) * virtual_r); + x += virtual_r; + y = virtual_r - y; + return 0; +} + +void BC_Pan::calculate_stick_position(int total_values, + int *value_positions, + float *values, + float maxvalue, + int virtual_r, + int &stick_x, + int &stick_y) +{ +// If 2 channels have positive values, use weighted average + int channel1 = -1; + int channel2 = -1; + + for(int i = 0; i < total_values; i++) + { + if(values[i] > 0.001) + { + if(channel1 < 0) channel1 = i; + else + if(channel2 < 0) channel2 = i; + else + break; + } + } + + if(channel1 >= 0 && channel2 >= 0) + { + int x1, y1, x2, y2; + rdtoxy(x1, y1, value_positions[channel1], virtual_r); + rdtoxy(x2, y2, value_positions[channel2], virtual_r); + stick_x = (x1 + x2) / 2; + stick_y = (y1 + y2) / 2; + } + else + { + +// use highest value as location of stick + float highest_value = 0; + int angle = 0; + + for(int i = 0; i < total_values; i++) + { + if(values[i] > highest_value) + { + highest_value = values[i]; + angle = value_positions[i]; + } + } + rdtoxy(stick_x, stick_y, angle, virtual_r); + } + +} +