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

[SFML 2.X] Notepad v2 - aplikacja notatnik wersja druga

Ostatnio zmodyfikowano 2025-06-07 14:37
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
» 2025-06-03 22:58:46
No więc napisałem ale pozostało mi jeszcze pozycjonowanie kursora. Nie mam pomysłu jak rozwiązać ten problem. Skąd wziąć pozycję kursora?

C/C++
if( event.text.unicode == '\b' ) {
   
// backspace
   
if( lines.size() > 0 && cursorPosition != sf::Vector2i( 0, 0 ) ) {
       
if( cursorPosition.x == 0 && cursorPosition.y > 0 ) {
           
           
// jeżeli pusta linia to usuń
           
if( lines[ cursorPosition.y - 1 ]->getString().toWideString().size() == 0 ) {
               
delete lines[ cursorPosition.y - 1 ];
               
lines[ cursorPosition.y - 1 ] = nullptr;
               
cursorPosition.y -= 1;
           
}
           
else {
               
//usuń znak z poprzedniej linii
               
std::wstring line = lines[ cursorPosition.y - 1 ]->getString().toWideString();
               
line.pop_back();
               
line = line + lines[ cursorPosition.y ]->getString().toWideString();
               
delete lines[ cursorPosition.y ];
               
lines[ cursorPosition.y ] = nullptr;
               
               
               
lines[ cursorPosition.y - 1 ]->setString( line );
           
}
           
           
lines = wrap_text( getTextFromLines() );
           
           
// positioning ?
           
       
}
       
else if( cursorPosition.x > 0 ) {
           
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
           
line.erase( cursorPosition.x - 1, 1 );
           
lines[ cursorPosition.y ]->setString( line );
           
cursorPosition.x -= 1;
       
}
       
    }
   
}
P-182454
tBane
Temat założony przez niniejszego użytkownika
» 2025-06-04 16:14:53
I znowu backspace nie działa poprawnie :-/ Dla pustej linii się wywala (miejsce z kodem oznaczyłem komentarzem "// backspace")


C/C++
#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
#include <cmath>
#include <filesystem>

sf::RenderWindow * window;

sf::Font font;
short characterSize;
sf::Color textColor;
sf::Color backgroundColor;

std::vector < sf::Text * > lines;

sf::Vector2i mousePosition;
sf::Vector2f worldMousePosition;

sf::RectangleShape cursor;
sf::Vector2i cursorPosition = sf::Vector2i( 0, 0 );

sf::Clock timeClock;
sf::Time currentTime;

std::vector < sf::Text * > wrap_text( std::wstring text ) {
   
   
std::vector < sf::Text * > lines;
   
   
std::wstring line = L"";
   
std::wstring word = L"";
   
   
for( auto & character: text ) {
       
       
       
if( character == L'\n' ) {
           
           
if( sf::Text( line + word, font, characterSize ).getGlobalBounds().width > window->getSize().x ) {
               
lines.push_back( new sf::Text( line, font, characterSize ) );
               
line = word;
               
word = L"";
           
}
           
else {
               
lines.push_back( new sf::Text( line + word, font, characterSize ) );
               
line = L"";
               
word = L"";
           
}
           
        }
       
else if( character == L' ' || character == L'\t' ) {
           
           
if( sf::Text( line + word, font, characterSize ).getGlobalBounds().width > window->getSize().x ) {
               
lines.push_back( new sf::Text( line, font, characterSize ) );
               
line = word + character;
               
word = L"";
           
}
           
else {
               
line = line + word + character;
               
word = L"";
           
}
           
        }
       
else
           
 word = word + character;
       
       
   
}
   
   
if( line != L"" || word != L"" ) {
       
       
lines.push_back( new sf::Text( line + word, font, characterSize ) );
   
}
   
   
for( int i = 0; i < lines.size(); i++ ) {
       
lines[ i ]->setPosition( sf::Vector2f( 0, i * font.getLineSpacing( characterSize ) ) );
       
lines[ i ]->setFillColor( textColor );
       
   
}
   
   
return lines;
   
}

void setCursorUp() {
   
   
if( cursorPosition.y > 0 ) {
       
       
float targetX = cursor.getGlobalBounds().left;
       
       
cursorPosition.y -= 1;
       
sf::Text * line = lines[ cursorPosition.y ];
       
size_t lineLength = line->getString().toWideString().size();
       
       
size_t closestIndex = 0;
       
float closestDistance = std::abs( line->findCharacterPos( 0 ).x - targetX );
       
       
for( size_t i = 1; i <= lineLength; ++i ) {
           
sf::Vector2f pos = line->findCharacterPos( i );
           
float distance = std::abs( pos.x - targetX );
           
           
if( distance < closestDistance ) {
               
closestIndex = i;
               
closestDistance = distance;
           
}
        }
       
       
cursorPosition.x = closestIndex;
       
cursor.setPosition( line->findCharacterPos( closestIndex ) );
   
}
}
void setCursorDown() {
   
if( cursorPosition.y < lines.size() - 1 ) {
       
       
float targetX = cursor.getGlobalBounds().left;
       
       
cursorPosition.y += 1;
       
sf::Text * line = lines[ cursorPosition.y ];
       
size_t lineLength = line->getString().toWideString().size();
       
       
size_t closestIndex = 0;
       
float closestDistance = std::abs( line->findCharacterPos( 0 ).x - targetX );
       
       
for( size_t i = 1; i <= lineLength; ++i ) {
           
sf::Vector2f pos = line->findCharacterPos( i );
           
float distance = std::abs( pos.x - targetX );
           
           
if( distance < closestDistance ) {
               
closestIndex = i;
               
closestDistance = distance;
           
}
        }
       
       
cursorPosition.x = closestIndex;
       
cursor.setPosition( line->findCharacterPos( closestIndex ) );
   
}
   
}

