LINUX.ORG.RU

SDL -> SDL2

 ,


0

3

Перевожу один свой проект на SDL2, раньше использовал SDL. Была такая логика - главное окно делилось на несколько зон, в каждой из которых рисовался свой surface. Приведу код:

  (loop with plot-n = 3 with plot-h = (round (/ height plot-n))
        for i from 0 below plot-n
        for name in (list
                     "Температура охлаждающей жидкости (°С)"
                     "Положение дроссельной заслонки (%)"
                     "Скорость вращения двигателя на холостом ходу (об/мин)")
        for s = (sdl:create-surface width plot-h) 
        do (progn
             (sdl:fill-surface sdl:*white* :surface s)
             (draw-plot name s)
             (sdl:draw-surface-at s
                                  (point :x 0 :y (* i (/ height plot-n)))
                                  :surface sdl:*default-surface*))))

В SDL2 всё по-другому и у меня не получается увязать вместе render и surface, да и, скорее всего, неправильный подход я пытаюсь использовать. Пробовал по-разному, к примеру так -

(let* ((s (sdl2:create-rgb-surface 100 100 1))
       (r (sdl2:create-software-renderer s)))
  (sdl2:set-render-draw-color r 0 0 255 255)
  (sdl2:render-draw-line r 0 0 100 100)
  (sdl2:render-copy render (sdl2:create-texture-from-surface r s)
                    :source-rect (make-rect 0 0 100 100)
                    :dest-rect (make-rect 10 10 110 110)))

Доки почитал, но что-то не разобрался. Спасибо.

РЕШЕНИЕ:

(defun start-plot ()
  (sdl2:make-this-thread-main
   (lambda ()
     (sdl2:with-init (:everything)
       (sdl2:with-window (win :title "prostolog" :w *width* :h *height*)
         (sdl2:with-renderer (render win)
           (sdl2:with-gl-context (gl-context win)
             (init-scene)
             (sdl2:with-event-loop (:method :poll)
               (:keyup
                (:keysym keysym)
                (when
                    (sdl2:scancode= (sdl2:scancode-value keysym) :scancode-escape)
                  (sdl2:push-event :quit)))
               (:idle
                ()
                (let ((foreground-textures '()))
                  
                  (dotimes (i 30)

                    ;; texture
                    (let ((texture
                            (sdl2:create-texture render 373694468 :target 100 50)))
                      ;; clear texture background
                      (sdl2:set-render-target render texture)
                      (sdl2:set-render-draw-color render 200 200 200 255)
                      (sdl2:render-clear render)
                      ;; drawing at texture
                      (sdl2:set-render-draw-color render 0 0 0 255)
                      (sdl2:render-draw-line render 0 0 100 50)
                      (sdl2:render-draw-line render 100 0 0 50)
                      ;; return render 
                      (sdl2:set-render-target render nil)
                      (push texture foreground-textures))

                    ;; anouther texture
                    (let ((texture
                            (sdl2:create-texture render 373694468 :target 200 30)))
                      ;; clear texture background
                      (sdl2:set-render-target render texture)
                      (sdl2:set-render-draw-color render 100 100 100 255)
                      (sdl2:render-clear render)
                      
                      ;; drawing at texture
                      (sdl2:set-render-draw-color render 255 0 0 255)
                      (sdl2:render-draw-line render 0 0 200 30)
                      (sdl2:render-draw-line render 0 30 200 0)
                      
                      ;; return render 
                      (sdl2:set-render-target render nil)
                      (push texture foreground-textures)))

                  ;; draw window background graphics
                  (sdl2:set-render-draw-color render 255 255 255 255)
                  (sdl2:render-clear render)
                  (sdl2:set-render-draw-color render 255 0 0 255)
                  (sdl2:render-draw-line render 0 0 *width* *height*)
                  (sdl2:set-render-draw-color render 0 0 255 50)
                  (sdl2:render-draw-line render *width* 0 0 *height*)
                  
                  ;; draw textures at window surface
                  (loop for ft in foreground-textures
                        for w = (texture-width ft) for h = (texture-height ft)
                        with offset = 0
                        while (< (+ offset h) *height*)
                        do
                           (progn
                             (sdl2:render-copy
                              render ft
                              :dest-rect (sdl2:make-rect
                                          (- (/ *width* 2) (/ w 2))
                                          offset w h))
                             (incf offset h))))

                ;; present all stuff at window surface
                (sdl2:render-present render))
                
               (:quit () t)))))))))

Не хочу разбирать твои птичьи скобки, но во-первых, «не разобрался» не является адекватной диагностикой. Не компилируется, падает, не рисует, рисует поней вместо того что ожидалось, что?

Во-вторых, в SDL2 принято использовать hardware accelerated рендер, так что для всего создаются текстуры (да, CreateTextureFromSurface) и рисуются уже они. Не знаю как это работает с software renderer, работает ли вообще и кому в здравом уме это может понадобиться. Поэтому либо используй нормальный HA renderer (CreateRenderer) и рисуй текстуры, либо используй по старинке software, но тогда по старинке же blit'ть свои поверхности на экранную поверхность.

slovazap ★★★★★ ()
Ответ на: комментарий от pseudo-cat

Всё правильно написано, вообще-то. Или тебе непременно на скобках нужно написать?

anonymous ()
Ответ на: комментарий от anonymous

Скобки вообще не при чем, это просто ЯП, какая разница на чём я написал код? Или лень код посмотреть на чём-то другом к чему привык? Тогда лучше вообще не писать. А это высокомерие так отвечать, когда знаешь ответ можно просто и понятно написать, а не кудахтать про птичьи скобки и про то что лень код читать.

Была такая логика:

  • создание нового surface
  • рисование в нём
  • отрисовка его в определенной позиции

В новой версии сдл во-первых нет функций для рисования в surface, а нужно рисовать в renderer. То есть нужно или вообще отказаться от surface или понять как его привязать для surface. Во-вторых, draw-surface-at, которой, кстати, в SDL вроде как нет, но есть в биндингах, которые я использую, теперь тоже нет. В общем задача на мой взгляд элементарная и код её отражает - создать и изрисовать с помощью draw-функций N отдельных областей, а потом отобразить их на экран.

Если бы я хорошо знал SDL я бы наверное вообще не спрашивал. И наверное вообще никто бы ничего не спрашивал.

pseudo-cat ★★★ ()
Последнее исправление: pseudo-cat (всего исправлений: 1)
Ответ на: комментарий от pseudo-cat

Охладите трахание, там просто стоит углепластик от легаси. В этом всё дело. Исправляйте биднинги или меняйте логику.

понять как его привязать для surface.

sdl2:create-texture-from-surface renderer это ли не оно?

anonymous ()
Ответ на: комментарий от anonymous

Ну и вообще-то sdl2 и sdl не слишком совместимы, кое-что придётся переписать в любом случае.

anonymous ()
Ответ на: комментарий от pseudo-cat

SDL2, что, написан на лишпе? Ты так пишешь про SDL, будто у него имеются официальные биндинги к этому ЯП. Мой тебе совет: делай минимальный рабочий SDL2-пример на C/C++:

$ cat sdl_test.c
#include <SDL2/SDL.h>

int main (int argc, char** argv)
{
    SDL_Window* window = NULL;
    window = SDL_CreateWindow(
        "Some SDL shit",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_SHOWN
    );

    SDL_Renderer* renderer = NULL;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    SDL_SetRenderDrawColor( renderer, 255, 0, 0, 255);

    SDL_RenderClear(renderer);

    SDL_Rect r[7];
    r[0].x =  90; r[1].x = 300; r[2].x = 100; r[3].x = 300; r[4].x = 100; r[5].x = 100; r[6].x = 480;
    r[0].y =  10; r[1].y =  20; r[2].y = 220; r[3].y =  20; r[4].y = 400; r[5].y =  20; r[6].y = 220;
    r[0].w = 460; r[1].w =  60; r[2].w = 440; r[3].w = 240; r[4].w = 240; r[5].w =  60; r[6].w =  60;
    r[0].h = 460; r[1].h = 440; r[2].h =  60; r[3].h =  60; r[4].h =  60; r[5].h = 240; r[6].h = 240;

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderFillRect(renderer, &r[0]);

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    int i = 1; for (; i <= 6; ++i) SDL_RenderFillRect(renderer, &r[i]);

    SDL_RenderPresent(renderer);

    SDL_Delay(5000);

    SDL_DestroyWindow(window);
    SDL_Quit();

    return EXIT_SUCCESS;
}

$ gcc sdl_test.c `sdl2-config --cflags` `sdl2-config --libs`

$ ./a.out

Потом переводи эту лапшу на свой лишп и смотри, будет оно работать или нет. Если не будет — привязки SDL2 к Lisp'у полное говно, переписывай их, чтобы всё работало точно так же, как в C/C++ примерах.

А ещё лучше перепиши своё приложение на НОРМАЛЬНЫЙ язык программирования, который имеет не только богатые UI-библиотеки, но средства построения графиков в них. Так ты себя избавишь от написания костылей, а твоё приложение будет выглядеть максимально нативно.

Ты решаешь проблему неправильно, стараясь из нутрей привязки разобраться в том, как работает SDL2.

EXL ★★★★★ ()
Ответ на: комментарий от pseudo-cat

Скобки вообще не при чем, это просто ЯП, какая разница на чём я написал код?

Если я напишу на брейнфаке и спрошу почему не работает, ты серьёзно будешь разбиратся в коде? Тут то же самое. Здесь обсуждают программирование, а не эзотерику, так что во-первых, будь готов к тому что маргинальщину не будут воспринимать серьёзно, во-вторых, будь готов что тебя просто пошлют искать проблему в кривых биндингах. Так что прежде чем указывать другим писать или не писать, сам десять раз подумай на этим, если пишешь куда-то помимо местаобитания скобочников.

В новой версии сдл во-первых нет функций для рисования в surface, а нужно рисовать в renderer

Ты думаешь в правильном направлении. Да, нужно, поэтому в renderer и рисуй, если ты о линиях и прямоугольниках. Если нужен вывод изображений, то загружаешь в texture и рисуешь через SDL_RendererCopy. Если нужна прямая работа с пикселями, рисуешь на surface (или просто в char[]), затем посылаешь в текстуру через SDL_UpdateTexture, затем опять таки Copy. Что ты имеешь в виду под областями я так и не понял.

slovazap ★★★★★ ()
Ответ на: комментарий от EXL

А ещё лучше перепиши своё приложение на НОРМАЛЬНЫЙ язык программирования

это пиздец товарищи, таких тупых советов я давненько не слышал

pseudo-cat ★★★ ()
Ответ на: комментарий от pseudo-cat

Вот он, культурный уровень лишпера.

anonymous ()
Ответ на: комментарий от anonymous
lisp: варианты перевода
сюсюкать
шепелявить
лепетать
anonymous ()
Ответ на: комментарий от pseudo-cat

да не обращай внимания! я его давно заигнорил)

dave ★★★★★ ()
Ответ на: комментарий от anonymous

sdl2:create-texture-from-surface renderer это ли не оно?

Извини, не заметил твой комментарий. Не совсем оно. Так как логика рисования изменилась, то есть теперь нет функций для рисования в surface,то мне он теперь и не особо нужен. Отсюда и случился весь вопрос - рисовать нужно в render, но он один на всё окно, а мне нужно разделить окно на несколько частей и, чтобы это не было постоянным вычислением offset-координат, я искал способ рисовать в новых surface/texture/что-нибудь-ещё, у которых свои абсолютные внутренние координаты и затем уже биндить это к глобальному окну с нужным смещением.

pseudo-cat ★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.