tBane Temat założony przez niniejszego użytkownika |
[C++ SFML] Schowek - Logika wycinania, wklejania i przesuwania obrazu » 2025-08-14 11:47:05 Cześć. Mam problem, którego nie potrafię samodzielnie rozwiąza, a mianowicie wklejanie i wycinanie obrazu. Na początek przedstawię funkcje kopiowania i wycinania. void copyImage( sf::Image & image ) { sf::Vector2i s( std::min( start_px.x, end_px.x ), std::min( start_px.y, end_px.y ) ); sf::Vector2i e( std::max( start_px.x, end_px.x ), std::max( start_px.y, end_px.y ) ); this->img = sf::Image(); this->img.create( e.x - s.x, e.y - s.y, sf::Color::Transparent ); this->img.copy( image, 0, 0, sf::IntRect( s.x, s.y, e.x - s.x, e.y - s.y ), false ); }
void cutImage( sf::Image & image ) { sf::Vector2i s( std::min( start_px.x, end_px.x ), std::min( start_px.y, end_px.y ) ); sf::Vector2i e( std::max( start_px.x, end_px.x ), std::max( start_px.y, end_px.y ) ); sf::Image background; background.create( e.x - s.x, e.y - s.y, sf::Color::Transparent ); image.copy( background, s.x, s.y, sf::IntRect( 0, 0, e.x - s.x, e.y - s.y ), false ); }
void pasteImage( sf::Image & image ) { sf::Vector2i s( std::min( start_px.x, end_px.x ), std::min( start_px.y, end_px.y ) ); sf::Vector2i e( std::max( start_px.x, end_px.x ), std::max( start_px.y, end_px.y ) ); image.copy( this->img, s.x, s.y, sf::IntRect( 0, 0, this->img.getSize().x, this->img.getSize().y ), true ); this->img = sf::Image(); }
Teraz próbuję opakować te funkcje w Eventy i robię to w następujący sposób: if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left ) { ElementGUI_pressed = this; if( tools->toolType == ToolType::Brush || tools->toolType == ToolType::Eraser ) drawPixels( colors_dialog->current_color ); if( tools->toolType == ToolType::Eraser ) drawPixels( sf::Color::Transparent ); if( tools->toolType == ToolType::Selector ) { if( selection->clickOnSelection( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ) ) { if( !selection->isMoved ) { selection->isMoved = true; selection->setOffset( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ); selection->copyImage( layers_dialog->getCurrentLayer()->image ); selection->cutImage( layers_dialog->getCurrentLayer()->image ); } } else { selection->start_px = worldToTile( worldMousePosition, position, size, zoom, zoom_delta ); selection->end_px = selection->start_px; selection->isMoved = false; } selecting = true; } }
if( event.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) { if( tools->toolType == ToolType::Brush ) { drawPixels( colors_dialog->getCurrentColor() ); } if( tools->toolType == ToolType::Eraser ) { drawPixels( sf::Color::Transparent ); } if( tools->toolType == ToolType::Selector ) { if( !selection->isMoved ) { selection->end_px = worldToTile( worldMousePosition, position, size, zoom, zoom_delta ); } else { selection->move( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ), layers_dialog->getCurrentLayer()->image.getSize() ); selecting = true; } } }
if( event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left ) { if( tools->toolType == ToolType::Selector ) { if( selection->isMoved ) { selection->isMoved = false; selection->pasteImage( layers_dialog->getCurrentLayer()->image ); } selecting =( std::abs( selection->start_px.x - selection->end_px.x ) >= 1 ) ||( std::abs( selection->start_px.y - selection->end_px.y ) >= 1 ); } }
No i niestety nie działa. Za każdym razem gdy przesunę zaznaczony fragment obrazu to nadpisuje mi on oryginalny obraz a nie powinien ponieważ nadal jest przesuwany. Obraz powinien być wklejany dopiero gdy zaznaczenie przestaje być aktywne. Chciałbym zrobić poprawnie przenoszenie grafiki ale nie wiem jak to zrobić.. Pomożecie ? Kodu jest dużo więc wkleiłem istotne fragmenty, ale jeżeli uważasz, że dobrze by było uruchomić projekt u siebie to dorzucam link do repozytorium. https://github.com/tBane1995/Anim-Paint.gitPowyższy kod znajduje się w pliku "Canvas.hpp" oraz "Selection.hpp" |
|
pekfos |
» 2025-08-14 21:02:10 Za każdym razem gdy przesunę zaznaczony fragment obrazu to nadpisuje mi on oryginalny obraz a nie powinien ponieważ nadal jest przesuwany. To czemu to napisałeś w obsłudze puszczenia LPM? Miałoby to więcej sensu w obsłudze naciśnięcia LPM poza obszarem zaznaczenia. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-15 06:06:36 Teraz pierwsze przesunięcie działa, a przy drugim kasuje zaznaczony obraz. Trzeba dodać jakąś flagę z tego co mi się wydaje. Ale jaką to nie mam pojęcia :-/ if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left ) { ElementGUI_pressed = this; if( tools->toolType == ToolType::Brush || tools->toolType == ToolType::Eraser ) drawPixels( colors_dialog->current_color ); if( tools->toolType == ToolType::Eraser ) drawPixels( sf::Color::Transparent ); if( tools->toolType == ToolType::Selector ) { if( selection->clickOnSelection( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ) ) { if( !selection->isMoved ) { selection->isMoved = true; selection->setOffset( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ); selection->copyImage( layers_dialog->getCurrentLayer()->image ); selection->cutImage( layers_dialog->getCurrentLayer()->image ); } } else { selection->pasteImage( layers_dialog->getCurrentLayer()->image ); selection->start_px = worldToTile( worldMousePosition, position, size, zoom, zoom_delta ); selection->end_px = selection->start_px; selection->isMoved = false; } selecting = true; } }
|
|
pekfos |
» 2025-08-15 12:13:23 A tą flagą nie jest selection->isMoved? Jak nie to co ta flaga w ogóle znaczy? Obecny błąd pewnie bierze się z kasowania tej flagi przy puszczeniu LPM. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-15 12:13:34 Udało się ! :D No więc tak. Należy dodać flagę sprawdzającą czy w zaznaczeniu jest jakiś obraz. void copyImage( sf::Image & image ) { sf::Vector2i s( std::min( start_px.x, end_px.x ), std::min( start_px.y, end_px.y ) ); sf::Vector2i e( std::max( start_px.x, end_px.x ), std::max( start_px.y, end_px.y ) ); this->img = sf::Image(); this->img.create( e.x - s.x, e.y - s.y, sf::Color::Transparent ); this->img.copy( image, 0, 0, sf::IntRect( s.x, s.y, e.x - s.x, e.y - s.y ), false ); hasImage = true; }
void cutImage( sf::Image & image ) { sf::Vector2i s( std::min( start_px.x, end_px.x ), std::min( start_px.y, end_px.y ) ); sf::Vector2i e( std::max( start_px.x, end_px.x ), std::max( start_px.y, end_px.y ) ); sf::Image background; background.create( e.x - s.x, e.y - s.y, sf::Color::Transparent ); image.copy( background, s.x, s.y, sf::IntRect( 0, 0, e.x - s.x, e.y - s.y ), false ); }
void pasteImage( sf::Image & image ) { sf::Vector2i s( std::min( start_px.x, end_px.x ), std::min( start_px.y, end_px.y ) ); sf::Vector2i e( std::max( start_px.x, end_px.x ), std::max( start_px.y, end_px.y ) ); image.copy( this->img, s.x, s.y, sf::IntRect( 0, 0, this->img.getSize().x, this->img.getSize().y ), true ); hasImage = false; this->img = sf::Image(); }
I teraz można sprawdzać czy obraz jest w zaznaczeniu i jeżeli nie jest to wtedy kopiować: if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left ) { ElementGUI_pressed = this; if( tools->toolType == ToolType::Brush || tools->toolType == ToolType::Eraser ) drawPixels( colors_dialog->current_color ); if( tools->toolType == ToolType::Eraser ) drawPixels( sf::Color::Transparent ); if( tools->toolType == ToolType::Selector ) { if( selection->clickOnSelection( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ) ) { if( !selection->isMoved ) { selection->isMoved = true; selection->setOffset( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ); if( !selection->hasImage ) { selection->copyImage( layers_dialog->getCurrentLayer()->image ); selection->cutImage( layers_dialog->getCurrentLayer()->image ); } } } else { selection->pasteImage( layers_dialog->getCurrentLayer()->image ); selection->start_px = worldToTile( worldMousePosition, position, size, zoom, zoom_delta ); selection->end_px = selection->start_px; selection->isMoved = false; } selecting = true; } }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-15 12:21:52 A tą flagą nie jest selection->isMoved? Jak nie to co ta flaga w ogóle znaczy? Obecny błąd pewnie bierze się z kasowania tej flagi przy puszczeniu LPM. A ta flaga jest do przesuwania zaznaczania na zasadzie drag and drop |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-15 15:50:58 Jeszcze jeden jest problem. Gdy się zaznaczy obszar i szybko się go będzie klikało i przesuwało, to obszar się zmniejsza choć nie powinien.   Wydaje mi się, że to wina tej funkcji: void move( sf::Vector2i point_px, sf::Vector2u map_size ) { bool x_reverse = start_px.x > end_px.x; bool y_reverse = start_px.y > end_px.y; sf::Vector2i s( std::min( start_px.x, end_px.x ), std::min( start_px.y, end_px.y ) ); sf::Vector2i e( std::max( start_px.x, end_px.x ), std::max( start_px.y, end_px.y ) ); sf::Vector2i sz = e - s; sf::Vector2i newMin = point_px + offset; start_px = newMin; end_px = newMin + sz; if( start_px.x < 0 ) { start_px.x = 0; end_px.x = sz.x; } if( start_px.y < 0 ) { start_px.y = 0; end_px.y = sz.y; } if( end_px.x >= map_size.x ) { end_px.x = map_size.x; start_px.x = end_px.x - sz.x; } if( end_px.y >= map_size.y ) { end_px.y = map_size.y; start_px.y = end_px.y - sz.y; } if( x_reverse == true ) std::swap( start_px.x, end_px.x ); if( y_reverse == true ) std::swap( start_px.y, end_px.y ); }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-08-15 17:21:52 Już błąd fixnięty - wystarczyło skasować obsługę zdarzenia MouseButtonReleased dla LPM i działa :-) if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left ) { ElementGUI_pressed = this; if( tools->toolType == ToolType::Brush || tools->toolType == ToolType::Eraser ) drawPixels( colors_dialog->current_color ); if( tools->toolType == ToolType::Eraser ) drawPixels( sf::Color::Transparent ); if( tools->toolType == ToolType::Selector ) { if( selection->clickOnSelection( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ) ) { if( selection->isMoved == false ) { selection->isMoved = true; selection->setOffset( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) ); if( !selection->hasImage ) { selection->copyImage( layers_dialog->getCurrentLayer()->image ); selection->cutImage( layers_dialog->getCurrentLayer()->image ); } } } else { selection->pasteImage( layers_dialog->getCurrentLayer()->image ); selection->start_px = worldToTile( worldMousePosition, position, size, zoom, zoom_delta ); selection->end_px = selection->start_px; selection->isMoved = false; } } }
else if( event.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) { if( tools->toolType == ToolType::Brush ) { drawPixels( colors_dialog->getCurrentColor() ); } if( tools->toolType == ToolType::Eraser ) { drawPixels( sf::Color::Transparent ); } if( tools->toolType == ToolType::Selector ) { if( selection->isMoved == false ) { } else { selection->move( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ), layers_dialog->getCurrentLayer()->image.getSize() ); } } } [ code ] |
|
« 1 » 2 |