void cursorPositioning() {
   
   
if( lines.size() == 0 ) {
       
cursor.setPosition( 0, 0 );
       
return;
   
}
   
   
float line_length = lines[ cursorPosition.y ]->getString().toWideString().size();
   
   
sf::Vector2f pos;
   
pos.x = lines[ cursorPosition.y ]->findCharacterPos( cursorPosition.x ).x;
   
pos.y = cursorPosition.y * font.getLineSpacing( characterSize );
   
cursor.setPosition( pos );
}

int getIndex() {
   
int index = 0;
   
for( int i = 0; i < cursorPosition.y; ++i )
   
if( lines[ i ] != nullptr )
       
 index += lines[ i ]->getString().toWideString().size();
   
else
       
 index += 1;
   
   
index += cursorPosition.x;
   
   
return index;
}

sf::Vector2i getCursorPositionFromIndex( int index ) {
   
int total = 0;
   
for( int i = 0; i < lines.size(); ++i ) {
       
if( lines[ i ] != nullptr ) {
           
int len = lines[ i ]->getString().toWideString().size();
           
if( index <= total + len ) {
               
int x = std::min( index - total, len );
               
return sf::Vector2i( x, i );
           
}
           
total += len;
       
}
       
else
           
 total += 1;
       
   
}
   
// Jeśli indeks poza zakresem, ustaw na koniec ostatniej linii
   
int lastLine = lines.size() - 1;
   
return sf::Vector2i( lines[ lastLine ]->getString().toWideString().size(), lastLine );
}

std::wstring getTextFromLines() {
   
   
std::wstring text = L"";
   
for( int i = 0; i < lines.size(); i += 1 )
   
if( lines[ i ] != nullptr ) {
       
text = text + lines[ i ]->getString().toWideString();
   
}
   
   
return text;
}

std::string ConvertWideToUtf8( std::wstring wide ) {
   
return std::string( wide.begin(), wide.end() );
}

