CI-Build 2022-08-01

This commit is contained in:
arch1t3cht 2022-08-01 23:24:30 +02:00
commit 4e8c02d38f
28 changed files with 1300 additions and 11 deletions

541
CMakeLists.txt Normal file
View file

@ -0,0 +1,541 @@
cmake_minimum_required(VERSION 3.14)
cmake_policy(SET CMP0074 NEW)
project(Aegisub)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include_directories("build")
include_directories("libaegisub/include")
include_directories("vendor/luajit/include")
add_library(libaegisub STATIC
libaegisub/common/parser.cpp
libaegisub/ass/dialogue_parser.cpp
libaegisub/ass/time.cpp
libaegisub/ass/uuencode.cpp
libaegisub/audio/provider.cpp
libaegisub/audio/provider_convert.cpp
libaegisub/audio/provider_dummy.cpp
libaegisub/audio/provider_hd.cpp
libaegisub/audio/provider_lock.cpp
libaegisub/audio/provider_pcm.cpp
libaegisub/audio/provider_ram.cpp
libaegisub/common/cajun/elements.cpp
libaegisub/common/cajun/reader.cpp
libaegisub/common/cajun/writer.cpp
libaegisub/lua/modules/lfs.cpp
libaegisub/lua/modules/re.cpp
libaegisub/lua/modules/unicode.cpp
libaegisub/lua/modules/lpeg.c
libaegisub/lua/modules.cpp
libaegisub/lua/script_reader.cpp
libaegisub/lua/utils.cpp
libaegisub/common/calltip_provider.cpp
libaegisub/common/character_count.cpp
libaegisub/common/charset.cpp
libaegisub/common/charset_6937.cpp
libaegisub/common/charset_conv.cpp
libaegisub/common/color.cpp
libaegisub/common/file_mapping.cpp
libaegisub/common/format.cpp
libaegisub/common/fs.cpp
libaegisub/common/hotkey.cpp
libaegisub/common/io.cpp
libaegisub/common/json.cpp
libaegisub/common/kana_table.cpp
libaegisub/common/karaoke_matcher.cpp
libaegisub/common/keyframe.cpp
libaegisub/common/line_iterator.cpp
libaegisub/common/log.cpp
libaegisub/common/mru.cpp
libaegisub/common/option.cpp
libaegisub/common/option_value.cpp
libaegisub/common/path.cpp
libaegisub/common/thesaurus.cpp
libaegisub/common/util.cpp
libaegisub/common/vfr.cpp
libaegisub/common/ycbcr_conv.cpp
libaegisub/common/dispatch.cpp
)
if (UNIX)
target_sources(libaegisub PRIVATE
libaegisub/unix/access.cpp
libaegisub/unix/fs.cpp
libaegisub/unix/log.cpp
libaegisub/unix/path.cpp
libaegisub/unix/util.cpp
)
elseif(WIN32)
target_sources(libaegisub PRIVATE
libaegisub/windows/access.cpp
libaegisub/windows/charset_conv_win.cpp
libaegisub/windows/fs.cpp
libaegisub/windows/lagi_pre.cpp
libaegisub/windows/log_win.cpp
libaegisub/windows/path_win.cpp
libaegisub/windows/util_win.cpp
)
endif(UNIX)
SET_TARGET_PROPERTIES(libaegisub PROPERTIES PREFIX "")
add_library(luabins STATIC
vendor/luabins/src/fwrite.c
vendor/luabins/src/load.c
vendor/luabins/src/luabins.c
vendor/luabins/src/luainternals.c
vendor/luabins/src/save.c
vendor/luabins/src/savebuffer.c
vendor/luabins/src/write.c
)
add_executable(luajit-minilua vendor/luajit/src/host/minilua.c)
if (NOT MSVC)
target_link_libraries(luajit-minilua m)
endif(NOT MSVC)
add_custom_command(TARGET luajit-minilua POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/vendor/luajit/src/gen
COMMAND luajit-minilua ../dynasm/dynasm.lua -D P64 -D JIT -D FFI -D FPU -D HFABI -D VER= -o gen/buildvm_arch.h vm_x86.dasc
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/vendor/luajit/src
)
add_custom_command(TARGET luajit-minilua POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/libresrc/default_config_win.json ${PROJECT_SOURCE_DIR}/src/libresrc/default_config_platform.json
COMMAND luajit-minilua ../../tools/respack.lua manifest.respack default_config.cpp default_config.h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/libresrc
BYPRODUCTS ${PROJECT_SOURCE_DIR}/src/libresrc/default_config.cpp ${PROJECT_SOURCE_DIR}/src/libresrc/default_config.h
)
add_custom_command(TARGET luajit-minilua POST_BUILD
COMMAND luajit-minilua ../../tools/respack.lua manifest.respack ../libresrc/bitmap.cpp ../libresrc/bitmap.h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/bitmaps
BYPRODUCTS ${PROJECT_SOURCE_DIR}/src/libresrc/bitmap.cpp ${PROJECT_SOURCE_DIR}/src/libresrc/bitmap.h
)
add_executable(luajit-buildvm
vendor/luajit/src/host/buildvm.c
vendor/luajit/src/host/buildvm_asm.c
vendor/luajit/src/host/buildvm_peobj.c
vendor/luajit/src/host/buildvm_lib.c
vendor/luajit/src/host/buildvm_fold.c
)
target_include_directories(luajit-buildvm PRIVATE vendor/luajit/src vendor/luajit/src/gen)
add_dependencies(luajit-buildvm luajit-minilua)
if(UNIX)
add_custom_command(TARGET luajit-buildvm POST_BUILD
COMMAND luajit-buildvm -m elfasm -o lj_vm.s
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/vendor/luajit/src
BYPRODUCTS ${PROJECT_SOURCE_DIR}/vendor/luajit/src/lj_vm.s
)
set_property(SOURCE vendor/luajit/src/lj_vm.s PROPERTY LANGUAGE C)
elseif(MSVC)
add_custom_command(TARGET luajit-buildvm POST_BUILD
COMMAND luajit-buildvm -m peobj -o lj_vm.obj
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/vendor/luajit/src
BYPRODUCTS ${PROJECT_SOURCE_DIR}/vendor/luajit/src/lj_vm.obj
)
endif(UNIX)
add_custom_command(TARGET luajit-buildvm POST_BUILD
COMMAND luajit-buildvm -m ffdef -o gen/lj_ffdef.h lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c
COMMAND luajit-buildvm -m bcdef -o gen/lj_bcdef.h lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c
COMMAND luajit-buildvm -m folddef -o gen/lj_folddef.h lj_opt_fold.c
COMMAND luajit-buildvm -m recdef -o gen/lj_recdef.h lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c
COMMAND luajit-buildvm -m libdef -o gen/lj_libdef.h lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c
COMMAND luajit-buildvm -m vmdef -o jit/vmdef.lua lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/vendor/luajit/src
)
add_library(luajit STATIC
vendor/luajit/src/lj_gc.c
vendor/luajit/src/lj_err.c
vendor/luajit/src/lj_char.c
vendor/luajit/src/lj_bc.c
vendor/luajit/src/lj_obj.c
vendor/luajit/src/lj_str.c
vendor/luajit/src/lj_tab.c
vendor/luajit/src/lj_func.c
vendor/luajit/src/lj_udata.c
vendor/luajit/src/lj_meta.c
vendor/luajit/src/lj_debug.c
vendor/luajit/src/lj_state.c
vendor/luajit/src/lj_dispatch.c
vendor/luajit/src/lj_vmevent.c
vendor/luajit/src/lj_vmmath.c
vendor/luajit/src/lj_strscan.c
vendor/luajit/src/lj_api.c
vendor/luajit/src/lj_lex.c
vendor/luajit/src/lj_parse.c
vendor/luajit/src/lj_bcread.c
vendor/luajit/src/lj_bcwrite.c
vendor/luajit/src/lj_load.c
vendor/luajit/src/lj_ir.c
vendor/luajit/src/lj_opt_mem.c
vendor/luajit/src/lj_opt_fold.c
vendor/luajit/src/lj_opt_narrow.c
vendor/luajit/src/lj_opt_dce.c
vendor/luajit/src/lj_opt_loop.c
vendor/luajit/src/lj_opt_split.c
vendor/luajit/src/lj_opt_sink.c
vendor/luajit/src/lj_mcode.c
vendor/luajit/src/lj_snap.c
vendor/luajit/src/lj_record.c
vendor/luajit/src/lj_crecord.c
vendor/luajit/src/lj_ffrecord.c
vendor/luajit/src/lj_asm.c
vendor/luajit/src/lj_trace.c
vendor/luajit/src/lj_gdbjit.c
vendor/luajit/src/lj_ctype.c
vendor/luajit/src/lj_cdata.c
vendor/luajit/src/lj_cconv.c
vendor/luajit/src/lj_ccall.c
vendor/luajit/src/lj_ccallback.c
vendor/luajit/src/lj_carith.c
vendor/luajit/src/lj_clib.c
vendor/luajit/src/lj_cparse.c
vendor/luajit/src/lj_lib.c
vendor/luajit/src/lj_alloc.c
vendor/luajit/src/lib_aux.c
vendor/luajit/src/lib_base.c
vendor/luajit/src/lib_math.c
vendor/luajit/src/lib_bit.c
vendor/luajit/src/lib_string.c
vendor/luajit/src/lib_table.c
vendor/luajit/src/lib_io.c
vendor/luajit/src/lib_os.c
vendor/luajit/src/lib_package.c
vendor/luajit/src/lib_debug.c
vendor/luajit/src/lib_jit.c
vendor/luajit/src/lib_ffi.c
vendor/luajit/src/lib_init.c
)
if(MSVC)
target_sources(luajit PRIVATE vendor/luajit/src/lj_vm.obj)
else(MSVC)
target_sources(luajit PRIVATE vendor/luajit/src/lj_vm.s)
set_property(SOURCE vendor/luajit/src/lj_vm.s PROPERTY LANGUAGE C)
target_link_libraries(luajit dl)
endif(MSVC)
target_include_directories(luajit PRIVATE vendor/luajit/src/gen)
add_dependencies(luajit luajit-buildvm)
target_compile_definitions(luajit PRIVATE LUAJIT_ENABLE_LUA52COMPAT)
add_library(resrc STATIC
src/libresrc/bitmap.cpp
src/libresrc/default_config.cpp
src/libresrc/libresrc.cpp
)
add_dependencies(resrc luajit-minilua)
add_library(csri STATIC
vendor/csri/lib/list.c
vendor/csri/lib/wrap.c
vendor/csri/subhelp/logging.c
)
target_include_directories(csri PRIVATE "vendor/csri/include")
IF (WIN32)
target_include_directories(csri PRIVATE "vendor/csri/lib/win32")
target_sources(csri PRIVATE vendor/csri/lib/win32/enumerate.c)
ELSE()
target_include_directories(csri PRIVATE "vendor/csri/lib/posix")
target_sources(csri PRIVATE vendor/csri/lib/posix/enumerate.c)
ENDIF()
add_executable(Aegisub WIN32
src/command/app.cpp
src/command/audio.cpp
src/command/automation.cpp
src/command/command.cpp
src/command/edit.cpp
src/command/grid.cpp
src/command/help.cpp
src/command/keyframe.cpp
src/command/recent.cpp
src/command/subtitle.cpp
src/command/time.cpp
src/command/timecode.cpp
src/command/tool.cpp
src/command/video.cpp
src/command/vis_tool.cpp
src/dialog_about.cpp
src/dialog_align.cpp
src/dialog_attachments.cpp
src/dialog_automation.cpp
src/dialog_autosave.cpp
src/dialog_colorpicker.cpp
src/dialog_detached_video.cpp
src/dialog_dummy_video.cpp
src/dialog_export.cpp
src/dialog_export_ebu3264.cpp
src/dialog_fonts_collector.cpp
src/dialog_jumpto.cpp
src/dialog_kara_timing_copy.cpp
src/dialog_log.cpp
src/dialog_paste_over.cpp
src/dialog_progress.cpp
src/dialog_properties.cpp
src/dialog_resample.cpp
src/dialog_search_replace.cpp
src/dialog_selected_choices.cpp
src/dialog_selection.cpp
src/dialog_shift_times.cpp
src/dialog_spellchecker.cpp
src/dialog_style_editor.cpp
src/dialog_style_manager.cpp
src/dialog_styling_assistant.cpp
src/dialog_text_import.cpp
src/dialog_timing_processor.cpp
src/dialog_translation.cpp
src/dialog_version_check.cpp
src/dialog_video_details.cpp
src/dialog_video_properties.cpp
src/subtitle_format.cpp
src/subtitle_format_ass.cpp
src/subtitle_format_ebu3264.cpp
src/subtitle_format_encore.cpp
src/subtitle_format_microdvd.cpp
src/subtitle_format_mkv.cpp
src/subtitle_format_srt.cpp
src/subtitle_format_ssa.cpp
src/subtitle_format_transtation.cpp
src/subtitle_format_ttxt.cpp
src/subtitle_format_txt.cpp
src/visual_tool.cpp
src/visual_tool_clip.cpp
src/visual_tool_cross.cpp
src/visual_tool_drag.cpp
src/visual_tool_rotatexy.cpp
src/visual_tool_rotatez.cpp
src/visual_tool_scale.cpp
src/visual_tool_vector_clip.cpp
src/MatroskaParser.c
src/aegisublocale.cpp
src/ass_attachment.cpp
src/ass_dialogue.cpp
src/ass_entry.cpp
src/ass_export_filter.cpp
src/ass_exporter.cpp
src/ass_file.cpp
src/ass_karaoke.cpp
src/ass_override.cpp
src/ass_parser.cpp
src/ass_style.cpp
src/ass_style_storage.cpp
src/async_video_provider.cpp
src/audio_box.cpp
src/audio_colorscheme.cpp
src/audio_controller.cpp
src/audio_display.cpp
src/audio_karaoke.cpp
src/audio_marker.cpp
src/audio_player.cpp
src/audio_provider_factory.cpp
src/audio_renderer.cpp
src/audio_renderer_spectrum.cpp
src/audio_renderer_waveform.cpp
src/audio_timing_dialogue.cpp
src/audio_timing_karaoke.cpp
src/auto4_base.cpp
src/auto4_lua.cpp
src/auto4_lua_assfile.cpp
src/auto4_lua_dialog.cpp
src/auto4_lua_progresssink.cpp
src/base_grid.cpp
src/charset_detect.cpp
src/colorspace.cpp
src/colour_button.cpp
src/compat.cpp
src/context.cpp
src/export_fixstyle.cpp
src/export_framerate.cpp
src/fft.cpp
src/font_file_lister.cpp
src/frame_main.cpp
src/gl_text.cpp
src/gl_wrap.cpp
src/grid_column.cpp
src/help_button.cpp
src/hotkey.cpp
src/hotkey_data_view_model.cpp
src/image_position_picker.cpp
src/initial_line_state.cpp
src/main.cpp
src/menu.cpp
src/mkv_wrap.cpp
src/pen.cpp
src/persist_location.cpp
src/preferences.cpp
src/preferences_base.cpp
src/project.cpp
src/resolution_resampler.cpp
src/search_replace_engine.cpp
src/selection_controller.cpp
src/spellchecker.cpp
src/spline.cpp
src/spline_curve.cpp
src/string_codec.cpp
src/subs_controller.cpp
src/subs_edit_box.cpp
src/subs_edit_ctrl.cpp
src/subs_preview.cpp
src/subtitles_provider.cpp
src/subtitles_provider_libass.cpp
src/text_file_reader.cpp
src/text_file_writer.cpp
src/text_selection_controller.cpp
src/thesaurus.cpp
src/timeedit_ctrl.cpp
src/toggle_bitmap.cpp
src/toolbar.cpp
src/tooltip_manager.cpp
src/utils.cpp
src/validators.cpp
src/vector2d.cpp
src/version.cpp
src/video_box.cpp
src/video_controller.cpp
src/video_display.cpp
src/video_frame.cpp
src/video_out_gl.cpp
src/video_provider_cache.cpp
src/video_provider_dummy.cpp
src/video_provider_manager.cpp
src/video_provider_yuv4mpeg.cpp
src/video_slider.cpp
src/visual_feature.cpp
)
target_link_libraries(Aegisub ${CMAKE_DL_LIBS} libaegisub luabins luajit resrc csri)
if (MSVC)
set_target_properties(libaegisub PROPERTIES COMPILE_FLAGS "/Yu${PROJECT_SOURCE_DIR}/libaegisub/lagi_pre.h" COMPILE_FLAGS "/FI${PROJECT_SOURCE_DIR}/libaegisub/lagi_pre.h")
else(MSVC)
target_compile_options(libaegisub PRIVATE -include "${PROJECT_SOURCE_DIR}/libaegisub/lagi_pre.h")
endif(MSVC)
set_property(
SOURCE libaegisub/unix/path.cpp
PROPERTY COMPILE_DEFINITIONS
P_DATA="${CMAKE_INSTALL_PREFIX}/share/aegisub/"
)
if (MSVC)
add_definitions("-DNOMINMAX -MP -DINITGUID")
set_target_properties(Aegisub PROPERTIES COMPILE_FLAGS "/Yu${PROJECT_SOURCE_DIR}/src/agi_pre.h" COMPILE_FLAGS "/FI${PROJECT_SOURCE_DIR}/src/agi_pre.h")
target_link_libraries (Aegisub Usp10)
#target_sources(Aegisub PRIVATE src/res/res.rc src/res/strings.rc src/crash_writer_minidump.cpp)
target_sources(Aegisub PRIVATE src/res/res.rc src/res/strings.rc src/crash_writer.cpp src/dpi_aware.manifest)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Aegisub)
else(MSVC)
target_sources(Aegisub PRIVATE src/crash_writer.cpp)
target_compile_options(Aegisub PRIVATE -include "${PROJECT_SOURCE_DIR}/src/agi_pre.h")
endif(MSVC)
if (WIN32)
target_sources(Aegisub PRIVATE src/font_file_lister_gdi.cpp)
else (WIN32)
find_package(Fontconfig REQUIRED)
target_link_libraries (Aegisub ${Fontconfig_LIBRARIES})
target_sources(Aegisub PRIVATE src/font_file_lister_fontconfig.cpp)
set_property(SOURCE src/font_file_lister_fontconfig.cpp PROPERTY INCLUDE_DIRECTORIES "${Fontconfig_INCLUDE_DIRS}")
endif (WIN32)
find_package(ass REQUIRED)
include_directories(${ass_INCLUDE_DIRS})
target_link_libraries (Aegisub ${ass_LIBRARIES})
find_package(Boost REQUIRED chrono filesystem locale regex system thread)
include_directories(${Boost_INCLUDE_DIRS})
target_link_directories(Aegisub PRIVATE ${Boost_LIBRARY_DIRS})
target_link_libraries(Aegisub ${Boost_LIBRARIES})
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
target_link_libraries (Aegisub ${OPENGL_LIBRARIES})
find_package(Hunspell REQUIRED)
include_directories(${HUNSPELL_INCLUDE_DIR})
target_link_libraries (Aegisub ${HUNSPELL_LIBRARIES})
add_definitions("-DWITH_HUNSPELL")
target_sources(Aegisub PRIVATE src/spellchecker_hunspell.cpp)
find_package(Iconv REQUIRED)
include_directories(${Iconv_INCLUDE_DIRS})
target_link_libraries (Aegisub ${Iconv_LIBRARIES})
add_definitions("-DHAVE_ICONV")
if (NOT Iconv_IS_BUILT_IN)
set_property(
SOURCE libaegisub/common/charset_conv.cpp
PROPERTY COMPILE_DEFINITIONS AGI_ICONV_CONST
)
endif (NOT Iconv_IS_BUILT_IN)
find_package(ICU REQUIRED uc dt in)
include_directories(${ICU_INCLUDE_DIRS})
target_link_libraries (Aegisub ${ICU_LIBRARIES})
find_package(wxWidgets REQUIRED adv base core gl stc xml)
include(${wxWidgets_USE_FILE})
target_link_libraries(Aegisub ${wxWidgets_LIBRARIES})
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIRS})
target_link_libraries (Aegisub ${ZLIB_LIBRARIES})
find_package(ALSA)
if (ALSA_FOUND)
include_directories(${ALSA_INCLUDE_DIRS})
target_link_libraries (Aegisub ${ALSA_LIBRARIES})
add_definitions("-DWITH_ALSA")
target_sources(Aegisub PRIVATE src/audio_player_alsa.cpp)
endif(ALSA_FOUND)
# target_compile_definitions(Aegisub PRIVATE "WITH_AVISYNTH")
# target_sources(Aegisub PRIVATE src/audio_provider_avs.cpp src/avisynth_wrap.cpp src/video_provider_avs.cpp)
target_compile_definitions(Aegisub PRIVATE "WITH_CSRI")
target_sources(Aegisub PRIVATE src/subtitles_provider_csri.cpp)
set_property(SOURCE src/subtitles_provider_csri.cpp PROPERTY INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/vendor/csri/include")
if(MSVC)
target_link_libraries (Aegisub dsound)
add_definitions("-DWITH_DIRECTSOUND")
target_sources(Aegisub PRIVATE src/audio_player_dsound.cpp src/audio_player_dsound2.cpp)
endif(MSVC)
find_package(FFMS2)
if (FFMS2_FOUND)
include_directories(${FFMS2_INCLUDE_DIRS})
target_link_libraries (Aegisub ${FFMS2_LIBRARIES})
add_definitions("-DWITH_FFMS2")
target_sources(Aegisub PRIVATE src/audio_provider_ffmpegsource.cpp src/ffmpegsource_common.cpp src/video_provider_ffmpegsource.cpp)
endif(FFMS2_FOUND)
find_package(FFTW)
if (FFTW_FOUND)
include_directories(${FFTW_INCLUDES})
target_link_libraries (Aegisub ${FFTW_LIBRARIES})
add_definitions("-DWITH_FFTW3")
endif(FFTW_FOUND)
#ifdef WITH_LIBPULSE
#add_definitions("-DWITH_LIBPULSE")
#target_sources(Aegisub PRIVATE src/audio_player_pulse.cpp)
find_package(OpenAL)
if (OPENAL_FOUND)
include_directories(${OPENAL_INCLUDE_DIR})
target_link_libraries (Aegisub ${OPENAL_LIBRARY})
add_definitions("-DWITH_OPENAL")
target_sources(Aegisub PRIVATE src/audio_player_openal.cpp)
endif(OPENAL_FOUND)
#ifdef WITH_OSS
#ifdef WITH_PORTAUDIO
#ifdef WITH_STARTUPLOG
find_package(uchardet)
if (uchardet_FOUND)
include_directories(${uchardet_INCLUDE_DIRS})
target_link_libraries (Aegisub ${uchardet_LIBRARIES})
add_definitions("-DWITH_UCHARDET")
endif(uchardet_FOUND)
#ifdef WITH_UPDATE_CHECKER

View file

@ -20,13 +20,15 @@ The `cibuilds` branch makes some CI builds of snapshots of `feature` at relevant
### Branch/Feature list
- [`folding`](https://github.com/arch1t3cht/Aegisub/tree/folding): Add the ability to visually group and collapse lines in the subtitle grid
- [`lua_api`](https://github.com/arch1t3cht/Aegisub/tree/lua_api): Add new functions to the Lua automation API, like controlling the selection or cursor in the text edit box
- [`vector_clip_actions`](https://github.com/arch1t3cht/Aegisub/tree/vector_clip_actions): Make the different modes of the vector clip tool (lines, bezier curves, adding points, etc) bindable to hotkeys
- [`color_picker_fix2`](https://github.com/arch1t3cht/Aegisub/tree/color_picker_fix2): Add an option (under "Interface") to restrict the color picker to the window, which fixes the color picker on Linux in a lot of cases.
- [`avisynth`](https://github.com/arch1t3cht/Aegisub/tree/avisynth): Reenable Avisynth support on Windows (Still occasionally crashes)
- [`bugfixes`](https://github.com/arch1t3cht/Aegisub/tree/bugfixes): Various fixes, mostly relevant for compilation
- [`misc_dc`](https://github.com/arch1t3cht/Aegisub/tree/misc_dc): Miscellaneous changes taken from AegisubDC
- [`video_panning_feature`](https://github.com/arch1t3cht/Aegisub/tree/video_panning_feature): Merge [moex3's video zoom and panning](https://github.com/TypesettingTools/Aegisub/pull/150), with an OSX fix and an option to toggle the behavior of Ctrl+Zoom
- [`video_panning_feature`](https://github.com/arch1t3cht/Aegisub/tree/video_panning_feature): Merge [moex3's video zoom and panning](https://github.com/TypesettingTools/Aegisub/pull/150), with an OSX fix and more options to control zoom behavior
- [`spectrum-frequency-mapping`](https://github.com/arch1t3cht/Aegisub/tree/spectrum-frequency-mapping): Merge EleonoreMizo's [spectrum display improvements](https://github.com/TypesettingTools/Aegisub/pull/94), and also make Shift+Scroll vertically zoom the audio display
- [`wangqr_time_video`](https://github.com/arch1t3cht/Aegisub/tree/wangqr_time_video): Merge wangqr's feature adding a tool for timing subtitles to changes in the video
### Troubleshooting
#### Building fails with a "CMake sandbox violation"
@ -43,6 +45,9 @@ The changes to `default_config.json` or similar files weren't detected by meson
#### The video is desynced / Frames don't appear at the right time
This is probably due to the ffms2 seeking bug ([#394](https://github.com/FFMS/ffms2/issues/394)). On Windows, this shouldn't happen anymore. On Linux, you need to install the latest git version of ffms2 - for example the [`ffms2-git`](https://aur.archlinux.org/packages/ffms2-git) AUR package on Arch linux, or just compile it yourself.
#### On Windows: Aegisub crashes whenever I open a video
If you're compiling yourself, try adding `--force-fallback-for=zlib` to the meson options.
# Aegisub

View file

@ -0,0 +1,57 @@
Automation 4 Gui Functions
This document describes the available Automation 4 functions for
controlling the editor's graphical interface. These all reside in the
table aegisub.gui .
---
Getting and setting the selection and cursor in the text edit box
This set of functions controls the selection in the text edit box.
All indices are counted starting from 1, following Lua conventions.
The setter functions are applied after all subtitle changes have been
applied. Only the latest update is applied.
The getter functions return the state after the latest update by
the setter functions, or the original state if there were none.
function aegisub.gui.get_cursor()
Returns: 1 number
1. The position of the cursor in the text edit field.
---
function aegisub.get_selection()
Returns: 2 values, all numbers.
1. Starting position of the selection.
2. Ending position of the selection, always larger or equal
than the stating position.
---
function aegisub.gui.set_cursor(position)
@position (number)
The new position of the cursor.
Returns: 0 values
---
function aegisub.gui.set_selection(start, end)
@start (number)
The new start of the selection.
@end (number)
The new end of the selection, i.e. where the cursor will be.
Can be smaller than the start, in which case the cursor will
be on the left side of the selection.
Returns: 0 values
---

View file

@ -51,6 +51,7 @@
#include "selection_controller.h"
#include "subs_controller.h"
#include "video_controller.h"
#include "text_selection_controller.h"
#include "utils.h"
#include <libaegisub/dispatch.h>
@ -285,6 +286,39 @@ namespace {
return 0;
}
int lua_get_text_cursor(lua_State *L)
{
push_value(L, get_context(L)->textSelectionController->GetStagedInsertionPoint() + 1);
return 1;
}
int lua_set_text_cursor(lua_State *L)
{
int point = lua_tointeger(L, -1) - 1;
lua_pop(L, 1);
get_context(L)->textSelectionController->StageSetInsertionPoint(point);
return 0;
}
int lua_get_text_selection(lua_State *L)
{
const agi::Context *c = get_context(L);
int start = c->textSelectionController->GetStagedSelectionStart() + 1;
int end = c->textSelectionController->GetStagedSelectionEnd() + 1;
push_value(L, start <= end ? start : end);
push_value(L, start <= end ? end : start);
return 2;
}
int lua_set_text_selection(lua_State *L)
{
int start = lua_tointeger(L, -2) - 1;
int end = lua_tointeger(L, -1) - 1;
lua_pop(L, 2);
get_context(L)->textSelectionController->StageSetSelection(start, end);
return 0;
}
int project_properties(lua_State *L)
{
const agi::Context *c = get_context(L);
@ -489,6 +523,12 @@ namespace {
set_field<project_properties>(L, "project_properties");
set_field<lua_get_audio_selection>(L, "get_audio_selection");
set_field<lua_set_status_text>(L, "set_status_text");
lua_createtable(L, 0, 4);
set_field<lua_get_text_cursor>(L, "get_cursor");
set_field<lua_set_text_cursor>(L, "set_cursor");
set_field<lua_get_text_selection>(L, "get_selection");
set_field<lua_set_text_selection>(L, "set_selection");
lua_setfield(L, -2, "gui");
// store aegisub table to globals
lua_settable(L, LUA_GLOBALSINDEX);
@ -786,6 +826,7 @@ namespace {
void LuaCommand::operator()(agi::Context *c)
{
c->textSelectionController->DropStagedChanges();
LuaStackcheck stackcheck(L);
set_context(L, c);
stackcheck.check_stack(0);
@ -883,6 +924,7 @@ namespace {
new_active = *new_sel.begin();
c->selectionController->SetSelectionAndActive(std::move(new_sel), new_active);
}
c->textSelectionController->CommitStagedChanges();
stackcheck.check_stack(0);
}

View file

@ -102,13 +102,19 @@ namespace {
}
template<typename T>
void get_userdata_field(lua_State *L, const char *name, const char *line_class, T *target)
bool get_userdata_field(lua_State *L, const char *name, const char *line_class, T *target, bool required)
{
lua_getfield(L, -1, name);
if (!lua_isuserdata(L, -1))
if (!lua_isuserdata(L, -1)) {
if (!required) {
lua_pop(L, 1);
return false;
}
throw bad_field("userdata", name, line_class);
}
*target = *static_cast<T *>(lua_touserdata(L, -1));
lua_pop(L, 1);
return true;
}
using namespace Automation4;
@ -316,7 +322,9 @@ namespace Automation4 {
dia->Margin[2] = get_int_field(L, "margin_t", "dialogue");
dia->Effect = get_string_field(L, "effect", "dialogue");
dia->Text = get_string_field(L, "text", "dialogue");
get_userdata_field(L, "_foldinfo", "dialogue", &dia->Fold);
if (!get_userdata_field(L, "_foldinfo", "dialogue", &dia->Fold, false)) {
dia->Fold = FoldInfo();
}
std::vector<uint32_t> new_ids;

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

View file

@ -51,6 +51,11 @@ button/bugtracker_button_24.png
button/bugtracker_button_32.png
button/bugtracker_button_48.png
button/bugtracker_button_64.png
button/button_align_16.png
button/button_align_24.png
button/button_align_32.png
button/button_align_48.png
button/button_align_64.png
button/button_audio_commit_16.png
button/button_audio_commit_24.png
button/button_audio_commit_32.png

View file

@ -43,6 +43,12 @@ public:
/// Get the currently selected color
agi::Color GetColor() { return colour; }
void SetColor(agi::Color color)
{
colour = color;
UpdateBitmap();
}
};
struct ColorValidator final : public wxValidator {

View file

@ -235,6 +235,18 @@ struct time_snap_scene final : public validate_video_loaded {
}
};
struct time_align_subtitle_to_point final : public validate_video_loaded {
CMD_NAME("time/align")
CMD_ICON(button_align)
STR_MENU("Align subtitle to video")
STR_DISP("Align subtitle to video")
STR_HELP("Align subtitle to video by key points")
void operator()(agi::Context* c) override {
c->videoController->Stop();
ShowAlignToVideoDialog(c);
}
};
struct time_add_lead_both final : public Command {
CMD_NAME("time/lead/both")
STR_MENU("Add lead in and out")
@ -393,6 +405,7 @@ namespace cmd {
reg(agi::make_unique<time_snap_end_video>());
reg(agi::make_unique<time_snap_scene>());
reg(agi::make_unique<time_snap_start_video>());
reg(agi::make_unique<time_align_subtitle_to_point>());
reg(agi::make_unique<time_start_decrease>());
reg(agi::make_unique<time_start_increase>());
}

375
src/dialog_align.cpp Normal file
View file

@ -0,0 +1,375 @@
// Copyright (c) 2019, Charlie Jiang
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Aegisub Project http://www.aegisub.org/
#include "ass_dialogue.h"
#include "ass_file.h"
#include "compat.h"
#include "dialog_manager.h"
#include "format.h"
#include "include/aegisub/context.h"
#include "video_frame.h"
#include "libresrc/libresrc.h"
#include "options.h"
#include "project.h"
#include "selection_controller.h"
#include "video_controller.h"
#include "async_video_provider.h"
#include "colour_button.h"
#include "image_position_picker.h"
#include <cmath>
#include <libaegisub/ass/time.h>
#include <libaegisub/vfr.h>
#include <wx/dialog.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
#if BOOST_VERSION >= 106900
#include <boost/gil.hpp>
#else
#include <boost/gil/gil_all.hpp>
#endif
namespace {
class DialogAlignToVideo final : public wxDialog {
agi::Context* context;
AsyncVideoProvider* provider;
wxImage preview_image;
VideoFrame current_frame;
int current_n_frame;
ImagePositionPicker* preview_frame;
ColourButton* selected_color;
wxTextCtrl* selected_x;
wxTextCtrl* selected_y;
wxTextCtrl* selected_tolerance;
void update_from_textbox();
void update_from_textbox(wxCommandEvent&);
bool check_exists(int pos, int x, int y, int* lrud, double* orig, unsigned char tolerance);
void process(wxEvent&);
public:
DialogAlignToVideo(agi::Context* context);
~DialogAlignToVideo();
};
DialogAlignToVideo::DialogAlignToVideo(agi::Context* context)
: wxDialog(context->parent, -1, _("Align subtitle to video by key point"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxRESIZE_BORDER)
, context(context), provider(context->project->VideoProvider())
{
auto add_with_label = [&](wxSizer * sizer, wxString const& label, wxWindow * ctrl) {
sizer->Add(new wxStaticText(this, -1, label), 0, wxLEFT | wxRIGHT | wxCENTER, 3);
sizer->Add(ctrl, 1, wxLEFT);
};
auto tolerance = OPT_GET("Tool/Align to Video/Tolerance")->GetInt();
auto maximized = OPT_GET("Tool/Align to Video/Maximized")->GetBool();
current_n_frame = context->videoController->GetFrameN();
current_frame = *context->project->VideoProvider()->GetFrame(current_n_frame, 0, true);
preview_image = GetImage(current_frame);
preview_frame = new ImagePositionPicker(this, preview_image, [&](int x, int y, unsigned char r, unsigned char g, unsigned char b) -> void {
selected_x->ChangeValue(wxString::Format(wxT("%i"), x));
selected_y->ChangeValue(wxString::Format(wxT("%i"), y));
selected_color->SetColor(agi::Color(r, g, b));
});
selected_color = new ColourButton(this, wxSize(55, 16), true, agi::Color("FFFFFF"));
selected_color->SetToolTip(_("The key color to be followed"));
selected_x = new wxTextCtrl(this, -1, "0");
selected_x->SetToolTip(_("The x coord of the key point"));
selected_y = new wxTextCtrl(this, -1, "0");
selected_y->SetToolTip(_("The y coord of the key point"));
selected_tolerance = new wxTextCtrl(this, -1, wxString::Format(wxT("%i"), int(tolerance)));
selected_tolerance->SetToolTip(_("Max tolerance of the color"));
selected_x->Bind(wxEVT_TEXT, &DialogAlignToVideo::update_from_textbox, this);
selected_y->Bind(wxEVT_TEXT, &DialogAlignToVideo::update_from_textbox, this);
update_from_textbox();
wxFlexGridSizer* right_sizer = new wxFlexGridSizer(4, 2, 5, 5);
add_with_label(right_sizer, _("X"), selected_x);
add_with_label(right_sizer, _("Y"), selected_y);
add_with_label(right_sizer, _("Color"), selected_color);
add_with_label(right_sizer, _("Tolerance"), selected_tolerance);
right_sizer->AddGrowableCol(1, 1);
wxSizer* main_sizer = new wxBoxSizer(wxHORIZONTAL);
main_sizer->Add(preview_frame, 1, (wxALL & ~wxRIGHT) | wxEXPAND, 5);
main_sizer->Add(right_sizer, 0, wxALIGN_LEFT, 5);
wxSizer* dialog_sizer = new wxBoxSizer(wxVERTICAL);
dialog_sizer->Add(main_sizer, wxSizerFlags(1).Border(wxALL & ~wxBOTTOM).Expand());
dialog_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Right().Border());
SetSizerAndFit(dialog_sizer);
SetSize(1024, 700);
CenterOnParent();
Bind(wxEVT_BUTTON, &DialogAlignToVideo::process, this, wxID_OK);
Bind(wxEVT_LEFT_DCLICK, &DialogAlignToVideo::process, this, preview_frame->GetId());
SetIcon(GETICON(button_align_16));
if (maximized)
wxDialog::Maximize(true);
}
DialogAlignToVideo::~DialogAlignToVideo()
{
long lt;
if (!selected_tolerance->GetValue().ToLong(&lt))
return;
if (lt < 0 || lt > 255)
return;
OPT_SET("Tool/Align to Video/Tolerance")->SetInt(lt);
}
void rgb2lab(unsigned char r, unsigned char g, unsigned char b, double* lab)
{
double X = (0.412453 * r + 0.357580 * g + 0.180423 * b) / 255.0;
double Y = (0.212671 * r + 0.715160 * g + 0.072169 * b) / 255.0;
double Z = (0.019334 * r + 0.119193 * g + 0.950227 * b) / 255.0;
double xr = X / 0.950456, yr = Y / 1.000, zr = Z / 1.088854;
if (yr > 0.008856) {
lab[0] = 116.0 * pow(yr, 1.0 / 3.0) - 16.0;
}
else {
lab[0] = 903.3 * yr;
}
double fxr, fyr, fzr;
if (xr > 0.008856)
fxr = pow(xr, 1.0 / 3.0);
else
fxr = 7.787 * xr + 16.0 / 116.0;
if (yr > 0.008856)
fyr = pow(yr, 1.0 / 3.0);
else
fyr = 7.787 * yr + 16.0 / 116.0;
if (zr > 0.008856)
fzr = pow(zr, 1.0 / 3.0);
else
fzr = 7.787 * zr + 16.0 / 116.0;
lab[1] = 500.0 * (fxr - fyr);
lab[2] = 200.0 * (fyr - fzr);
}
template<typename T>
bool check_point(boost::gil::pixel<unsigned char, T> & pixel, double orig[3], unsigned char tolerance)
{
double lab[3];
// in pixel: B,G,R
rgb2lab(pixel[2], pixel[1], pixel[0], lab);
auto diff = sqrt(pow(lab[0] - orig[0], 2) + pow(lab[1] - orig[1], 2) + pow(lab[2] - orig[2], 2));
return diff <= tolerance;
}
template<typename T>
bool calculate_point(boost::gil::image_view<T> view, int x, int y, double orig[3], unsigned char tolerance, int* ret)
{
auto origin = *view.at(x, y);
if (!check_point(origin, orig, tolerance))
return false;
auto w = view.width();
auto h = view.height();
int l = x, r = x, u = y, d = y;
for (int i = x + 1; i < w; i++)
{
auto p = *view.at(i, y);
if (!check_point(p, orig, tolerance))
{
r = i;
break;
}
}
for (int i = x - 1; i >= 0; i--)
{
auto p = *view.at(i, y);
if (!check_point(p, orig, tolerance))
{
l = i;
break;
}
}
for (int i = y + 1; i < h; i++)
{
auto p = *view.at(x, i);
if (!check_point(p, orig, tolerance))
{
d = i;
break;
}
}
for (int i = y - 1; i >= 0; i--)
{
auto p = *view.at(x, i);
if (!check_point(p, orig, tolerance))
{
u = i;
break;
}
}
ret[0] = l;
ret[1] = r;
ret[2] = u;
ret[3] = d;
return true;
}
void DialogAlignToVideo::process(wxEvent &)
{
auto n_frames = provider->GetFrameCount();
auto w = provider->GetWidth();
auto h = provider->GetHeight();
long lx, ly, lt;
if (!selected_x->GetValue().ToLong(&lx) || !selected_y->GetValue().ToLong(&ly) || !selected_tolerance->GetValue().ToLong(&lt))
{
wxMessageBox(_("Bad x or y position or tolerance value!"));
return;
}
if (lx < 0 || ly < 0 || lx >= w || ly >= h)
{
wxMessageBox(wxString::Format(_("Bad x or y position! Require: 0 <= x < %i, 0 <= y < %i"), w, h));
return;
}
if (lt < 0 || lt > 255)
{
wxMessageBox(_("Bad tolerance value! Require: 0 <= torlerance <= 255"));
return;
}
int x = int(lx), y = int(ly);
unsigned char tolerance = (unsigned char)(lt);
auto color = selected_color->GetColor();
auto r = color.r;
auto b = color.b;
auto g = color.g;
double lab[3];
rgb2lab(r, g, b, lab);
int pos = current_n_frame;
auto frame = provider->GetFrame(pos, -1, true);
auto view = interleaved_view(frame->width, frame->height, reinterpret_cast<boost::gil::bgra8_pixel_t*>(frame->data.data()), frame->pitch);
if (frame->flipped)
y = frame->height - y;
// Ensure selected color and position match
if(!check_point(*view.at(x,y), lab, tolerance))
{
wxMessageBox(_("Selected position and color are not within tolerance!"));
return;
}
int lrud[4];
calculate_point(view, x, y, lab, tolerance, lrud);
// find forward
#define CHECK_EXISTS_POS check_exists(pos, x, y, lrud, lab, tolerance)
do {
pos -= 2;
} while (pos >= 0 && CHECK_EXISTS_POS);
pos++;
pos = std::max(0, pos);
auto left = CHECK_EXISTS_POS ? pos : pos + 1;
pos = current_n_frame;
do {
pos += 2;
} while (pos < n_frames && CHECK_EXISTS_POS);
pos--;
pos = std::min(pos, n_frames - 1);
auto right = CHECK_EXISTS_POS ? pos : pos - 1;
auto timecode = context->project->Timecodes();
auto line = context->selectionController->GetActiveLine();
line->Start = timecode.TimeAtFrame(left, agi::vfr::Time::START);
line->End = timecode.TimeAtFrame(right, agi::vfr::Time::END); // exclusive
context->ass->Commit(_("Align to video by key point"), AssFile::COMMIT_DIAG_TIME);
Close();
}
bool DialogAlignToVideo::check_exists(int pos, int x, int y, int* lrud, double* orig, unsigned char tolerance)
{
auto frame = provider->GetFrame(pos, -1, true);
auto view = interleaved_view(frame->width, frame->height, reinterpret_cast<boost::gil::bgra8_pixel_t*>(frame->data.data()), frame->pitch);
if (frame->flipped)
y = frame->height - y;
int actual[4];
if (!calculate_point(view, x, y, orig, tolerance, actual)) return false;
int dl = abs(actual[0] - lrud[0]);
int dr = abs(actual[1] - lrud[1]);
int du = abs(actual[2] - lrud[2]);
int dd = abs(actual[3] - lrud[3]);
return dl <= 5 && dr <= 5 && du <= 5 && dd <= 5;
}
void DialogAlignToVideo::update_from_textbox()
{
long lx, ly;
int w = preview_image.GetWidth(), h = preview_image.GetHeight();
if (!selected_x->GetValue().ToLong(&lx) || !selected_y->GetValue().ToLong(&ly))
return;
if (lx < 0 || ly < 0 || lx >= w || ly >= h)
return;
int x = int(lx);
int y = int(ly);
auto r = preview_image.GetRed(x, y);
auto g = preview_image.GetGreen(x, y);
auto b = preview_image.GetBlue(x, y);
selected_color->SetColor(agi::Color(r, g, b));
}
void DialogAlignToVideo::update_from_textbox(wxCommandEvent & evt)
{
update_from_textbox();
}
}
void ShowAlignToVideoDialog(agi::Context * c)
{
c->dialog->Show<DialogAlignToVideo>(c);
}

View file

@ -74,3 +74,4 @@ void ShowSpellcheckerDialog(agi::Context *c);
void ShowStyleManagerDialog(agi::Context *c);
void ShowTimingProcessorDialog(agi::Context *c);
void ShowVideoDetailsDialog(agi::Context *c);
void ShowAlignToVideoDialog(agi::Context* c);

View file

@ -29,6 +29,11 @@
#include <wx/msgdlg.h>
namespace {
const char* added_hotkeys_cj[][3] = {
{"time/align", "Video", "KP_TAB"},
{nullptr}
};
const char *added_hotkeys_7035[][3] = {
{"audio/play/line", "Audio", "R"},
{nullptr}
@ -81,6 +86,11 @@ void init() {
auto migrations = OPT_GET("App/Hotkey Migrations")->GetListString();
if (boost::find(migrations, "cj") == end(migrations)) {
migrate_hotkeys(added_hotkeys_cj);
migrations.emplace_back("cj");
}
if (boost::find(migrations, "7035") == end(migrations)) {
migrate_hotkeys(added_hotkeys_7035);
migrations.emplace_back("7035");

View file

@ -0,0 +1,132 @@
#include "image_position_picker.h"
BEGIN_EVENT_TABLE(ImagePositionPicker, wxPanel)
// some useful events
/*
EVT_MOTION(ImagePositionPicker::mouseMoved)
EVT_LEFT_DOWN(ImagePositionPicker::mouseDown)
EVT_LEFT_UP(ImagePositionPicker::mouseReleased)
EVT_RIGHT_DOWN(ImagePositionPicker::rightClick)
EVT_LEAVE_WINDOW(ImagePositionPicker::mouseLeftWindow)
EVT_KEY_DOWN(ImagePositionPicker::keyPressed)
EVT_KEY_UP(ImagePositionPicker::keyReleased)
EVT_MOUSEWHEEL(ImagePositionPicker::mouseWheelMoved)
*/
// catch paint events
EVT_PAINT(ImagePositionPicker::paintEvent)
//Size event
EVT_SIZE(ImagePositionPicker::OnSize)
EVT_MOUSE_EVENTS(ImagePositionPicker::OnMouseEvent)
END_EVENT_TABLE()
// some useful events
/*
void ImagePositionPicker::mouseMoved(wxMouseEvent& event) {}
void ImagePositionPicker::mouseDown(wxMouseEvent& event) {}
void ImagePositionPicker::mouseWheelMoved(wxMouseEvent& event) {}
void ImagePositionPicker::mouseReleased(wxMouseEvent& event) {}
void ImagePositionPicker::rightClick(wxMouseEvent& event) {}
void ImagePositionPicker::mouseLeftWindow(wxMouseEvent& event) {}
void ImagePositionPicker::keyPressed(wxKeyEvent& event) {}
void ImagePositionPicker::keyReleased(wxKeyEvent& event) {}
*/
ImagePositionPicker::ImagePositionPicker(wxWindow* parent, wxImage i, updator upd) : wxPanel(parent)
{
image = i;
prevW = -1;
prevH = -1;
w = image.GetWidth();
h = image.GetHeight();
update = upd;
}
/*
* Called by the system of by wxWidgets when the panel needs
* to be redrawn. You can also trigger this call by
* calling Refresh()/Update().
*/
void ImagePositionPicker::paintEvent(wxPaintEvent& evt)
{
// depending on your system you may need to look at double-buffered dcs
wxPaintDC dc(this);
render(dc);
}
/*
* Alternatively, you can use a clientDC to paint on the panel
* at any time. Using this generally does not free you from
* catching paint events, since it is possible that e.g. the window
* manager throws away your drawing when the window comes to the
* background, and expects you will redraw it when the window comes
* back (by sending a paint event).
*/
void ImagePositionPicker::paintNow()
{
// depending on your system you may need to look at double-buffered dcs
wxClientDC dc(this);
render(dc);
}
/*
* Here we do the actual rendering. I put it in a separate
* method so that it can work no matter what type of DC
* (e.g. wxPaintDC or wxClientDC) is used.
*/
void ImagePositionPicker::render(wxDC& dc)
{
int neww, newh;
dc.GetSize(&neww, &newh);
if (neww != prevW || newh != prevH)
{
// keep the image proportionate
int ww, hh;
if (double(neww) / w >= double(newh) / h) // too long
{
ww = newh * w / h;
hh = newh;
}
else
{
ww = neww;
hh = neww * h / w;
}
resized = wxBitmap(image.Scale(ww, hh /*, wxIMAGE_QUALITY_HIGH*/));
prevW = ww;
prevH = hh;
dc.DrawBitmap(resized, 0, 0, false);
}
else {
dc.DrawBitmap(resized, 0, 0, false);
}
}
/*
* Here we call refresh to tell the panel to draw itself again.
* So when the user resizes the image panel the image should be resized too.
*/
void ImagePositionPicker::OnSize(wxSizeEvent& event) {
Refresh();
//skip the event.
event.Skip();
}
void ImagePositionPicker::OnMouseEvent(wxMouseEvent& evt)
{
wxPoint pos = evt.GetPosition();
if (evt.Dragging() || evt.LeftDown() || evt.LeftUp())
{
int x = pos.x * w / prevW;
int y = pos.y * h / prevH;
if (x >= 0 && x < w && y >= 0 && y < h)
update(x, y, image.GetRed(x, y), image.GetGreen(x, y), image.GetBlue(x, y));
}
else if (evt.LeftDClick()) {
// Propagate the double click event to submit
evt.ResumePropagation(wxEVENT_PROPAGATE_MAX);
evt.Skip();
}
}

View file

@ -0,0 +1,37 @@
#include <wx/wx.h>
#include <wx/sizer.h>
#include "gl_wrap.h"
typedef std::function<void(double, double, unsigned char, unsigned char, unsigned char)> updator;
class ImagePositionPicker : public wxPanel
{
wxImage image;
wxBitmap resized;
int prevW, prevH, w, h;
updator update;
public:
ImagePositionPicker(wxWindow* parent, wxImage i, updator upd);
void paintEvent(wxPaintEvent & evt);
void paintNow();
void OnSize(wxSizeEvent& event);
void OnMouseEvent(wxMouseEvent& evt);
void render(wxDC& dc);
// some useful events
/*
void mouseMoved(wxMouseEvent& event);
void mouseDown(wxMouseEvent& event);
void mouseWheelMoved(wxMouseEvent& event);
void mouseReleased(wxMouseEvent& event);
void rightClick(wxMouseEvent& event);
void mouseLeftWindow(wxMouseEvent& event);
void keyPressed(wxKeyEvent& event);
void keyReleased(wxKeyEvent& event);
*/
DECLARE_EVENT_TABLE()
};

View file

@ -581,6 +581,10 @@
},
"Visual" : {
"Autohide": false
},
"Align to Video" : {
"Tolerance" : 20,
"Maximized" : true
}
},
@ -590,6 +594,8 @@
},
"Video" : {
"Disable Scroll Zoom" : false,
"Reverse Zoom" : false,
"Default Zoom" : 7,
"Detached" : {
"Enabled" : false,
@ -619,6 +625,6 @@
},
"Subtitle Sync" : true,
"Video Pan": false,
"Default to UI Zoom": false
"Default to Video Zoom": false
}
}

View file

@ -263,7 +263,7 @@
"subtitle/select/all" : [
"Ctrl-A"
],
"grid/toggle" : [
"grid/fold/toggle" : [
"Enter"
],
"video/frame/next" : [
@ -289,6 +289,9 @@
],
"video/frame/prev/large" : [
"Alt-Left"
],
"time/align" : [
"KP_TAB"
]
},
"Translation Assistant" : {

View file

@ -42,6 +42,7 @@
"subtitle/select/visible",
"time/snap/scene",
"time/frame/current",
"time/align",
"",
"tool/style/manager",
"subtitle/properties",

View file

@ -580,6 +580,10 @@
},
"Visual" : {
"Autohide": false
},
"Align to Video" : {
"Tolerance" : 20,
"Maximized" : true
}
},
@ -589,6 +593,8 @@
},
"Video" : {
"Disable Scroll Zoom" : false,
"Reverse Zoom" : false,
"Default Zoom" : 7,
"Detached" : {
"Enabled" : false,
@ -618,6 +624,6 @@
},
"Subtitle Sync" : true,
"Video Pan": false,
"Default to UI Zoom": false
"Default to Video Zoom": false
}
}

View file

@ -273,7 +273,7 @@
"subtitle/select/all" : [
"Ctrl-A"
],
"grid/toggle" : [
"grid/fold/toggle" : [
"Enter"
],
"video/frame/next" : [

View file

@ -56,6 +56,7 @@ aegisub_src = files(
'context.cpp',
'crash_writer.cpp',
'dialog_about.cpp',
'dialog_align.cpp',
'dialog_attachments.cpp',
'dialog_automation.cpp',
'dialog_autosave.cpp',
@ -98,6 +99,7 @@ aegisub_src = files(
'help_button.cpp',
'hotkey.cpp',
'hotkey_data_view_model.cpp',
'image_position_picker.cpp',
'initial_line_state.cpp',
'main.cpp',
'menu.cpp',

View file

@ -174,6 +174,9 @@ void Video(wxTreebook *book, Preferences *parent) {
p->CellSkip(general);
p->OptionAdd(general, _("Automatically open audio when opening video"), "Video/Open Audio");
p->CellSkip(general);
p->OptionAdd(general, _("Disable zooming with scroll bar"), "Video/Disable Scroll Zoom")
->SetToolTip("Makes the scroll bar not zoom the video. Useful when using a track pad that often scrolls accidentally.");
p->OptionAdd(general, _("Reverse zoom direction"), "Video/Reverse Zoom");
const wxString czoom_arr[24] = { "12.5%", "25%", "37.5%", "50%", "62.5%", "75%", "87.5%", "100%", "112.5%", "125%", "137.5%", "150%", "162.5%", "175%", "187.5%", "200%", "212.5%", "225%", "237.5%", "250%", "262.5%", "275%", "287.5%", "300%" };
wxArrayString choice_zoom(24, czoom_arr);
@ -446,7 +449,8 @@ void Advanced_Video(wxTreebook *book, Preferences *parent) {
p->OptionChoice(expert, _("Subtitles provider"), sp_choice, "Subtitle/Provider");
p->OptionAdd(expert, _("Video Panning"), "Video/Video Pan");
p->OptionAdd(expert, _("Default to UI Zoom"), "Video/Default to UI Zoom");
p->OptionAdd(expert, _("Default to Video Zoom"), "Video/Default to Video Zoom")
->SetToolTip("Reverses the behavior of Ctrl while scrolling the video display. If not set, scrolling will default to UI zoom and Ctrl+scrolling will zoom the video. If set, this will be reversed.");
#ifdef WITH_AVISYNTH

View file

@ -73,3 +73,18 @@ void TextSelectionController::SetSelection(int start, int end) {
changing = false;
AnnounceSelectionChanged();
}
void TextSelectionController::CommitStagedChanges() {
if (has_staged_selection) {
if (staged_selection_start <= staged_selection_end) {
SetSelection(staged_selection_start, staged_selection_end);
} else {
// commit some crimes to get this to work in all cases
SetInsertionPoint(staged_selection_end == 0 ? staged_selection_start : 0);
SetSelection(staged_selection_start, staged_selection_start);
SetInsertionPoint(staged_selection_end);
}
has_staged_selection = false;
}
}

View file

@ -25,6 +25,10 @@ class TextSelectionController {
int insertion_point = 0;
bool changing = false;
int staged_selection_start = 0;
int staged_selection_end = 0;
bool has_staged_selection = false;
wxStyledTextCtrl *ctrl = nullptr;
void UpdateUI(wxStyledTextEvent &evt);
@ -35,10 +39,23 @@ public:
void SetSelection(int start, int end);
void SetInsertionPoint(int point);
// This set of functions allows staging changes to the selection or insertion points, which can then be applied later.
// This is useful when one is still waiting on other changes to be applied, but already listening for changes to the
// selection in the eventually visible text.
// They also provide a wrapper for setting a selection whose insertion point is on the left side.
void StageSetSelection(int start, int end) { staged_selection_start = start; staged_selection_end = end; has_staged_selection = true; };
void StageSetInsertionPoint(int point) { StageSetSelection(point, point); };
void CommitStagedChanges();
void DropStagedChanges() { has_staged_selection = false; };
int GetSelectionStart() const { return selection_start; }
int GetSelectionEnd() const { return selection_end; }
int GetInsertionPoint() const { return insertion_point; }
int GetStagedSelectionStart() const { return has_staged_selection ? staged_selection_start : selection_start; }
int GetStagedSelectionEnd() const { return has_staged_selection ? staged_selection_end : selection_end; }
int GetStagedInsertionPoint() const { return has_staged_selection ? staged_selection_end : insertion_point; }
void SetControl(wxStyledTextCtrl *ctrl);
~TextSelectionController();

View file

@ -409,8 +409,11 @@ void VideoDisplay::OnMouseLeave(wxMouseEvent& event) {
void VideoDisplay::OnMouseWheel(wxMouseEvent& event) {
bool videoPan = OPT_GET("Video/Video Pan")->GetBool();
if (int wheel = event.GetWheelRotation()) {
if (ForwardMouseWheelEvent(this, event)) {
if (!videoPan || (event.ControlDown() != OPT_GET("Video/Default to UI Zoom")->GetBool())) {
if (ForwardMouseWheelEvent(this, event) && !OPT_GET("Video/Disable Scroll Zoom")->GetBool()) {
if (OPT_GET("Video/Reverse Zoom")->GetBool()) {
wheel = -wheel;
}
if (!videoPan || (event.ControlDown() == OPT_GET("Video/Default to Video Zoom")->GetBool())) {
SetWindowZoom(windowZoomValue + .125 * (wheel / event.GetWheelDelta()));
} else {
SetVideoZoom(wheel / event.GetWheelDelta());