Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++ SFML] Schowek - Logika wycinania, wklejania i przesuwania obrazu

Ostatnio zmodyfikowano 2025-08-18 07:51
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
» 2025-08-15 17:55:45
Jednak nie zadziałało .. Teraz źle oblicza offset dla przesunięcia

P-182892
tBane
Temat założony przez niniejszego użytkownika
» 2025-08-15 20:07:58
Rozwiązanie

C/C++
if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left ) {
   
ElementGUI_pressed = this;
   
   
   
if( tools->toolType == ToolType::Brush ) {
       
drawPixels( colors_dialog->getCurrentColor() );
   
}
   
else if( tools->toolType == ToolType::Eraser ) {
       
drawPixels( sf::Color::Transparent );
   
}
   
else if( tools->toolType == ToolType::Selector ) {
       
       
if( selection->state == SelectionState::Idle ) {
           
sf::Vector2i tile = worldToTile( worldMousePosition, position, size, zoom, zoom_delta );
           
selection->state = SelectionState::Selecting;
           
selection->rect = sf::IntRect( tile.x, tile.y, 0, 0 );
       
}
       
else if( selection->state == SelectionState::Selected ) {
           
sf::Vector2i tile = worldToTile( worldMousePosition, position, size, zoom, zoom_delta );
           
sf::IntRect norm = selection->normalizeRect( selection->rect );
           
           
if( selection->clickOnSelection( tile ) ) {
               
selection->offset = tile - sf::Vector2i( norm.left, norm.top );
               
selection->state = SelectionState::Moving;
               
               
if( !selection->hasImage ) {
                   
selection->copyImage( layers_dialog->getCurrentLayer()->image, norm );
                   
selection->cutImage( layers_dialog->getCurrentLayer()->image, norm );
               
}
            }
           
else {
               
if( selection->hasImage ) {
                   
selection->pasteImage( layers_dialog->getCurrentLayer()->image, norm );
                   
selection->hasImage = false; // wyczyść bufor po wklejeniu
                   
selection->img = sf::Image();
               
}
               
               
selection->state = SelectionState::Selecting;
               
selection->rect = sf::IntRect( tile.x, tile.y, 0, 0 );
           
}
        }
    }
}

else if( event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left ) {
   
if( tools->toolType == ToolType::Selector ) {
       
if( selection->state == SelectionState::Selecting ) {
           
sf::IntRect norm = selection->normalizeRect( selection->rect );
           
if( norm.width <= 0 || norm.height <= 0 ) {
               
selection->state = SelectionState::Idle;
               
selection->rect = sf::IntRect( 0, 0, 0, 0 );
           
}
           
else {
               
selection->rect = norm;
               
selection->state = SelectionState::Selected;
           
}
        }
       
else if( selection->state == SelectionState::Moving ) {
           
selection->rect = selection->normalizeRect( selection->rect );
           
selection->state = SelectionState::Selected;
       
}
    }
}

else if( event.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) {
   
   
if( tools->toolType == ToolType::Brush ) {
       
drawPixels( colors_dialog->getCurrentColor() );
   
}
   
else if( tools->toolType == ToolType::Eraser ) {
       
drawPixels( sf::Color::Transparent );
   
}
   
else if( tools->toolType == ToolType::Selector ) {
       
       
if( selection->state == SelectionState::Selecting ) {
           
sf::Vector2i tile = worldToTile( worldMousePosition, position, size, zoom, zoom_delta );
           
selection->rect.width = tile.x - selection->rect.left;
           
selection->rect.height = tile.y - selection->rect.top;
       
}
       
else if( selection->state == SelectionState::Moving ) {
           
sf::Vector2i tile = worldToTile( worldMousePosition, position, size, zoom, zoom_delta );
           
sf::Vector2i dst = tile - selection->offset;
           
selection->rect.left = dst.x;
           
selection->rect.top = dst.y;
       
}
    }
}
P-182893
tBane
Temat założony przez niniejszego użytkownika
» 2025-08-17 15:26:39
Cześć ponownie. Mam parę błędów, których nie mogę rozwiązać. Próbowałem dodać opcje dla schowka tzn. wytnij, kopiuj i wklej.
*Funkcja Kopiuj oraz Wklej działa (tools.hpp)
*Zaznaczenie obszaru i przesunięcie go nie działa :-/ (canvas.hpp)
*funkcja wytnij - działa tylko kopiowanie (tools.hpp)

https://github.com/tBane1995/Anim-Paint.git