int main()
{
   
   
sf::View view( sf::FloatRect( 0, 0, 480, 640 ) );
   
window = new sf::RenderWindow( sf::VideoMode( view.getSize().x, view.getSize().y ), "Easy Notepad v2", sf::Style::Titlebar | sf::Style::Close );
   
   
font = sf::Font();
   
font.loadFromFile( "arial.ttf" );
   
   
characterSize = 17;
   
   
textColor = sf::Color( 192, 192, 192 );
   
backgroundColor = sf::Color( 48, 48, 48 );
   
   
lines = wrap_text(
   
L"Gracz najpierw zagaduje handlarza gdyż ten jest najbliżej. Handlarz oferuje skórzane ubranie w zamian za dostarczenie kilku skór od myśliwego, "
    L"którego gracz mijał wcześniej. Zielarka da graczowi trochę złota w zamian za przyniesienie kilku roślin leczniczych. "
    L"U kowala gracz może zakupić oręż - zwyczajny prosty miecz gdyż jest to niewprawiony kowal w miecznictwie. "
    L"Zaś do wieży mędrca nie da się dostać. Gracz rusza spowrotem do myśliwego po skóry, lecz ten jest nieufny, "
    L"ale ostatecznie zgadza się i daje graczowi skóry.\n"
// enter
   
L"Gracz wraca ze skórami do handlarza i odbiera nowe ubranie \"skórzane kurtka\" oraz \"skórzane spodnie\"."
    L"Handlarz jednak jeszcze jedno zadanie ma dla gracza. Dostawa towarów ze wschodu się opóźnia i trzeba sprawdzić "
    L"co się z nią stało i tak gracz rusza z kolejnym zadaniem \"spóźniona dostawa\"."
   
);
   
   
std::cout << "Current directory: " << std::filesystem::current_path() << std::endl;
   
   
cursor = sf::RectangleShape( sf::Vector2f( 2, characterSize ) );
   
cursor.setFillColor( sf::Color::Red );
   
   
sf::Clock clock;
   
   
while( window->isOpen() )
   
{
       
       
mousePosition = sf::Mouse::getPosition( * window ); // get the mouse position about window
       
worldMousePosition = window->mapPixelToCoords( mousePosition ); // get global mouse position
       
       
currentTime = timeClock.getElapsedTime();
       
       
sf::Event event;
       
while( window->pollEvent( event ) ) {
           
           
if( event.type == sf::Event::Closed )
               
 window->close();
           
           
if( event.type == sf::Event::Resized )
           
{
               
// Aktualizacja widoku bez skalowania
               
sf::View view;
               
view.setSize( static_cast < float >( event.size.width ), static_cast < float >( event.size.height ) );
               
view.setCenter( view.getSize() / 2.f );
               
window->setView( view );
           
}
           
else if( event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left ) {
               
//sf::Vector2i cur_pos = getCursorPosition();
                //setCursorPosition(cur_pos);
           
}
           
else if( event.type == sf::Event::TextEntered ) {
               
               
if( event.text.unicode < 128 ) {
                   
                   
                   
                   
if( event.text.unicode == '\b' ) {
                       
// backspace
                       
if( lines.size() > 0 && cursorPosition != sf::Vector2i( 0, 0 ) ) {
                           
if( cursorPosition.x == 0 && cursorPosition.y > 0 ) {
                               
                               
                               
if( lines[ cursorPosition.y ]->getString().toWideString().size() == 0 ) {
                                   
delete lines[ cursorPosition.y - 1 ];
                                   
lines[ cursorPosition.y - 1 ] = nullptr;
                                   
cursorPosition.y -= 1;
                                   
lines = wrap_text( getTextFromLines() );
                               
}
                               
else {
                                   
                                   
int index = getIndex();
                                   
std::wstring line1 = lines[ cursorPosition.y - 1 ]->getString().toWideString();
                                   
line1.pop_back();
                                   
std::wstring line2 = lines[ cursorPosition.y ]->getString().toWideString();
                                   
                                   
std::wstring line = line1 + line2;
                                   
                                   
delete lines[ cursorPosition.y ];
                                   
lines[ cursorPosition.y ] = nullptr;
                                   
                                   
index = index - 1;
                                   
                                   
lines[ cursorPosition.y - 1 ]->setString( line );
                                   
lines = wrap_text( getTextFromLines() );
                                   
cursorPosition = getCursorPositionFromIndex( index );
                               
}
                               
                            }
                           
else if( cursorPosition.x > 0 ) {
                               
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                               
line.erase( cursorPosition.x - 1, 1 );
                               
lines[ cursorPosition.y ]->setString( line );
                               
cursorPosition.x -= 1;
                               
int index = getIndex();
                               
lines = wrap_text( getTextFromLines() );
                               
cursorPosition = getCursorPositionFromIndex( index );
                           
}
                           
                        }
                       
                    }
                   
else if( event.text.unicode == 32 ) {
                       
// space
                       
                       
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                       
line.insert( cursorPosition.x, 1, ' ' );
                       
lines[ cursorPosition.y ]->setString( line );
                       
                       
lines = wrap_text( getTextFromLines() );
                       
cursorPosition.x += 1;
                       
                   
}
                   
else if( event.text.unicode == 13 ) {
                       
// enter
                       
                       
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                       
line.insert( cursorPosition.x, 1, '\n' );
                       
lines[ cursorPosition.y ]->setString( line );
                       
                       
lines = wrap_text( getTextFromLines() );
                       
                       
cursorPosition.y += 1;
                       
cursorPosition.x = 0;
                       
                       
                   
}
                   
else {
                       
// is character
                       
                       
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                       
line.insert( cursorPosition.x, 1, char( event.text.unicode ) );
                       
lines[ cursorPosition.y ]->setString( line );
                       
cursorPosition.x += 1;
                       
                       
lines = wrap_text( getTextFromLines() );
                   
}
                   
                   
                }
               
               
cursorPositioning();
           
}
           
else if( event.type == sf::Event::KeyPressed ) {
               
if( event.key.code == sf::Keyboard::Left ) {
                   
if( cursorPosition.x > 0 )
                       
 cursorPosition.x -= 1;
                   
else if( cursorPosition.y > 0 ) {
                       
cursorPosition.y -= 1;
                       
cursorPosition.x = lines[ cursorPosition.y ]->getString().toWideString().size();
                   
}
                   
                }
               
else if( event.key.code == sf::Keyboard::Right ) {
                   
if( cursorPosition.x < lines[ cursorPosition.y ]->getString().getSize() )
                       
 cursorPosition.x += 1;
                   
else if( cursorPosition.y < lines.size() - 1 ) {
                       
cursorPosition.x = 0;
                       
cursorPosition.y += 1;
                   
}
                   
                }
               
else if( event.key.code == sf::Keyboard::Up ) {
                   
setCursorUp();
                   
               
}
               
else if( event.key.code == sf::Keyboard::Down ) {
                   
                   
setCursorDown();
               
}
               
               
cursorPositioning();
               
           
}
           
           
        }
       
       
window->clear( backgroundColor );
       
for( auto & line: lines )
           
 window->draw( * line );
       
       
if( std::fmod( currentTime.asSeconds(), 0.6f ) < 0.3f )
           
 window->draw( cursor );
       
       
window->display();
   
}
}
P-182486
pekfos
» 2025-06-04 22:18:02
Dla pustej linii się wywala (miejsce z kodem oznaczyłem komentarzem "// backspace")
A co tu w ogóle działa? Podaj dokładne kroki do reprodukcji jak chcesz pogadać o konkretnym problemie.
P-182487
tBane
Temat założony przez niniejszego użytkownika
» 2025-06-04 22:23:11
Działa wprowadzanie tekstu i dodawanie spacji oraz kasowanie tekstu ze środka linii. Ale nie rozumiem dlaczego backspace przed pustą linią nie działa no i ten enter też nie chce działać no chyba, że dodam L'\n" w następującej funkcji:

