diff --git a/wayland/docs/uml/diagram-activity-animation.png b/wayland/docs/uml/diagram-activity-animation.png new file mode 100644 index 0000000..7b31149 Binary files /dev/null and b/wayland/docs/uml/diagram-activity-animation.png differ diff --git a/wayland/docs/uml/diagram-activity-animation.puml b/wayland/docs/uml/diagram-activity-animation.puml new file mode 100644 index 0000000..9cc50f9 --- /dev/null +++ b/wayland/docs/uml/diagram-activity-animation.puml @@ -0,0 +1,51 @@ +@startuml +title Цикл анимации фигуры (aux_thread) + +start + +:aux_thread запущен; + +while (окно не закрыто?) is (да) + + :Залочить figure_mutex; + + :figure_animation_step(draw_info); + + partition "figure_animation_step (ASM)" { + :Обработка коллизий; + note right + figure_handle_collision(): + - Расчёт точек фигуры на окружности + - Проверка выхода за границы + - Инверсия velocity при коллизии + - Обновление angular_velocity + end note + + :Обновить позицию; + note right + position += (velocity * speed) / height + end note + + :Обновить угол поворота; + note right + angle += angular_velocity * speed + end note + + :Применить трение к вращению; + note right + angular_velocity *= 0.95 + end note + } + + :Разлочить figure_mutex; + + :usleep(33 ms); + note right: ~30 FPS обновление физики + +endwhile (нет) + +:Завершение потока; + +stop + +@enduml diff --git a/wayland/docs/uml/diagram-activity-render.png b/wayland/docs/uml/diagram-activity-render.png new file mode 100644 index 0000000..a54ea0e Binary files /dev/null and b/wayland/docs/uml/diagram-activity-render.png differ diff --git a/wayland/docs/uml/diagram-activity-render.puml b/wayland/docs/uml/diagram-activity-render.puml new file mode 100644 index 0000000..8c62d6f --- /dev/null +++ b/wayland/docs/uml/diagram-activity-render.puml @@ -0,0 +1,76 @@ +@startuml +title Цикл отрисовки окна (window_thread) + +start + +:window_thread запущен; + +:Создать event queue; +:window_init(); +:Запустить aux_thread для анимации; + +while (окно не закрыто?) is (да) + + :wl_display_dispatch_queue(); + note right: Ожидание событий Wayland + + if (событие произошло?) then (да) + + if (xdg_surface_configure?) then (да) + :xdg_surface_ack_configure(); + if (буфер не создан?) then (да) + :resize_canvas(); + endif + :draw(); + endif + + if (xdg_toplevel_configure?) then (да) + if (размер изменился?) then (да) + :resize_new(w, h); + note right + - Освободить старый буфер + - Создать новый буфер + - Обновить размеры draw_info + end note + endif + endif + + if (xdg_toplevel_close?) then (да) + :Установить need_close = 1; + endif + + if (frame_callback?) then (да) + :Уничтожить старый callback; + :Создать новый callback; + + partition "draw()" { + :Залочить figure_mutex; + + :Очистить фон (черный); + + :figure_draw(); + note right + - Получить текущую фигуру + - Нарисовать границу и заливку + - Цвет зависит от типа фигуры + end note + + :Разлочить figure_mutex; + + :wl_surface_attach(buffer); + :wl_surface_damage_buffer(); + :wl_surface_commit(); + } + endif + + endif + +endwhile (нет) + +:window_destroy(); +:Уничтожить event queue; +:signal_thread_exit(); + +stop + +@enduml diff --git a/wayland/docs/uml/diagram-class.png b/wayland/docs/uml/diagram-class.png new file mode 100644 index 0000000..43e245c Binary files /dev/null and b/wayland/docs/uml/diagram-class.png differ diff --git a/wayland/docs/uml/diagram-class.puml b/wayland/docs/uml/diagram-class.puml new file mode 100644 index 0000000..1146eb2 --- /dev/null +++ b/wayland/docs/uml/diagram-class.puml @@ -0,0 +1,127 @@ +@startuml +title Структура классов проекта Wayland + +class wayland_runtime { + + init_wayland() : int32_t + + run_window() : int32_t + + wait_for_windows() : void + + destroy_wayland() : void + + get_window_by_surface(surf) : wayland_window* + -- + - g_display : wl_display* + - g_slots[MAX_WINDOW_THREADS] : window_thread_slot + - g_thread_lock : pthread_mutex_t + - g_active_threads : atomic_int + - g_shutdown : atomic_bool +} + +class window_thread_slot { + + thread : pthread_t + + aux_thread : pthread_t + + active : int + + queue : wl_event_queue* + + window : wayland_window +} + +class wayland_window { + + id : int + + wl_surface : wl_surface* + + xdg_surface : xdg_surface* + + xdg_toplevel : xdg_toplevel* + + buffer : wl_buffer* + + frame_callback : wl_callback* + + queue : wl_event_queue* + + need_close : int + + draw_info : window_draw_info + -- + + window_init(display, queue) : int + + window_destroy() : void + + window_should_close() : int +} + +class window_draw_info { + + width : uint32_t + + height : uint32_t + + data : void* + + figure : figure_animation_info + + figure_mutex : pthread_mutex_t +} + +class figure_animation_info { + + type : figure_type + + position : vec2 + + velocity : vec2 + + angle : float + + angular_velocity : float + + speed : float + + radius : float +} + +enum figure_type { + FIGURE_CIRCLE = 0 + FIGURE_TRIANGLE = 1 + FIGURE_SQUARE = 2 +} + +class registry { + + registry_global_bind(display) : int + + registry_global_unbind() : void + + registry_get_compositor() : wl_compositor* + + registry_get_shm() : wl_shm* + + registry_get_xdg_wm_base() : xdg_wm_base* + -- + - global_compositor : wl_compositor* + - global_shm : wl_shm* + - global_wm_base : xdg_wm_base* + - global_registry : wl_registry* + - global_thread : pthread_t + - global_thread_running : atomic_int +} + +class input { + + input_register_seat(seat) : void + + input_cleanup() : void + -- + - seat : wl_seat* + - keyboard : wl_keyboard* + - xkb_ctx : xkb_context* + - xkb_keymap : xkb_keymap* + - xkb_state : xkb_state* + - focused_window : wayland_window* +} + +class input_handle { + + keyboard_key_handle(kc, ks, state, window) : void +} + +class figure_animate <> { + + figure_animation_step(draw_info) : void + + place_points_on_circle(...) : void + -- + - figure_handle_collision(draw_info) : void + - check_collision_mask(...) : uint64_t + - sincos_f32_rbp(angle) : (sin, cos) +} + +class figure_draw { + + figure_draw(draw_info, thickness, border_color, fill_color) : void +} + +wayland_runtime "1" *-- "0..128" window_thread_slot +window_thread_slot "1" *-- "1" wayland_window +wayland_window "1" *-- "1" window_draw_info +window_draw_info "1" *-- "1" figure_animation_info +figure_animation_info --> figure_type + +wayland_runtime ..> registry : uses +wayland_runtime ..> input : uses +wayland_window ..> registry : uses +wayland_window ..> figure_draw : uses + +input ..> input_handle : uses +input --> wayland_window : focuses + +window_thread_slot ..> figure_animate : uses (aux_thread) +figure_draw ..> figure_animate : uses + +@enduml diff --git a/wayland/docs/uml/diagram-component.png b/wayland/docs/uml/diagram-component.png new file mode 100644 index 0000000..c97b961 Binary files /dev/null and b/wayland/docs/uml/diagram-component.png differ diff --git a/wayland/docs/uml/diagram-component.puml b/wayland/docs/uml/diagram-component.puml new file mode 100644 index 0000000..2f94691 --- /dev/null +++ b/wayland/docs/uml/diagram-component.puml @@ -0,0 +1,74 @@ +@startuml +title Компоненты проекта Wayland + +package "Wayland Application" { + + [wayland-runtime] as Runtime + [registry] as Registry + [input] as Input + [input-handle] as InputHandle + [window] as Window + + package "Rendering & Animation" { + [figure-draw] as FigureDraw + [figure-animate (ASM)] as FigureAnimate + } + + Runtime --> Registry : использует глобальные объекты + Runtime --> Input : инициализирует + Runtime --> Window : создаёт и управляет + + Input --> InputHandle : делегирует обработку + InputHandle --> Runtime : вызывает run_window() + InputHandle --> Window : изменяет параметры фигуры + + Window --> Registry : получает compositor, shm, wm_base + Window --> FigureDraw : отрисовка фигуры + Window --> FigureAnimate : aux_thread для анимации + + FigureDraw --> FigureAnimate : использует place_points_on_circle +} + +package "System Libraries" { + [wayland-client] as WaylandLib + [xdg-shell-protocol] as XDGShell + [xkbcommon] as XKB +} + +Registry --> WaylandLib +Registry --> XDGShell +Window --> WaylandLib +Window --> XDGShell +Input --> WaylandLib +Input --> XKB + +cloud "Wayland Compositor" as Compositor + +Runtime --> Compositor : wl_display_connect() +Registry --> Compositor : получение глобальных объектов +Window --> Compositor : создание окон и буферов +Input --> Compositor : получение событий клавиатуры + +note right of Runtime + Центральный компонент: + - Управление жизненным циклом + - Многопоточность (окна + анимация) + - Синхронизация через mutex +end note + +note right of FigureAnimate + Реализация на NASM: + - Физика движения + - Обработка коллизий + - Математика (sin/cos) + - SSE инструкции +end note + +note right of Window + Каждое окно в отдельном потоке: + - window_thread: отрисовка + - aux_thread: анимация + - Event queue для изоляции событий +end note + +@enduml diff --git a/wayland/docs/uml/diagram-sequence-init.png b/wayland/docs/uml/diagram-sequence-init.png new file mode 100644 index 0000000..5df8dc8 Binary files /dev/null and b/wayland/docs/uml/diagram-sequence-init.png differ diff --git a/wayland/docs/uml/diagram-sequence-init.puml b/wayland/docs/uml/diagram-sequence-init.puml new file mode 100644 index 0000000..4f5d19f --- /dev/null +++ b/wayland/docs/uml/diagram-sequence-init.puml @@ -0,0 +1,78 @@ +@startuml +title Последовательность инициализации Wayland приложения + +actor Main +participant "wayland-runtime" as Runtime +participant "registry" as Registry +participant "input" as Input +participant "window" as Window + +Main -> Runtime: init_wayland() +activate Runtime + +Runtime -> Runtime: wl_display_connect() +note right: Подключение к Wayland серверу + +Runtime -> Registry: registry_global_bind(display) +activate Registry + +Registry -> Registry: wl_display_get_registry() +Registry -> Registry: wl_registry_add_listener() +Registry -> Registry: wl_display_roundtrip() +note right: Получение глобальных объектов:\n- wl_compositor\n- wl_shm\n- xdg_wm_base\n- wl_seat + +Registry -> Input: input_register_seat(seat) +activate Input +Input -> Input: wl_seat_add_listener() +Input -> Input: wl_seat_get_keyboard() +Input -> Input: xkb_context_new() +note right: Инициализация обработки клавиатуры +deactivate Input + +Registry -> Registry: pthread_create(global_thread) +note right: Запуск потока обработки\nглобальных событий + +deactivate Registry + +Runtime -> Runtime: Инициализация слотов окон +Runtime -> Runtime: atomic_store(g_shutdown, 0) + +deactivate Runtime + +Main -> Runtime: run_window() +activate Runtime + +Runtime -> Runtime: Найти свободный слот +Runtime -> Runtime: pthread_create(window_thread) +note right: Создание потока окна + +Runtime --> Main: slot_index + +== Поток окна == + +Runtime -> Runtime: wl_display_create_queue() +Runtime -> Window: window_init(display, queue) +activate Window + +Window -> Registry: registry_get_compositor() +Window -> Registry: registry_get_shm() +Window -> Registry: registry_get_xdg_wm_base() + +Window -> Window: wl_compositor_create_surface() +Window -> Window: xdg_wm_base_get_xdg_surface() +Window -> Window: xdg_surface_get_toplevel() +Window -> Window: Инициализация listeners +Window -> Window: Инициализация figure_animation_info +note right: Параметры анимации:\n- position, velocity\n- angle, angular_velocity\n- speed, radius + +deactivate Window + +Runtime -> Runtime: pthread_create(aux_thread) +note right: Вспомогательный поток\nдля анимации + +Runtime -> Runtime: wl_display_dispatch_queue() +note right: Цикл обработки событий окна + +deactivate Runtime + +@enduml diff --git a/wayland/docs/uml/diagram-sequence-keyboard.png b/wayland/docs/uml/diagram-sequence-keyboard.png new file mode 100644 index 0000000..f3af73b Binary files /dev/null and b/wayland/docs/uml/diagram-sequence-keyboard.png differ diff --git a/wayland/docs/uml/diagram-sequence-keyboard.puml b/wayland/docs/uml/diagram-sequence-keyboard.puml new file mode 100644 index 0000000..be9b06b --- /dev/null +++ b/wayland/docs/uml/diagram-sequence-keyboard.puml @@ -0,0 +1,61 @@ +@startuml +title Обработка клавиатурного ввода + +actor User +participant "Wayland Server" as Server +participant "input" as Input +participant "input-handle" as Handler +participant "wayland-runtime" as Runtime +participant "window" as Window + +User -> Server: Нажатие клавиши +Server -> Input: keyboard_key(key, state) +activate Input + +Input -> Input: xkb_state_key_get_one_sym() +note right: Преобразование keycode в keysym + +Input -> Handler: keyboard_key_handle(kc, ks, state, window) +activate Handler + +alt Клавиша Enter + Handler -> Runtime: run_window() + note right: Создание нового окна +else Клавиша '1' + Handler -> Window: figure.type = CIRCLE +else Клавиша '2' + Handler -> Window: figure.type = TRIANGLE +else Клавиша '3' + Handler -> Window: figure.type = SQUARE +else Клавиша '-' + Handler -> Handler: pthread_mutex_lock() + Handler -> Window: figure.speed -= 0.5 + Handler -> Handler: Ограничить [1, 30] + Handler -> Handler: pthread_mutex_unlock() +else Клавиша '+' или '=' + Handler -> Handler: pthread_mutex_lock() + Handler -> Window: figure.speed += 0.5 + Handler -> Handler: Ограничить [1, 30] + Handler -> Handler: pthread_mutex_unlock() +else Клавиша Up + Handler -> Handler: pthread_mutex_lock() + Handler -> Window: figure.radius += 2.0 + Handler -> Handler: Ограничить [1, max] + Handler -> Handler: pthread_mutex_unlock() +else Клавиша Down + Handler -> Handler: pthread_mutex_lock() + Handler -> Window: figure.radius -= 2.0 + Handler -> Handler: Ограничить [1, max] + Handler -> Handler: pthread_mutex_unlock() +end + +deactivate Handler +deactivate Input + +note over Window + Изменения параметров фигуры + влияют на следующий frame + анимации и отрисовки +end note + +@enduml diff --git a/wayland/docs/uml/diagram-state-figure.png b/wayland/docs/uml/diagram-state-figure.png new file mode 100644 index 0000000..6f6fc03 Binary files /dev/null and b/wayland/docs/uml/diagram-state-figure.png differ diff --git a/wayland/docs/uml/diagram-state-figure.puml b/wayland/docs/uml/diagram-state-figure.puml new file mode 100644 index 0000000..52d734e --- /dev/null +++ b/wayland/docs/uml/diagram-state-figure.puml @@ -0,0 +1,62 @@ +@startuml +title Диаграмма состояний фигуры + +[*] --> Circle : init (по умолчанию) + +Circle : Красный цвет (0xFFFF0000) +Circle : radius точек = 16 +Triangle : Зелёный цвет (0xFF00FF00) +Triangle : radius точек = 3 +Square : Синий цвет (0xFF0000FF) +Square : radius точек = 4 + +Circle --> Triangle : Клавиша '2' +Circle --> Square : Клавиша '3' + +Triangle --> Circle : Клавиша '1' +Triangle --> Square : Клавиша '3' + +Square --> Circle : Клавиша '1' +Square --> Triangle : Клавиша '2' + +Circle : velocity движет позицию +Circle : angular_velocity вращает +Triangle : velocity движет позицию +Triangle : angular_velocity вращает +Square : velocity движет позицию +Square : angular_velocity вращает + +note right of Circle + Общие свойства для всех состояний: + - position (x, y) + - velocity (vx, vy) + - angle (угол поворота) + - angular_velocity (скорость вращения) + - speed (множитель скорости: 1-30) + - radius (радиус в пикселях) + + Управление: + - '+'/'-': изменение speed + - Up/Down: изменение radius + - Enter: создать новое окно +end note + +state "Коллизия с границей" as Collision { + [*] --> CheckCollision + CheckCollision --> InvertVelocity : точка вышла за границу + InvertVelocity --> UpdateAngularVel : инверсия компоненты velocity + UpdateAngularVel --> CheckCollision : обновление angular_velocity + + CheckCollision : проверка всех точек фигуры + InvertVelocity : vel = -vel (по оси коллизии) + UpdateAngularVel : зависит от направления движения +} + +Circle --> Collision : каждый frame +Triangle --> Collision : каждый frame +Square --> Collision : каждый frame +Collision --> Circle +Collision --> Triangle +Collision --> Square + +@enduml diff --git a/wayland/src/figure-animate.asm b/wayland/src/figure-animate.asm index 3b7bf48..10a15c2 100644 --- a/wayland/src/figure-animate.asm +++ b/wayland/src/figure-animate.asm @@ -18,7 +18,7 @@ ANG_COLLIDE_COEF: dd 0.55 ANG_BOOST_FACTOR: dd 0.02 ANG_MAX: dd 0.04 ANG_SWITCH_FACTOR: dd 0.1 - ANG_MAX_DELTA: dd 0.5 + ANG_MAX_DELTA: dd 0.1 ANG_FRICTION: dd 0.95 section .text @@ -380,6 +380,7 @@ figure_handle_collision: ; Обработка коллизий: инвертировать velocity только если движемся к границе +; Обработка velocity ; Проверка left (bit 0): инвертировать velocity.x только если vel.x < 0 test r14, 0x1 jz .check_right diff --git a/wayland/src/input-handle.c b/wayland/src/input-handle.c index 3109808..2ba60f6 100644 --- a/wayland/src/input-handle.c +++ b/wayland/src/input-handle.c @@ -34,7 +34,7 @@ void keyboard_key_handle(xkb_keycode_t kc, xkb_keysym_t ks, enum keyboard_key_st case '-': /* decrease animation speed (multiplicative delta, clamped) */ pthread_mutex_lock(&window->draw_info.figure_mutex); - window->draw_info.figure.speed -= 0.5f; + window->draw_info.figure.speed -= 1; if (window->draw_info.figure.speed < 1) window->draw_info.figure.speed = 1; printf("keyboard: speed decreased to %.2f\n", window->draw_info.figure.speed); @@ -44,9 +44,9 @@ void keyboard_key_handle(xkb_keycode_t kc, xkb_keysym_t ks, enum keyboard_key_st case '=': /* some layouts may emit '=' for unshifted, handle + via keysym */ /* increase animation speed (multiplicative delta, clamped) */ pthread_mutex_lock(&window->draw_info.figure_mutex); - window->draw_info.figure.speed += 0.5f; - if (window->draw_info.figure.speed > 30.0f) - window->draw_info.figure.speed = 30.0f; + window->draw_info.figure.speed += 1; + if (window->draw_info.figure.speed > 50.0f) + window->draw_info.figure.speed = 50.0f; printf("keyboard: speed increased to %.2f\n", window->draw_info.figure.speed); pthread_mutex_unlock(&window->draw_info.figure_mutex); break;