C/C++
btn_paste = new ButtonWithBottomText( L"paste", sf::Color::Transparent, tools_text_color, tools_text_hover_color, getTexture( L"tex\\tools\\btn_paste.png" ), getTexture( L"tex\\tools\\btn_paste_hover.png" ) );
btn_paste->onclick_func =[ this ]() {
   
if( selection->state != SelectionState::Idle )
       
 copyImage( selection->img, layers_dialog->getCurrentLayer()->image, selection->normalizeRect() );
   
   
sf::Vector2i rect = loadImageFromClipboard( selection->img );
   
selection->rect = sf::IntRect( 0, 0, rect.x, rect.y );
   
selection->state = SelectionState::Selected;
   
selection->hasImage = true;
};
btn_cut = new ButtonWithBottomText( L"cut", sf::Color::Transparent, tools_text_color, tools_text_hover_color, getTexture( L"tex\\tools\\btn_cut.png" ), getTexture( L"tex\\tools\\btn_cut_hover.png" ) );
btn_cut->onclick_func =[ this ]() {
   
copyImageToClipboard( layers_dialog->getCurrentLayer()->image, selection->normalizeRect() );
   
cutImage( selection->img, selection->rect );
   
selection->rect = sf::IntRect( 0, 0, 0, 0 );
   
selection->state = SelectionState::Idle;
};
btn_copy = new ButtonWithBottomText( L"copy", sf::Color::Transparent, tools_text_color, tools_text_hover_color, getTexture( L"tex\\tools\\btn_copy.png" ), getTexture( L"tex\\tools\\btn_copy_hover.png" ) );
btn_copy->onclick_func =[ this ]() {
   
copyImageToClipboard( layers_dialog->getCurrentLayer()->image, selection->normalizeRect() );
   
copyImage( layers_dialog->getCurrentLayer()->image, selection->img, selection->normalizeRect() );
};

C/C++
void handleEvent( sf::Event & event ) {
   
   
if(( ElementGUI_hovered == this || ElementGUI_hovered == nullptr ) &&( ElementGUI_pressed == this || ElementGUI_pressed == nullptr ) ) {
       
if( bg_sprite.getGlobalBounds().contains( worldMousePosition ) ) {
           
           
if( tools->toolType == ToolType::Brush || tools->toolType == ToolType::Eraser ) {
               
brush_is_visible = true;
               
brush->setPosition( worldToTile( worldMousePosition, position, size, zoom, zoom_delta ) );
           
}
           
           
           
if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left ) {
               
if( tools->toolType == ToolType::Brush ) {
                   
drawPixels( tools->first_color->color );
               
}
               
else if( tools->toolType == ToolType::Eraser ) {
                   
drawPixels( sf::Color::Transparent );
               
}
               
               
else if( tools->toolType == ToolType::Selector ) {
                   
                   
if( selection->state == SelectionState::Idle ) {
                       
sf::Vector2i tile = worldToTile( worldMousePosition, position, size, zoom, zoom_delta );
                       
selection->state = SelectionState::Selecting;
                       
selection->rect = sf::IntRect( tile.x, tile.y, 0, 0 );
                   
}
                   
                }
            }
           
else if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Right ) {
               
if( tools->toolType == ToolType::Brush ) {
                   
drawPixels( tools->second_color->color );
               
}
            }
           
else if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Middle ) {
               
isMoved = true;
               
offset = bg_sprite.getPosition() - worldMousePosition;
           
}
           
else if( event.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) {
               
               
if( tools->toolType == ToolType::Brush ) {
                   
drawPixels( tools->first_color->color );
               
}
               
else if( tools->toolType == ToolType::Eraser ) {
                   
drawPixels( sf::Color::Transparent );
               
}
            }
           
else if( event.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Right ) ) {
               
               
if( tools->toolType == ToolType::Brush ) {
                   
drawPixels( tools->second_color->color );
               
}
            }
           
else if( event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Middle ) {
               
isMoved = false;
           
}
           
           
else if( event.type == sf::Event::MouseWheelScrolled ) {
               
sf::Vector2f mouseBeforeZoom = worldMousePosition - position;
               
float oldZoom = zoom;
               
               
zoom += 0.25f * event.mouseWheelScroll.delta;
               
zoom = std::clamp( zoom, min_zoom, max_zoom );
               
               
generateBackground( size );
               
               
sf::Vector2f mouseAfterZoom = mouseBeforeZoom *( zoom / oldZoom );
               
position +=( worldMousePosition -( position + mouseAfterZoom ) );
               
bg_sprite.setPosition( position );
               
           
}
        }
       
else {
           
brush_is_visible = false;
       
}
    }
   