C/C++
std::wstring getTextFromLines() {
   
   
std::wstring text = L"";
   
for( int i = 0; i < lines.size(); i += 1 )
   
if( lines[ i ] != nullptr ) {
       
text = text + lines[ i ]->getString().toWideString() + L"\n";
   
}
   
   
return text;
}

Ale backspace i tak nie działa .. :-/
P-182488
pekfos
» 2025-06-04 22:33:25
Mam tu problem żeby w ogóle dodać pustą linię. Enter robi dziwne rzeczy i wywala program.
C/C++
lines = wrap_text(
L"A\n\nB"
);
A

B
Kursor w pustej linii, backspace kasuje "A". To ma więcej sensu:
C/C++
if( lines[ cursorPosition.y ]->getString().toWideString().size() == 0 ) { // bieżąca linia jest pusta
   
delete lines[ cursorPosition.y ]; // więc skasuj bieżącą linię, nie poprzednią
   
lines[ cursorPosition.y ] = nullptr;
   
cursorPosition.x = lines[ cursorPosition.y - 1 ]->getString().getSize();
   
cursorPosition.y -= 1;
   
lines = wrap_text( getTextFromLines() );
}
Drugi przypadek: Kursor na początku 3. linii, przed literą B. Backspace wywala program na pop_back():
C/C++
int index = getIndex();
std::wstring line1 = lines[ cursorPosition.y - 1 ]->getString().toWideString();
line1.pop_back(); // <<----------, line1 jest puste
std::wstring line2 = lines[ cursorPosition.y ]->getString().toWideString();
Ten kod ma sens, natomiast linie miały mieć \n który chcesz tu usuwać, chyba że zdążyłeś zmienić koncepcję.
P-182489
tBane
Temat założony przez niniejszego użytkownika
» 2025-06-04 22:40:22
Ok. Dziękuję za odpowiedź :-) Już poprawiłem te linie i teraz działa. Pozostało tylko do zrobienia wrapowanie tekstu za kursorem.

// edit
teraz nie działa wprowadzanie znaków. Gdy wprowadza się znaki z klawiatury i linia przekroczy szerokość okna to ostatnie słowo trafia do nowej linii, gdy dalej wprowadza się znaki i kolejne słowo przekroczy dopuszczalną szerokość to też tworzy kolejnę linię. Trzeba zrobić tak, by poprawnie zawijało tekst.

C/C++
#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
#include <cmath>
#include <filesystem>

sf::RenderWindow * window;

sf::Font font;
short characterSize;
sf::Color textColor;
sf::Color backgroundColor;

std::vector < sf::Text * > lines;

sf::Vector2i mousePosition;
sf::Vector2f worldMousePosition;

sf::RectangleShape cursor;
sf::Vector2i cursorPosition = sf::Vector2i( 0, 0 );

sf::Clock timeClock;
sf::Time currentTime;

std::vector < sf::Text * > wrap_text( std::wstring text ) {
   
   
std::vector < sf::Text * > lines;
   
   
std::wstring line = L"";
   
std::wstring word = L"";
   
   
for( auto & character: text ) {
       
       
       
if( character == L'\n' ) {
           
           
if( sf::Text( line + word, font, characterSize ).getGlobalBounds().width > window->getSize().x ) {
               
lines.push_back( new sf::Text( line, font, characterSize ) );
               
line = word;
               
word = L"";
           
}
           
else {
               
lines.push_back( new sf::Text( line + word, font, characterSize ) );
               
line = L"";
               
word = L"";
           
}
           
        }
       
else if( character == L' ' || character == L'\t' ) {
           
           
if( sf::Text( line + word, font, characterSize ).getGlobalBounds().width > window->getSize().x ) {
               
lines.push_back( new sf::Text( line, font, characterSize ) );
               
line = word + character;
               
word = L"";
           
}
           
else {
               
line = line + word + character;
               
word = L"";
           
}
           
        }
       
else
           
 word = word + character;
       
       
   
}
   
   
if( line != L"" || word != L"" ) {
       
       
lines.push_back( new sf::Text( line + word, font, characterSize ) );
   
}
   
   
for( int i = 0; i < lines.size(); i++ ) {
       
lines[ i ]->setPosition( sf::Vector2f( 0, i * font.getLineSpacing( characterSize ) ) );
       
lines[ i ]->setFillColor( textColor );
       
   
}
   
   
return lines;
   
}

void setCursorUp() {
   
   
if( cursorPosition.y > 0 ) {
       
       
float targetX = cursor.getGlobalBounds().left;
       
       
cursorPosition.y -= 1;
       
sf::Text * line = lines[ cursorPosition.y ];
       
size_t lineLength = line->getString().toWideString().size();
       
       
size_t closestIndex = 0;
       
float closestDistance = std::abs( line->findCharacterPos( 0 ).x - targetX );
       
       
for( size_t i = 1; i <= lineLength; ++i ) {
           
sf::Vector2f pos = line->findCharacterPos( i );
           
float distance = std::abs( pos.x - targetX );
           
           
if( distance < closestDistance ) {
               
closestIndex = i;
               
closestDistance = distance;
           
}
        }
       
       
cursorPosition.x = closestIndex;
       
cursor.setPosition( line->findCharacterPos( closestIndex ) );
   
}
}
void setCursorDown() {
   
if( cursorPosition.y < lines.size() - 1 ) {
       
       
float targetX = cursor.getGlobalBounds().left;
       
       
cursorPosition.y += 1;
       
sf::Text * line = lines[ cursorPosition.y ];
       
size_t lineLength = line->getString().toWideString().size();
       
       
size_t closestIndex = 0;
       
float closestDistance = std::abs( line->findCharacterPos( 0 ).x - targetX );
       
       
for( size_t i = 1; i <= lineLength; ++i ) {
           
sf::Vector2f pos = line->findCharacterPos( i );
           
float distance = std::abs( pos.x - targetX );
           
           
if( distance < closestDistance ) {
               
closestIndex = i;
               
closestDistance = distance;
           
}
        }
       
       
cursorPosition.x = closestIndex;
       
cursor.setPosition( line->findCharacterPos( closestIndex ) );
   
}
   
}

void cursorPositioning() {
   
   
if( lines.size() == 0 ) {
       
cursor.setPosition( 0, 0 );
       
return;
   
}
   
   
float line_length = lines[ cursorPosition.y ]->getString().toWideString().size();
   
   
sf::Vector2f pos;
   
pos.x = lines[ cursorPosition.y ]->findCharacterPos( cursorPosition.x ).x;
   
pos.y = cursorPosition.y * font.getLineSpacing( characterSize );
   
cursor.setPosition( pos );
}

int getIndex() {
   
int index = 0;
   
for( int i = 0; i < cursorPosition.y; ++i )
   
if( lines[ i ] != nullptr )
       
 index += lines[ i ]->getString().toWideString().size();
   
else
       
 index += 1;
   
   
index += cursorPosition.x;
   
   
return index;
}

sf::Vector2i getCursorPositionFromIndex( int index ) {
   
int total = 0;
   
for( int i = 0; i < lines.size(); ++i ) {
       
if( lines[ i ] != nullptr ) {
           
int len = lines[ i ]->getString().toWideString().size();
           
if( index <= total + len ) {
               
int x = std::min( index - total, len );
               
return sf::Vector2i( x, i );
           
}
           
total += len;
       
}
       
else
           
 total += 1;
       
   
}
   
// Jeśli indeks poza zakresem, ustaw na koniec ostatniej linii
   
int lastLine = lines.size() - 1;
   
return sf::Vector2i( lines[ lastLine ]->getString().toWideString().size(), lastLine );
}

std::wstring getTextFromLines() {
   
   
std::wstring text = L"";
   
for( int i = 0; i < lines.size(); i += 1 )
   
if( lines[ i ] != nullptr ) {
       
text = text + lines[ i ]->getString().toWideString() + L"\n";
   
}
   
   
return text;
}

std::string ConvertWideToUtf8( std::wstring wide ) {
   
return std::string( wide.begin(), wide.end() );
}