else {
       
brush_is_visible = false;
   
}
   
   
if( event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left ) {
       
if(( ElementGUI_hovered == this || ElementGUI_hovered == nullptr ) &&( ElementGUI_pressed == this || ElementGUI_pressed == nullptr ) ) {
           
if( selection->state == SelectionState::Selected ) {
               
sf::Vector2i tile = worldToTile( worldMousePosition, position, zoom, zoom_delta );
               
sf::IntRect norm = selection->normalizeRect();
               
               
if( selection->clickOnSelection( tile ) ) {
                   
selection->offset = tile - sf::Vector2i( norm.left, norm.top );
                   
selection->state = SelectionState::Moving;
                   
                   
if( !selection->hasImage ) {
                       
copyImage( layers_dialog->getCurrentLayer()->image, selection->img, norm );
                       
cutImage( layers_dialog->getCurrentLayer()->image, norm );
                       
                   
}
                }
               
else {
                   
if( selection->hasImage ) {
                       
//copyImage(selection->img, layers_dialog->getCurrentLayer()->image, norm);
                       
selection->hasImage = false;
                       
//selection->img = sf::Image();
                   
}
                   
                   
selection->state = SelectionState::Selecting;
                   
tile = worldToTile( worldMousePosition, position, size, zoom, zoom_delta );
                   
selection->rect = sf::IntRect( tile.x, tile.y, 0, 0 );
               
}
            }
        }
    }
   
   
if( event.type == sf::Event::MouseMoved && sf::Mouse::isButtonPressed( sf::Mouse::Left ) ) {
       
if( tools->toolType == ToolType::Selector ) {
           
           
if( selection->state == SelectionState::Selecting ) {
               
sf::Vector2i tile = worldToTile( worldMousePosition, position, zoom, zoom_delta );
               
selection->rect.width = tile.x - selection->rect.left;
               
selection->rect.height = tile.y - selection->rect.top;
           
}
           
else if( selection->state == SelectionState::Moving ) {
               
sf::Vector2i tile = worldToTile( worldMousePosition, position, zoom, zoom_delta );
               
sf::Vector2i dst = tile - selection->offset;
               
selection->rect.left = dst.x;
               
selection->rect.top = dst.y;
           
}
        }
    }
   
   
if( event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left ) {
       
if(( ElementGUI_hovered == this || ElementGUI_hovered == nullptr ) &&( ElementGUI_pressed == this || ElementGUI_pressed == nullptr ) ) {
           
if( tools->toolType == ToolType::Selector ) {
               
if( selection->state == SelectionState::Selecting ) {
                   
sf::IntRect norm = selection->normalizeRect();
                   
if( norm.width <= 0 || norm.height <= 0 ) {
                       
selection->state = SelectionState::Idle;
                       
selection->rect = sf::IntRect( 0, 0, 0, 0 );
                   
}
                   
else {
                       
selection->rect = norm;
                       
selection->state = SelectionState::Selected;
                   
}
                }
               
else if( selection->state == SelectionState::Moving ) {
                   
selection->rect = selection->normalizeRect();
                   
selection->state = SelectionState::Selected;
               
}
            }
        }
    }
}
P-182894
pekfos
» 2025-08-17 18:36:47
C/C++
sf::RenderWindow * window = new sf::RenderWindow(
sf::VideoMode( view.getSize().x, view.getSize().y ),
"Anim Paint",
sf::Style::Titlebar | sf::Style::Resize | sf::Style::Close );
To jest błędne. Polegasz na nieokreślonej kolejności tworzenia zmiennych globalnych między jednostkami translacji. Jeżeli to się utworzy przed globalnym muteksem w implementacji SFML, to program się wywali przy starcie. U mnie musiałem to poprawić. Z podobnego powodu wszystkie twoje programy które testowałem wywalają się przy próbie czystego wyłączenia, tym razem przez kolejność niszczenia zmiennych globalnych.

C/C++
void copyImage( sf::Image & image ) {
   
   
// copy the image
   
this->img = sf::Image();
   
this->img.create( rect.width, rect.height, sf::Color::Transparent );
   
this->img.copy( image, 0, 0, sf::IntRect( 0, 0, rect.width, rect.height ), false );
   
hasImage = true;
   
}
Kopiujesz zaznaczony obraz zawsze z lewego górnego rogu całego obrazu, zamiast od (rect.left, rect.top).
P-182895
tBane
Temat założony przez niniejszego użytkownika
» 2025-08-17 19:17:38
U mnie się program nie wysypuje. Jaka jest więc poprawna metoda dynamicznego tworzenia okna?

Na pewno korzystasz z SFML 2.6.2? Bo w tym nowym 3.1 faktycznie pokazuje błędy.
P-182896
pekfos
» 2025-08-17 20:40:16
Twórz okno w main, albo w kodzie wywołanym w main. Tak jak to zapisałeś teraz, okno zostanie utworzone przed wykonaniem main, w czasie inicjalizacji zmiennych globalnych i nie masz żadnej gwarancji że SFML będzie w tym momencie sprawne.
P-182897
tBane
Temat założony przez niniejszego użytkownika
» 2025-08-17 20:47:47
Ok. Jutro poprawię wszystkie moje programy :-)
P-182898
tBane
Temat założony przez niniejszego użytkownika
» 2025-08-18 07:51:57
Poprawiłem wszystkie programy na Githubie, w których występował ten bug. Jakby ktoś jeszcze znalazł jakiś błąd, bug to proszę o kontakt. :-)
P-182899
1 « 2 »
Poprzednia strona Strona 2 z 2