int main()
{
   
   
sf::View view( sf::FloatRect( 0, 0, 480, 640 ) );
   
window = new sf::RenderWindow( sf::VideoMode( view.getSize().x, view.getSize().y ), "Easy Notepad v2", sf::Style::Titlebar | sf::Style::Close );
   
   
font = sf::Font();
   
font.loadFromFile( "arial.ttf" );
   
   
characterSize = 17;
   
   
textColor = sf::Color( 192, 192, 192 );
   
backgroundColor = sf::Color( 48, 48, 48 );
   
   
lines = wrap_text(
   
L"Gracz najpierw zagaduje handlarza gdyż ten jest najbliżej. Handlarz oferuje skórzane ubranie w zamian za dostarczenie kilku skór od myśliwego, "
    L"którego gracz mijał wcześniej. Zielarka da graczowi trochę złota w zamian za przyniesienie kilku roślin leczniczych. "
    L"U kowala gracz może zakupić oręż - zwyczajny prosty miecz gdyż jest to niewprawiony kowal w miecznictwie. "
    L"Zaś do wieży mędrca nie da się dostać. Gracz rusza spowrotem do myśliwego po skóry, lecz ten jest nieufny, "
    L"ale ostatecznie zgadza się i daje graczowi skóry.\n"
// enter
   
L"Gracz wraca ze skórami do handlarza i odbiera nowe ubranie \"skórzane kurtka\" oraz \"skórzane spodnie\"."
    L"Handlarz jednak jeszcze jedno zadanie ma dla gracza. Dostawa towarów ze wschodu się opóźnia i trzeba sprawdzić "
    L"co się z nią stało i tak gracz rusza z kolejnym zadaniem \"spóźniona dostawa\"."
   
);
   
   
std::cout << "Current directory: " << std::filesystem::current_path() << std::endl;
   
   
cursor = sf::RectangleShape( sf::Vector2f( 2, characterSize ) );
   
cursor.setFillColor( sf::Color::Red );
   
   
sf::Clock clock;
   
   
while( window->isOpen() )
   
{
       
       
mousePosition = sf::Mouse::getPosition( * window ); // get the mouse position about window
       
worldMousePosition = window->mapPixelToCoords( mousePosition ); // get global mouse position
       
       
currentTime = timeClock.getElapsedTime();
       
       
sf::Event event;
       
while( window->pollEvent( event ) ) {
           
           
if( event.type == sf::Event::Closed )
               
 window->close();
           
           
if( event.type == sf::Event::Resized )
           
{
               
// Aktualizacja widoku bez skalowania
               
sf::View view;
               
view.setSize( static_cast < float >( event.size.width ), static_cast < float >( event.size.height ) );
               
view.setCenter( view.getSize() / 2.f );
               
window->setView( view );
           
}
           
else if( event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left ) {
               
//sf::Vector2i cur_pos = getCursorPosition();
                //setCursorPosition(cur_pos);
           
}
           
else if( event.type == sf::Event::TextEntered ) {
               
               
if( event.text.unicode < 128 ) {
                   
                   
                   
                   
if( event.text.unicode == '\b' ) {
                       
// backspace
                       
if( lines.size() > 0 && cursorPosition != sf::Vector2i( 0, 0 ) ) {
                           
if( cursorPosition.x == 0 && cursorPosition.y > 0 ) {
                               
                               
                               
if( lines[ cursorPosition.y ]->getString().toWideString().size() == 0 ) {
                                   
delete lines[ cursorPosition.y ];
                                   
lines[ cursorPosition.y ] = nullptr;
                                   
cursorPosition.x = lines[ cursorPosition.y - 1 ]->getString().getSize();
                                   
cursorPosition.y -= 1;
                                   
lines = wrap_text( getTextFromLines() );
                               
}
                               
else {
                                   
                                   
int index = getIndex();
                                   
std::wstring line1 = lines[ cursorPosition.y - 1 ]->getString().toWideString();
                                   
std::wstring line2 = lines[ cursorPosition.y ]->getString().toWideString();
                                   
                                   
std::wstring line = line1 + line2;
                                   
                                   
delete lines[ cursorPosition.y ];
                                   
lines[ cursorPosition.y ] = nullptr;
                                   
                                   
//index = index - 1;
                                   
                                   
lines[ cursorPosition.y - 1 ]->setString( line );
                                   
lines = wrap_text( getTextFromLines() );
                                   
cursorPosition = getCursorPositionFromIndex( index );
                               
}
                               
                            }
                           
else if( cursorPosition.x > 0 ) {
                               
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                               
line.erase( cursorPosition.x - 1, 1 );
                               
lines[ cursorPosition.y ]->setString( line );
                               
cursorPosition.x -= 1;
                               
int index = getIndex();
                               
lines = wrap_text( getTextFromLines() );
                               
cursorPosition = getCursorPositionFromIndex( index );
                           
}
                           
                        }
                       
                    }
                   
else if( event.text.unicode == 32 ) {
                       
// space
                       
                       
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                       
line.insert( cursorPosition.x, 1, ' ' );
                       
lines[ cursorPosition.y ]->setString( line );
                       
                       
lines = wrap_text( getTextFromLines() );
                       
cursorPosition.x += 1;
                       
                   
}
                   
else if( event.text.unicode == 13 ) {
                       
// enter
                       
                       
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                       
line.insert( cursorPosition.x, 1, '\n' );
                       
lines[ cursorPosition.y ]->setString( line );
                       
                       
lines = wrap_text( getTextFromLines() );
                       
                       
cursorPosition.y += 1;
                       
cursorPosition.x = 0;
                       
                       
                   
}
                   
else {
                       
// is character
                       
                       
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                       
line.insert( cursorPosition.x, 1, char( event.text.unicode ) );
                       
lines[ cursorPosition.y ]->setString( line );
                       
cursorPosition.x += 1;
                       
                       
lines = wrap_text( getTextFromLines() );
                   
}
                   
                   
                }
               
               
cursorPositioning();
           
}
           
else if( event.type == sf::Event::KeyPressed ) {
               
if( event.key.code == sf::Keyboard::Left ) {
                   
if( cursorPosition.x > 0 )
                       
 cursorPosition.x -= 1;
                   
else if( cursorPosition.y > 0 ) {
                       
cursorPosition.y -= 1;
                       
cursorPosition.x = lines[ cursorPosition.y ]->getString().toWideString().size();
                   
}
                   
                }
               
else if( event.key.code == sf::Keyboard::Right ) {
                   
if( cursorPosition.x < lines[ cursorPosition.y ]->getString().getSize() )
                       
 cursorPosition.x += 1;
                   
else if( cursorPosition.y < lines.size() - 1 ) {
                       
cursorPosition.x = 0;
                       
cursorPosition.y += 1;
                   
}
                   
                }
               
else if( event.key.code == sf::Keyboard::Up ) {
                   
setCursorUp();
                   
               
}
               
else if( event.key.code == sf::Keyboard::Down ) {
                   
                   
setCursorDown();
               
}
               
               
cursorPositioning();
               
           
}
           
           
        }
       
       
window->clear( backgroundColor );
       
for( auto & line: lines )
           
 window->draw( * line );
       
       
if( std::fmod( currentTime.asSeconds(), 0.6f ) < 0.3f )
           
 window->draw( cursor );
       
       
window->display();
   
}
}
P-182490
tBane
Temat założony przez niniejszego użytkownika
» 2025-06-06 00:14:20
Nie jestem pewien co do tych emiterów na końcu linii bo wrapper wtedy nie zawija poprawnie tekstu
P-182491
tBane
Temat założony przez niniejszego użytkownika
» 2025-06-06 02:05:23
Skasowałem wszystko i wróciłem do punktu z enterem. Enter oczywiście nie działa - :-/ - nie rozumiem gdzie popełniłem błąd :-/

C/C++
#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
#include <cmath>
#include <filesystem>

sf::RenderWindow * window;

sf::Font font;
short characterSize;
sf::Color textColor;
sf::Color backgroundColor;

std::vector < sf::Text * > lines;

sf::Vector2i mousePosition;
sf::Vector2f worldMousePosition;

sf::RectangleShape cursor;
sf::Vector2i cursorPosition = sf::Vector2i( 0, 0 );

sf::Clock timeClock;
sf::Time currentTime;

std::vector < sf::Text * > wrap_text( std::wstring text ) {
   
   
std::vector < sf::Text * > lines;
   
   
std::wstring line = L"";
   
std::wstring word = L"";
   
   
for( auto & character: text ) {
       
       
if( character == L'\n' ) {
           
           
if( sf::Text( line + word, font, characterSize ).getGlobalBounds().width > window->getSize().x ) {
               
lines.push_back( new sf::Text( line, font, characterSize ) );
               
line = word;
               
word = L"";
           
}
           
else {
               
lines.push_back( new sf::Text( line + word, font, characterSize ) );
               
line = L"";
               
word = L"";
           
}
           
        }
       
else if( character == L' ' || character == L'\t' ) {
           
           
if( sf::Text( line + word, font, characterSize ).getGlobalBounds().width > window->getSize().x ) {
               
lines.push_back( new sf::Text( line, font, characterSize ) );
               
line = word + character;
               
word = L"";
           
}
           
else {
               
line = line + word + character;
               
word = L"";
           
}
           
        }
       
else
           
 word = word + character;
       
       
   
}
   
   
if( line != L"" || word != L"" ) {
       
       
lines.push_back( new sf::Text( line + word, font, characterSize ) );
   
}
   
   
for( int i = 0; i < lines.size(); i++ ) {
       
lines[ i ]->setPosition( sf::Vector2f( 0, i * font.getLineSpacing( characterSize ) ) );
       
lines[ i ]->setFillColor( textColor );
       
   
}
   
   
return lines;
   
}

void setCursorUp() {
   
   
if( cursorPosition.y > 0 ) {
       
       
float targetX = cursor.getGlobalBounds().left;
       
       
cursorPosition.y -= 1;
       
sf::Text * line = lines[ cursorPosition.y ];
       
size_t lineLength = line->getString().toWideString().size();
       
       
size_t closestIndex = 0;
       
float closestDistance = std::abs( line->findCharacterPos( 0 ).x - targetX );
       
       
for( size_t i = 1; i <= lineLength; ++i ) {
           
sf::Vector2f pos = line->findCharacterPos( i );
           
float distance = std::abs( pos.x - targetX );
           
           
if( distance < closestDistance ) {
               
closestIndex = i;
               
closestDistance = distance;
           
}
        }
       
       
cursorPosition.x = closestIndex;
       
cursor.setPosition( line->findCharacterPos( closestIndex ) );
   
}
}
void setCursorDown() {
   
if( cursorPosition.y < lines.size() - 1 ) {
       
       
float targetX = cursor.getGlobalBounds().left;
       
       
cursorPosition.y += 1;
       
sf::Text * line = lines[ cursorPosition.y ];
       
size_t lineLength = line->getString().toWideString().size();
       
       
size_t closestIndex = 0;
       
float closestDistance = std::abs( line->findCharacterPos( 0 ).x - targetX );
       
       
for( size_t i = 1; i <= lineLength; ++i ) {
           
sf::Vector2f pos = line->findCharacterPos( i );
           
float distance = std::abs( pos.x - targetX );
           
           
if( distance < closestDistance ) {
               
closestIndex = i;
               
closestDistance = distance;
           
}
        }
       
       
cursorPosition.x = closestIndex;
       
cursor.setPosition( line->findCharacterPos( closestIndex ) );
   
}
   
}

void cursorPositioning() {
   
   
float line_length = lines[ cursorPosition.y ]->getString().toWideString().size();
   
   
sf::Vector2f pos;
   
pos.x = lines[ cursorPosition.y ]->findCharacterPos( cursorPosition.x ).x;
   
pos.y = cursorPosition.y * font.getLineSpacing( characterSize );
   
cursor.setPosition( pos );
}

std::string ConvertWideToUtf8( std::wstring wide ) {
   
return std::string( wide.begin(), wide.end() );
}

std::wstring getTextFromLines() {
   
   
std::wstring text = L"";
   
for( int i = 0; i < lines.size(); i += 1 )
       
 text += lines[ i ]->getString().toWideString();
   
   
return text;
}

int main()
{
   
   
sf::View view( sf::FloatRect( 0, 0, 128, 640 ) );
   
window = new sf::RenderWindow( sf::VideoMode( view.getSize().x, view.getSize().y ), "Easy Notepad v2", sf::Style::Titlebar | sf::Style::Close );
   
   
font = sf::Font();
   
font.loadFromFile( "arial.ttf" );
   
   
characterSize = 17;
   
   
textColor = sf::Color( 192, 192, 192 );
   
backgroundColor = sf::Color( 48, 48, 48 );
   
   
lines = wrap_text(
   
L"Gracz najpierw zagaduje handlarza gdyż ten jest najbliżej. Handlarz oferuje skórzane ubranie w zamian za dostarczenie kilku skór od myśliwego, "
    L"którego gracz mijał wcześniej. Zielarka da graczowi trochę złota w zamian za przyniesienie kilku roślin leczniczych. "
    L"U kowala gracz może zakupić oręż - zwyczajny prosty miecz gdyż jest to niewprawiony kowal w miecznictwie. "
    L"Zaś do wieży mędrca nie da się dostać. Gracz rusza spowrotem do myśliwego po skóry, lecz ten jest nieufny, "
    L"ale ostatecznie zgadza się i daje graczowi skóry.\n"
// enter
   
L"Gracz wraca ze skórami do handlarza i odbiera nowe ubranie \"skórzane kurtka\" oraz \"skórzane spodnie\"."
    L"Handlarz jednak jeszcze jedno zadanie ma dla gracza. Dostawa towarów ze wschodu się opóźnia i trzeba sprawdzić "
    L"co się z nią stało i tak gracz rusza z kolejnym zadaniem \"spóźniona dostawa\"."
   
);
   
   
lines = wrap_text( L"Ala ma kota.\nMa też psa." );
   
   
cursor = sf::RectangleShape( sf::Vector2f( 2, characterSize ) );
   
cursor.setFillColor( sf::Color::Red );
   
   
sf::Clock clock;
   
   
while( window->isOpen() )
   
{
       
       
mousePosition = sf::Mouse::getPosition( * window ); // get the mouse position about window
       
worldMousePosition = window->mapPixelToCoords( mousePosition ); // get global mouse position
       
       
currentTime = timeClock.getElapsedTime();
       
       
sf::Event event;
       
while( window->pollEvent( event ) ) {
           
           
if( event.type == sf::Event::Closed )
               
 window->close();
           
           
if( event.type == sf::Event::Resized )
           
{
               
// Aktualizacja widoku bez skalowania
               
sf::View view;
               
view.setSize( static_cast < float >( event.size.width ), static_cast < float >( event.size.height ) );
               
view.setCenter( view.getSize() / 2.f );
               
window->setView( view );
           
}
           
else if( event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Left ) {
               
//sf::Vector2i cur_pos = getCursorPosition();
                //setCursorPosition(cur_pos);
           
}
           
else if( event.type == sf::Event::TextEntered ) {
               
               
if( event.text.unicode < 128 ) {
                   
                   
if( event.text.unicode == '\b' ) {
                       
// backspace
                       
                       
                   
}
                   
else if( event.text.unicode == 32 ) {
                       
// space
                       
                       
                   
}
                   
else if( event.text.unicode == 13 ) {
                       
// enter
                       
                        // pobierz linie
                       
std::wstring line = lines[ cursorPosition.y ]->getString().toWideString();
                       
                       
// wstaw enter w linii
                       
line.insert( cursorPosition.x, 1, L'\n' );
                       
                       
//przypisz linie z enterem
                       
lines[ cursorPosition.y ]->setString( line );
                       
                       
// pobierz text ze wszystkich linii ( w tym ten z podwojnym eneterem )
                       
std::wstring text = getTextFromLines();
                       
                       
// wrapuj pobrany text
                       
lines = wrap_text( text );
                       
                       
cursorPosition.y = 0;
                       
cursorPosition.x = 0;
                       
                       
                   
}
                   
else {
                       
// is character
                       
                        //std::wstring line = lines[cursorPosition.y]->getString().toWideString();
                        //line.insert(cursorPosition.x, 1, char(event.text.unicode));
                        //lines[cursorPosition.y]->setString(line);
                       
                       
                        //lines = wrap_text(getTextFromLines());
                   
}
                   
                   
                }
               
               
cursorPositioning();
           
}
           
else if( event.type == sf::Event::KeyPressed ) {
               
if( event.key.code == sf::Keyboard::Left ) {
                   
if( cursorPosition.x > 0 )
                       
 cursorPosition.x -= 1;
                   
else if( cursorPosition.y > 0 ) {
                       
cursorPosition.y -= 1;
                       
cursorPosition.x = lines[ cursorPosition.y ]->getString().toWideString().size();
                   
}
                   
                }
               
else if( event.key.code == sf::Keyboard::Right ) {
                   
if( cursorPosition.x < lines[ cursorPosition.y ]->getString().getSize() )
                       
 cursorPosition.x += 1;
                   
else if( cursorPosition.y < lines.size() - 1 ) {
                       
cursorPosition.x = 0;
                       
cursorPosition.y += 1;
                   
}
                   
                }
               
else if( event.key.code == sf::Keyboard::Up ) {
                   
setCursorUp();
                   
               
}
               
else if( event.key.code == sf::Keyboard::Down ) {
                   
                   
setCursorDown();
               
}
               
               
cursorPositioning();
               
           
}
           
           
        }
       
       
window->clear( backgroundColor );
       
for( auto & line: lines )
           
 window->draw( * line );
       
       
if( std::fmod( currentTime.asSeconds(), 0.6f ) < 0.3f )
           
 window->draw( cursor );
       
       
window->display();
   
}
}
P-182492
1 « 2 » 3
Poprzednia strona Strona 2 z 3 Następna strona