Merge branch 'master' into meson-vs2019
14
.ci/upload_win_installer.sh
Normal file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
dest="ftp://shelter.mahoro-net.org/aegisub-japan7"
|
||||
tag=$(git describe --exact-match)
|
||||
[ "$tag" ] || exit
|
||||
|
||||
curl -T 'packages\win_installer\output\Aegisub-Japan7-x64.exe' --user $FTP_USER:$FTP_PASS "$dest/Aegisub-Japan7-${tag#v}-x64.exe"
|
||||
|
||||
printf "${tag#v}\n$(git tag -l --format='%(contents)' $tag)" > latest
|
||||
curl -T latest --user "$FTP_USER:$FTP_PASS" "$dest/"
|
||||
|
||||
url="Aegisub-Japan7-${tag#v}-x64.exe"
|
||||
printf "<!doctype html><html><head><meta http-equiv='refresh' content='0; url=$url' /></head><body><a href='$url'>$url</a></body></html>" > Aegisub-Japan7-latest-x64
|
||||
curl -T Aegisub-Japan7-latest-x64 --user "$FTP_USER:$FTP_PASS" "$dest/"
|
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "subprojects/japan7-fonts"]
|
||||
path = subprojects/japan7-fonts
|
||||
url = https://github.com/odrling/japan7-fonts.git
|
54
README.md
@ -1,18 +1,24 @@
|
||||
# Aegisub
|
||||
# Aegisub-Japan7
|
||||
|
||||
For binaries and general information [see the homepage](http://www.aegisub.org).
|
||||
[](https://ci.appveyor.com/project/odrling/aegisub/branch/master)
|
||||
|
||||
The bug tracker can be found at http://devel.aegisub.org.
|
||||
## Installation
|
||||
|
||||
Support is available on [the forums](http://forum.aegisub.org) or [on IRC](irc://irc.rizon.net/aegisub).
|
||||
The latest Windows build can be downloaded at https://mugen.karaokes.moe/downloads/aegisub-japan7/Aegisub-Japan7-latest-x64
|
||||
|
||||
## Building Aegisub
|
||||
A package is available on the AUR for Arch Linux users: [aegisub-japan7-git](https://aur.archlinux.org/packages/aegisub-japan7-git/)
|
||||
|
||||
An ebuild is available for Gentoo users at https://git.odrling.xyz/odrling/odrling-overlay/src/branch/master/media-video/aegisub/aegisub-9999.ebuild
|
||||
|
||||
The default style uses the [Amaranth font](https://github.com/googlefonts/amaranth), which is installed by default when installing from the sources above.
|
||||
|
||||
## Building Aegisub-Japan7
|
||||
|
||||
### Windows
|
||||
|
||||
Prerequisites:
|
||||
|
||||
1. Visual Studio 2015 (the free Community edition is good enough)
|
||||
1. Visual Studio 2017 (the free Community edition is good enough)
|
||||
2. The June 2010 DirectX SDK (the final release before DirectSound was dropped)
|
||||
3. [Yasm](http://yasm.tortall.net/) installed to somewhere on your path.
|
||||
|
||||
@ -81,6 +87,42 @@ wxWidgets is located in vendor/wxWidgets, and can be built like so:
|
||||
Once the dependencies are installed, build Aegisub with `autoreconf && ./configure --with-wxdir=/path/to/Aegisub/vendor/wxWidgets && make && make osx-bundle`.
|
||||
`autoreconf` should be skipped if you are building from a source tarball rather than `git`.
|
||||
|
||||
### Linux, BSD or Toasters
|
||||
|
||||
Install all the dependencies with the package manager of your distribution:
|
||||
|
||||
wxGTK
|
||||
boost
|
||||
icu
|
||||
ffmpegsource
|
||||
fontconfig
|
||||
freetype
|
||||
libass
|
||||
zlib
|
||||
libiconv
|
||||
opengl
|
||||
openal
|
||||
openssl or libressl
|
||||
|
||||
Optional dependencies:
|
||||
|
||||
alsa-lib
|
||||
fftw
|
||||
openal
|
||||
portaudio
|
||||
pulseaudio
|
||||
hunspell
|
||||
luajit (can be bundled with your build)
|
||||
|
||||
|
||||
Once all the dependencies are installed, run:
|
||||
|
||||
```bash
|
||||
./autogen.sh
|
||||
./configure
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
## Updating Moonscript
|
||||
|
||||
From within the Moonscript repository, run `bin/moon bin/splat.moon -l moonscript moonscript/ > bin/moonscript.lua`.
|
||||
|
87
appveyor.yml
Normal file
@ -0,0 +1,87 @@
|
||||
image: Visual Studio 2017
|
||||
|
||||
install:
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- git submodule update --init --recursive
|
||||
- curl -O https://mugen.karaokes.moe/downloads/aegisub-japan7/openssl-aegisub.zip
|
||||
- set PATH=C:\gettext\bin;"C:\Program Files (x86)\Inno Setup 5";C:\yasm;%PATH%
|
||||
- mkdir C:\yasm
|
||||
- curl -o "C:\yasm\yasm.exe" http://www.tortall.net/projects/yasm/releases/yasm-1.3.0-win64.exe
|
||||
- mkdir C:\gettext
|
||||
- curl -L -o "C:\gettext.zip" https://github.com/vslavik/gettext-tools-windows/releases/download/v0.20.1/gettext-tools-windows-0.20.1.zip
|
||||
- cd C:\gettext
|
||||
- 7z x C:\gettext.zip
|
||||
|
||||
build_script:
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- MSBuild.exe Aegisub.sln /target:BuildTasks
|
||||
- 7z x openssl-aegisub.zip
|
||||
- MSBuild.exe Aegisub.sln /m /p:Configuration=Release /p:Platform=x64
|
||||
|
||||
after_build:
|
||||
- curl -o "C:\aegisub-codecs.zip" https://mugen.karaokes.moe/downloads/aegisub-codecs.zip
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
- msgfmt.exe -o po\ar.mo po\ar.po
|
||||
- msgfmt.exe -o po\wxstd-ar.mo vendor\wxWidgets\locale\ar.po
|
||||
- msgfmt.exe -o po\bg.mo po\bg.po
|
||||
- msgfmt.exe -o po\ca.mo po\ca.po
|
||||
- msgfmt.exe -o po\wxstd-ca.mo vendor\wxWidgets\locale\ca.po
|
||||
- msgfmt.exe -o po\cs.mo po\cs.po
|
||||
- msgfmt.exe -o po\wxstd-cs.mo vendor\wxWidgets\locale\cs.po
|
||||
- msgfmt.exe -o po\da.mo po\da.po
|
||||
- msgfmt.exe -o po\wxstd-da.mo vendor\wxWidgets\locale\da.po
|
||||
- msgfmt.exe -o po\de.mo po\de.po
|
||||
- msgfmt.exe -o po\wxstd-de.mo vendor\wxWidgets\locale\de.po
|
||||
- msgfmt.exe -o po\el.mo po\el.po
|
||||
- msgfmt.exe -o po\wxstd-el.mo vendor\wxWidgets\locale\el.po
|
||||
- msgfmt.exe -o po\es.mo po\es.po
|
||||
- msgfmt.exe -o po\wxstd-es.mo vendor\wxWidgets\locale\es.po
|
||||
- msgfmt.exe -o po\eu.mo po\eu.po
|
||||
- msgfmt.exe -o po\wxstd-eu.mo vendor\wxWidgets\locale\eu.po
|
||||
- msgfmt.exe -o po\fa.mo po\fa.po
|
||||
- msgfmt.exe -o po\fi.mo po\fi.po
|
||||
- msgfmt.exe -o po\wxstd-fi.mo vendor\wxWidgets\locale\fi.po
|
||||
- msgfmt.exe -o po\fr_FR.mo po\fr_FR.po
|
||||
- msgfmt.exe -o po\wxstd-fr.mo vendor\wxWidgets\locale\fr.po
|
||||
- msgfmt.exe -o po\gl.mo po\gl.po
|
||||
- msgfmt.exe -o po\wxstd-gl_ES.mo vendor\wxWidgets\locale\gl_ES.po
|
||||
- msgfmt.exe -o po\hu.mo po\hu.po
|
||||
- msgfmt.exe -o po\wxstd-hu.mo vendor\wxWidgets\locale\hu.po
|
||||
- msgfmt.exe -o po\id.mo po\id.po
|
||||
- msgfmt.exe -o po\wxstd-id.mo vendor\wxWidgets\locale\id.po
|
||||
- msgfmt.exe -o po\it.mo po\it.po
|
||||
- msgfmt.exe -o po\wxstd-it.mo vendor\wxWidgets\locale\it.po
|
||||
- msgfmt.exe -o po\ja.mo po\ja.po
|
||||
- msgfmt.exe -o po\wxstd-ja.mo vendor\wxWidgets\locale\ja.po
|
||||
- msgfmt.exe -o po\ko.mo po\ko.po
|
||||
- msgfmt.exe -o po\wxstd-ko_KR.mo vendor\wxWidgets\locale\ko_KR.po
|
||||
- msgfmt.exe -o po\nl.mo po\nl.po
|
||||
- msgfmt.exe -o po\wxstd-nl.mo vendor\wxWidgets\locale\nl.po
|
||||
- msgfmt.exe -o po\pl.mo po\pl.po
|
||||
- msgfmt.exe -o po\wxstd-pl.mo vendor\wxWidgets\locale\pl.po
|
||||
- msgfmt.exe -o po\pt_BR.mo po\pt_BR.po
|
||||
- msgfmt.exe -o po\wxstd-pt_BR.mo vendor\wxWidgets\locale\pt_BR.po
|
||||
- msgfmt.exe -o po\pt_PT.mo po\pt_PT.po
|
||||
- msgfmt.exe -o po\wxstd-pt.mo vendor\wxWidgets\locale\pt.po
|
||||
- msgfmt.exe -o po\ru.mo po\ru.po
|
||||
- msgfmt.exe -o po\wxstd-ru.mo vendor\wxWidgets\locale\ru.po
|
||||
- msgfmt.exe -o po\sr_RS.mo po\sr_RS.po
|
||||
- msgfmt.exe -o po\sr_RS@latin.mo po\sr_RS@latin.po
|
||||
- msgfmt.exe -o po\uk_UA.mo po\uk_UA.po
|
||||
- msgfmt.exe -o po\wxstd-uk_UA.mo vendor\wxWidgets\locale\uk_UA.po
|
||||
- msgfmt.exe -o po\vi.mo po\vi.po
|
||||
- msgfmt.exe -o po\wxstd-vi.mo vendor\wxWidgets\locale\vi.po
|
||||
- msgfmt.exe -o po\zh_CN.mo po\zh_CN.po
|
||||
- msgfmt.exe -o po\wxstd-zh_CN.mo vendor\wxWidgets\locale\zh_CN.po
|
||||
- msgfmt.exe -o po\zh_TW.mo po\zh_TW.po
|
||||
- msgfmt.exe -o po\wxstd-zh_TW.mo vendor\wxWidgets\locale\zh_TW.po
|
||||
- 7z x "C:\aegisub-codecs.zip"
|
||||
- cd packages\win_installer
|
||||
- iscc aegisub3.iss
|
||||
- cd ..\..
|
||||
|
||||
on_success:
|
||||
- IF DEFINED APPVEYOR_REPO_TAG_NAME bash.exe ".ci\upload_win_installer.sh"
|
||||
|
||||
artifacts:
|
||||
- path: packages\win_installer\output\Aegisub-Japan7-x64.exe
|
25
automation/autoload/clean-k-tags.lua
Normal file
@ -0,0 +1,25 @@
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"Clean k tags"
|
||||
script_description = tr"Remove double k tags"
|
||||
script_author = "amoethyst"
|
||||
script_version = "1.0"
|
||||
|
||||
function special_k(subs, sel)
|
||||
|
||||
-- if the first tag is K/kf this would break the timing for the previous timing
|
||||
local expr = "^(.-){\\(ko?)([0-9.]*)[^}]-}([^{]-){\\[kK][fo]?([0-9.]*)[^}]-}( -{(\\[kK][fo]?)[0-9.]*[^}]-}.*)$"
|
||||
|
||||
for _, i in ipairs(sel) do
|
||||
line = subs[i]
|
||||
before, tag, k1, between, k2, after = line.text:match(expr)
|
||||
while after ~= nil do
|
||||
line.text = before .. "{\\" .. tag .. tonumber(k1) + tonumber(k2) .. "}" .. between .. after
|
||||
subs[i] = line
|
||||
before, tag, k1, between, k2, after = line.text:match(expr)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, script_description, special_k)
|
175
automation/autoload/duetto-meika.lua
Normal file
@ -0,0 +1,175 @@
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"Duetto Meika"
|
||||
script_description = tr"The ultimate tool for karaoke duets"
|
||||
script_author = "amoethyst"
|
||||
|
||||
include("utils.lua")
|
||||
|
||||
|
||||
function replace_style(line, style_name, style_string)
|
||||
before_style, after_style = line.text:match("^(.-{[^}]-)\\?s:".. style_name .."(.*)$")
|
||||
return before_style .. style_string .. after_style
|
||||
end
|
||||
|
||||
|
||||
function duetto(subs, sel)
|
||||
styles = {}
|
||||
|
||||
-- create the style map
|
||||
for _, line in ipairs(subs) do
|
||||
if line.class == "style" then
|
||||
styles[line.name] = line
|
||||
end
|
||||
end
|
||||
|
||||
-- duetto~
|
||||
for _, i in ipairs(sel) do
|
||||
line = subs[i]
|
||||
|
||||
current_style = styles[line.style]
|
||||
-- match every `s:` marker
|
||||
for style_name in line.text:gmatch("{[^}]*s:([^}\\]*)[^}]*}") do
|
||||
if style_name ~= current_style.name then
|
||||
|
||||
style = styles[style_name]
|
||||
-- build the tags to use the new style
|
||||
style_string = ""
|
||||
if current_style.color1 ~= style.color1 then
|
||||
style_string = style_string .. "\\c" .. style.color1
|
||||
end
|
||||
if current_style.color2 ~= style.color2 then
|
||||
style_string = style_string .. "\\2c" .. style.color2
|
||||
end
|
||||
if current_style.color3 ~= style.color3 then
|
||||
style_string = style_string .. "\\3c" .. style.color3
|
||||
end
|
||||
if current_style.color4 ~= style.color4 then
|
||||
style_string = style_string .. "\\4c" .. style.color4
|
||||
end
|
||||
|
||||
-- set style
|
||||
line.text = replace_style(line, style_name, style_string)
|
||||
current_style = style
|
||||
else
|
||||
-- remove marker to not break everything
|
||||
line.text = replace_style(line, style_name, "")
|
||||
end
|
||||
end
|
||||
subs[i] = line
|
||||
end
|
||||
|
||||
aegisub.set_undo_point(script_name)
|
||||
end
|
||||
|
||||
|
||||
function test_colors(c1, c2)
|
||||
return color_from_style(c1) == color_from_style(c2)
|
||||
end
|
||||
|
||||
|
||||
function get_script_style(style, styles)
|
||||
for key, script_style in pairs(styles) do
|
||||
if (test_colors(style.color1, script_style.color1)
|
||||
and test_colors(style.color2, script_style.color2)
|
||||
and test_colors(style.color3, script_style.color3)
|
||||
and test_colors(style.color4, script_style.color4)
|
||||
and tonumber(style.fontsize) == tonumber(script_style.fontsize)
|
||||
and style.fontname == script_style.fontname) then
|
||||
return script_style
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
function deduetto_meika(subs, sel)
|
||||
local styles = {}
|
||||
local last_style = -1
|
||||
|
||||
-- create the style map
|
||||
for i, line in ipairs(subs) do
|
||||
if line.class == "style" then
|
||||
styles[line.name] = line
|
||||
last_style = i
|
||||
end
|
||||
end
|
||||
|
||||
local new_styles = {}
|
||||
|
||||
for _, i in ipairs(sel) do
|
||||
local line = subs[i]
|
||||
local current_style = table.copy(styles[line.style])
|
||||
|
||||
local search_index = 1
|
||||
while search_index < #line.text do
|
||||
local match_start, match_end = line.text:find("{[^}]*}", search_index)
|
||||
if match_start == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local bracketed = line.text:sub(match_start, match_end)
|
||||
local new_style = false
|
||||
|
||||
-- change style's colors
|
||||
for tag, value in bracketed:gmatch("\\([1-4]?c)([^}\\]*)") do
|
||||
new_style = true
|
||||
if tag == "c" or tag == "1c" then
|
||||
current_style.color1 = value
|
||||
elseif tag == "2c" then
|
||||
current_style.color2 = value
|
||||
elseif tag == "3c" then
|
||||
current_style.color3 = value
|
||||
elseif tag == "4c" then
|
||||
current_style.color4 = value
|
||||
end
|
||||
end
|
||||
|
||||
-- change style's font
|
||||
for tag, value in bracketed:gmatch("\\(f[sn])([^}\\]*)") do
|
||||
new_style = true
|
||||
if tag == "fs" then
|
||||
current_style.fontsize = value
|
||||
elseif tag == "fn" then
|
||||
current_style.fontname = value
|
||||
end
|
||||
end
|
||||
|
||||
if new_style then
|
||||
local script_style = get_script_style(current_style, styles)
|
||||
if script_style == nil then
|
||||
if get_script_style(current_style, new_styles) == nil then
|
||||
new_styles[#new_styles+1] = table.copy(current_style)
|
||||
end
|
||||
else
|
||||
-- remove inline colors
|
||||
bracketed = bracketed:gsub("\\[1-4]?c[^\\}]*", "")
|
||||
bracketed = bracketed:gsub("\\[1-4]?a[^\\}]*", "")
|
||||
-- remove inline fonts
|
||||
bracketed = bracketed:gsub("\\f[sn][^\\}]*", "")
|
||||
|
||||
-- add style marker
|
||||
bracketed = "{s:" .. script_style.name .. bracketed:sub(2, #bracketed)
|
||||
line.text = line.text:sub(1, match_start-1) .. bracketed .. line.text:sub(match_end + 1, #line.text)
|
||||
end
|
||||
end
|
||||
|
||||
search_index = match_start + 1
|
||||
end
|
||||
|
||||
subs[i] = line
|
||||
end
|
||||
|
||||
if #new_styles > 0 then
|
||||
for i, new_style in ipairs(new_styles) do
|
||||
new_style.name = "Deduetto style " .. i
|
||||
subs.insert(last_style, new_style)
|
||||
last_style = last_style + 1
|
||||
aegisub.log("Created new style: " .. new_style.name .. "\n")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, script_description, duetto)
|
||||
aegisub.register_macro(tr"Deduetto Meika", tr"Create styles from inline color tags", deduetto_meika)
|
173
automation/autoload/karaoke-adjust-1sec.lua
Normal file
@ -0,0 +1,173 @@
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"Karaoke 1sec adjust lead-in"
|
||||
script_description = tr"Adjust karaoke leadin to 1sec"
|
||||
script_author = "Flore"
|
||||
script_version = "1.00"
|
||||
|
||||
include("cleantags.lua")
|
||||
|
||||
leadinmsec = 1000 --lead in time can be changed here
|
||||
|
||||
ktag = "\\[kK][fo]?%d+" --pattern used to detect karaoke tags
|
||||
|
||||
-- KM template line definition
|
||||
km_template_effect = "template pre-line all keeptags"
|
||||
km_template_text = '!retime("line",$start < 900 and -$start or -900,200)!{!$start < 900 and "\\\\k" .. ($start/10) or "\\\\k90"!\\fad(!$start < 900 and $start or 300!,200)}'
|
||||
|
||||
function hasleadin(line)--check if there is an existing lead in (2 consecutive bracket with karaoke tags at the start of the line)
|
||||
return line.text:find("^{[^{}]-" .. ktag .. "[^{}]-}%s*{[^{}]-" .. ktag .. "[^{}]-}")
|
||||
end
|
||||
|
||||
|
||||
function removeleadin(line)
|
||||
if not hasleadin(line) then
|
||||
return line
|
||||
end
|
||||
|
||||
leadin = tonumber( line.text:match("^{[^{}]-\\[kK][fo]?(%d+)[^{}]-}%s*{[^{}]-" .. ktag .. "[^{}]-}") ) --read lead-in value
|
||||
line.text = line.text:gsub("^({[^{}]-)\\[kK][fo]?%d+(.-}%s*{[^{}]-" .. ktag .. ".-})","%1%2") --remove lead in
|
||||
|
||||
line.text = cleantags(line.text) --clean tags
|
||||
|
||||
line.start_time = line.start_time + leadin*10 --adjust start time
|
||||
|
||||
--aegisub.log(line.text)
|
||||
|
||||
return line
|
||||
end
|
||||
|
||||
|
||||
function adjust_1sec(subs, sel)
|
||||
|
||||
for _, i in ipairs(sel) do
|
||||
local line = subs[i]
|
||||
|
||||
line.text = cleantags(line.text)
|
||||
|
||||
if( line.text:find(ktag)) then--don't do anything if there is no ktags in this line
|
||||
|
||||
--start by removing existing lead-in
|
||||
while hasleadin(line) do
|
||||
if aegisub.progress.is_cancelled() then return end
|
||||
line = removeleadin(line)
|
||||
end
|
||||
|
||||
--then add our lead in
|
||||
|
||||
if line.start_time >= leadinmsec then
|
||||
line.text = string.format("{\\k%d}%s",leadinmsec/10, line.text)
|
||||
line.start_time = line.start_time - leadinmsec
|
||||
|
||||
else --if line starts too early to put the needed lead in, make the line start at time 0 and fill with appropriate lead in
|
||||
line.text = string.format("{\\k%d}%s",line.start_time/10, line.text)
|
||||
line.start_time = 0
|
||||
end
|
||||
|
||||
subs[i] = line
|
||||
end
|
||||
end
|
||||
|
||||
aegisub.set_undo_point(tr"1sec adjust lead-in")
|
||||
end
|
||||
|
||||
|
||||
function remove_tag(line, tag)
|
||||
local expr = "^(.-{[^}]*)\\" .. tag .. "[^\\}]*(.*)"
|
||||
while true do
|
||||
before, after = line.text:match(expr)
|
||||
if before == nil then
|
||||
return line
|
||||
else
|
||||
line.text = cleantags(before .. after)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function is_template_line(line)
|
||||
return (line.class == "dialogue"
|
||||
and line.effect == km_template_effect
|
||||
and line.text == km_template_text)
|
||||
end
|
||||
|
||||
|
||||
function mugenizer(subs)
|
||||
local first = nil
|
||||
local styles_different = false
|
||||
local styles = 0
|
||||
local i_styles = {}
|
||||
local template_present = false
|
||||
|
||||
for i, line in ipairs(subs) do
|
||||
if line.class == "info" then
|
||||
if line.key == "PlayResX" or line.key == "PlayResY" then
|
||||
line.value = "0"
|
||||
end
|
||||
end
|
||||
|
||||
if line.class == "style" then
|
||||
line.fontname = "Arial"
|
||||
line.fontsize = "24"
|
||||
line.outline = "1.5"
|
||||
line.shadow = "0"
|
||||
line.margin_l = "15"
|
||||
line.margin_r = "15"
|
||||
line.margin_t = "20"
|
||||
line.margin_b = "20"
|
||||
|
||||
i_styles[styles] = i
|
||||
if styles > 0 then
|
||||
styles_different = styles_different or line.color1 ~= subs[i_styles[styles-1]].color1 or line.color2 ~= subs[i_styles[styles-1]].color2 or line.color3 ~= subs[i_styles[styles-1]].color3 or line.color4 ~= subs[i_styles[styles-1]].color4
|
||||
end
|
||||
styles = styles + 1
|
||||
end
|
||||
|
||||
if is_template_line(line) then
|
||||
line.comment = true
|
||||
template_present = true
|
||||
end
|
||||
|
||||
if line.class == "dialogue" and not line.comment and line.effect ~= "fx" then
|
||||
if first == nil then
|
||||
first = i
|
||||
end
|
||||
|
||||
line.text = cleantags(line.text)
|
||||
|
||||
while hasleadin(line) do
|
||||
if aegisub.progress.is_cancelled() then return end
|
||||
line = removeleadin(line)
|
||||
end
|
||||
|
||||
line = remove_tag(line, "fad")
|
||||
end
|
||||
|
||||
subs[i] = line
|
||||
end
|
||||
|
||||
if not styles_different then
|
||||
for i = 0, styles-1, 1 do
|
||||
line = subs[i_styles[i]]
|
||||
line.color1 = "&H008AFF"
|
||||
line.color2 = "&HFFFFFF"
|
||||
line.color3 = "&H000000"
|
||||
line.color4 = "&H000000"
|
||||
subs[i_styles[i]] = line
|
||||
end
|
||||
end
|
||||
|
||||
if not template_present then
|
||||
-- add mugen's magic line
|
||||
line = subs[first]
|
||||
line.comment = true
|
||||
line.start_time = 0
|
||||
line.end_time = 0
|
||||
line.effect = km_template_effect
|
||||
line.text = km_template_text
|
||||
subs.insert(first, line)
|
||||
end
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, script_description, adjust_1sec)
|
||||
aegisub.register_macro(tr"Mugenizer", tr"Mugenize your subs", mugenizer)
|
@ -1,79 +0,0 @@
|
||||
--[[
|
||||
Copyright (c) 2007, Niels Martin Hansen
|
||||
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.
|
||||
]]
|
||||
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"Automatic karaoke lead-in"
|
||||
script_description = tr"Join up the ends of selected lines and add \\k tags to shift karaoke"
|
||||
script_author = "Niels Martin Hansen"
|
||||
script_version = "1.0"
|
||||
|
||||
function add_auto_leadin(subs, sel)
|
||||
-- Smallest inter-line duration
|
||||
local min_interdur = nil
|
||||
|
||||
for i = 2, #sel do
|
||||
-- Grab two selected lines
|
||||
local A = subs[sel[i-1]]
|
||||
local B = subs[sel[i]]
|
||||
|
||||
-- Blank duration between lines
|
||||
local interdur = B.start_time - A.end_time
|
||||
|
||||
if interdur > 0 then
|
||||
-- Update smallest inter-line duration
|
||||
if not min_interdur or interdur < min_interdur then
|
||||
min_interdur = interdur
|
||||
end
|
||||
|
||||
B.start_time = A.end_time
|
||||
B.text = string.format("{\\k%d}%s", interdur/10, B.text)
|
||||
|
||||
subs[sel[i]] = B
|
||||
else
|
||||
aegisub.debug.out(2, "Warning: Skipping line-pair with zero or negative inter-duration:\n%s\n%s\n\n", A.text, B.text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if min_interdur then
|
||||
aegisub.debug.out(0, "Smallest inter-line duration: %d milliseconds", min_interdur)
|
||||
|
||||
aegisub.set_undo_point(script_name)
|
||||
else
|
||||
aegisub.debug.out(2, "Warning: No lines modified")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function check_minsel_2(subs, sel)
|
||||
return #sel >= 2
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, script_description, add_auto_leadin, check_minsel_2)
|
48
automation/autoload/karaoke-split.lua
Normal file
@ -0,0 +1,48 @@
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"Split karaoke line"
|
||||
script_description = tr"Split line at {split} marker according to ktags"
|
||||
script_author = "amoethyst"
|
||||
script_version = "1.0"
|
||||
|
||||
function split_line(subs, sel)
|
||||
|
||||
function getduration(line)
|
||||
d = 0
|
||||
|
||||
kduration = "{[^}]-\\[kK][fo]?(%d+)[^}]-}"
|
||||
for match in line:gmatch(kduration) do
|
||||
d = d + tonumber(match)
|
||||
end
|
||||
|
||||
return d * 10
|
||||
end
|
||||
|
||||
insertions = 0
|
||||
for _, i in ipairs(sel) do
|
||||
i = i + insertions
|
||||
line1 = subs[i]
|
||||
line2 = subs[i]
|
||||
|
||||
split_expr = "(.-)%s*{split}%s*(.*)"
|
||||
line1.text, line2.text = line1.text:match(split_expr)
|
||||
|
||||
while line1.text ~= nil do
|
||||
line1.end_time = line1.start_time + getduration(line1.text)
|
||||
line2.start_time = line1.end_time
|
||||
|
||||
subs[i] = line1
|
||||
i = i + 1
|
||||
insertions = insertions + 1
|
||||
subs.insert(i, line2)
|
||||
line1 = subs[i]
|
||||
|
||||
line1.text, line2.text = line1.text:match(split_expr)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
aegisub.set_undo_point(tr"Karaoke split")
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, script_description, split_line)
|
@ -1,21 +0,0 @@
|
||||
-- Automation 4 demo script
|
||||
-- Macro that adds \be1 tags in front of every selected line
|
||||
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"Add edgeblur"
|
||||
script_description = tr"A demo macro showing how to do simple line modification in Automation 4"
|
||||
script_author = "Niels Martin Hansen"
|
||||
script_version = "1"
|
||||
|
||||
|
||||
function add_edgeblur(subtitles, selected_lines, active_line)
|
||||
for z, i in ipairs(selected_lines) do
|
||||
local l = subtitles[i]
|
||||
l.text = "{\\be1}" .. l.text
|
||||
subtitles[i] = l
|
||||
end
|
||||
aegisub.set_undo_point(script_name)
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, tr"Adds \\be1 tags to all selected lines", add_edgeblur)
|
@ -1,80 +0,0 @@
|
||||
-- Automation 4 demo script
|
||||
-- Converts halfwidth (ASCII) Latin letters to fullwidth JIS Latin letters
|
||||
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr("Make text fullwidth")
|
||||
script_description = tr("Shows how to use the unicode include to iterate over characters and a lookup table to convert those characters to something else.")
|
||||
script_author = "Niels Martin Hansen"
|
||||
script_version = "1"
|
||||
|
||||
include("unicode.lua")
|
||||
|
||||
|
||||
lookup = {
|
||||
['!'] = '!', ['"'] = '”', ['#'] = '#', ['$'] = '$',
|
||||
['%'] = '%', ['&'] = '&', ["'"] = '’', ['('] = '(',
|
||||
[')'] = ')', ['*'] = '*', ['+'] = '+', [','] = ',',
|
||||
['-'] = '-', ['.'] = '.', ['/'] = '/',
|
||||
['1'] = '1', ['2'] = '2', ['3'] = '3', ['4'] = '4',
|
||||
['5'] = '5', ['6'] = '6', ['7'] = '7', ['8'] = '8',
|
||||
['9'] = '9', ['0'] = '0',
|
||||
[':'] = ':', [';'] = ';', ['<'] = '<', ['='] = '=',
|
||||
['>'] = '>', ['?'] = '?', ['@'] = '@',
|
||||
['A'] = 'A', ['B'] = 'B', ['C'] = 'C', ['D'] = 'D',
|
||||
['E'] = 'E', ['F'] = 'F', ['G'] = 'G', ['H'] = 'H',
|
||||
['I'] = 'I', ['J'] = 'J', ['K'] = 'K', ['L'] = 'L',
|
||||
['M'] = 'M', ['N'] = 'N', ['O'] = 'O', ['P'] = 'P',
|
||||
['Q'] = 'Q', ['R'] = 'R', ['S'] = 'S', ['T'] = 'T',
|
||||
['U'] = 'U', ['V'] = 'V', ['W'] = 'W', ['X'] = 'X',
|
||||
['Y'] = 'Y', ['Z'] = 'Z',
|
||||
['['] = '[', ['\\'] = '\', [']'] = ']', ['^'] = '^',
|
||||
['a'] = 'a', ['b'] = 'b', ['c'] = 'c', ['d'] = 'd',
|
||||
['e'] = 'e', ['f'] = 'f', ['g'] = 'g', ['h'] = 'h',
|
||||
['i'] = 'i', ['j'] = 'j', ['k'] = 'k', ['l'] = 'l',
|
||||
['m'] = 'm', ['n'] = 'n', ['o'] = 'o', ['p'] = 'p',
|
||||
['q'] = 'q', ['r'] = 'r', ['s'] = 's', ['t'] = 't',
|
||||
['u'] = 'u', ['v'] = 'v', ['w'] = 'w', ['x'] = 'x',
|
||||
['y'] = 'y', ['z'] = 'z',
|
||||
['_'] = '_', ['`'] = '‘',
|
||||
['{'] = '{', ['|'] = '|', ['}'] = '}', ['~'] = '~',
|
||||
}
|
||||
|
||||
function make_fullwidth(subtitles, selected_lines, active_line)
|
||||
for z, i in ipairs(selected_lines) do
|
||||
local l = subtitles[i]
|
||||
|
||||
aegisub.debug.out(string.format('Processing line %d: "%s"\n', i, l.text))
|
||||
aegisub.debug.out("Chars: \n")
|
||||
|
||||
local in_tags = false
|
||||
local newtext = ""
|
||||
for c in unicode.chars(l.text) do
|
||||
aegisub.debug.out(c .. ' -> ')
|
||||
if c == "{" then
|
||||
in_tags = true
|
||||
end
|
||||
if in_tags then
|
||||
aegisub.debug.out(c .. " (ignored, in tags)\n")
|
||||
newtext = newtext .. c
|
||||
else
|
||||
if lookup[c] then
|
||||
aegisub.debug.out(lookup[c] .. " (converted)\n")
|
||||
newtext = newtext .. lookup[c]
|
||||
else
|
||||
aegisub.debug.out(c .. " (not found in lookup)\n")
|
||||
newtext = newtext .. c
|
||||
end
|
||||
end
|
||||
if c == "}" then
|
||||
in_tags = false
|
||||
end
|
||||
end
|
||||
|
||||
l.text = newtext
|
||||
subtitles[i] = l
|
||||
end
|
||||
aegisub.set_undo_point(tr"Make fullwidth")
|
||||
end
|
||||
|
||||
aegisub.register_macro(tr"Make fullwidth", tr"Convert Latin letters to SJIS fullwidth letters", make_fullwidth)
|
@ -1,32 +0,0 @@
|
||||
-- Copyright (c) 2010, Thomas Goyne <plorkyeran@aegisub.org>
|
||||
--
|
||||
-- Permission to use, copy, modify, and distribute this software for any
|
||||
-- purpose with or without fee is hereby granted, provided that the above
|
||||
-- copyright notice and this permission notice appear in all copies.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
-- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
-- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
-- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
-- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
-- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
-- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"Strip tags"
|
||||
script_description = tr"Remove all override tags from selected lines"
|
||||
script_author = "Thomas Goyne"
|
||||
script_version = "1"
|
||||
|
||||
function strip_tags(subs, sel)
|
||||
for _, i in ipairs(sel) do
|
||||
local line = subs[i]
|
||||
line.text = line.text:gsub("{[^}]+}", "")
|
||||
subs[i] = line
|
||||
end
|
||||
aegisub.set_undo_point(tr"strip tags")
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, script_description, strip_tags)
|
||||
|
523
automation/autoload/ua.BlurAndGlow.lua
Normal file
@ -0,0 +1,523 @@
|
||||
--[[ "Blur / Layers" creates layers with blur. Supports 2 borders, xbord, ybord, xshad, and yshad. Basic support for transforms and \r.
|
||||
"Blur + Glow" - Same as above but with an extra layer for glow. Set blur amount and alpha for the glow.
|
||||
The "double border" option additionally lets you change the size and colour of the 2nd border.
|
||||
If blur is missing, default blur is added.
|
||||
"Bottom blur" allows you to use different blur for the lowest non-glow layer than for top layer(s).
|
||||
"fix \\1a for layers with border and fade" - Uses \1a&HFF& for the duration of a fade on layers with border.
|
||||
"transition" - for \fad(500,0) with transition 80ms you get \1a&HFF&\t(420,500,\1a&H00&).
|
||||
"only add glow" - will add glow to a line with a border, without messing with the primary / border. (Blur + Glow)
|
||||
"only add 2nd border" - will add 2nd border, without messing with the primary / first border. (Blur / Layers)
|
||||
"Fix fades" - Recalculates those \1a fades mentioned above.
|
||||
Use this when you shift something like an episode title to a new episode and the duration of the sign is different.
|
||||
"Change layer" - raises or lowers layer for all selected lines by the same amount. [This is separate from the other functions.]
|
||||
|
||||
Full manual: http://unanimated.xtreemhost.com/ts/scripts-manuals.htm#blurglow
|
||||
]]
|
||||
|
||||
script_name="Blur and Glow"
|
||||
script_description="Add blur and/or glow to signs"
|
||||
script_author="unanimated"
|
||||
script_url="http://unanimated.xtreemhost.com/ts/blur-and-glow.lua"
|
||||
script_version="2.5"
|
||||
script_namespace="ua.BlurAndGlow"
|
||||
|
||||
local haveDepCtrl,DependencyControl,depRec=pcall(require,"l0.DependencyControl")
|
||||
if haveDepCtrl then
|
||||
script_version="2.5.0"
|
||||
depRec=DependencyControl{feed="https://raw.githubusercontent.com/TypesettingTools/unanimated-Aegisub-Scripts/master/DependencyControl.json"}
|
||||
end
|
||||
|
||||
|
||||
function glow(subs,sel)
|
||||
if not res.rep then al=res.alfa bl=res.blur end
|
||||
if res.glowcol then glowc=res.glc:gsub("#(%x%x)(%x%x)(%x%x)","&H%3%2%1&") end
|
||||
if res.autod then if res.clr or res.bsize then res.double=true end end
|
||||
for z=#sel,1,-1 do
|
||||
i=sel[z]
|
||||
progress("Glowing line: "..(#sel-z+1).."/"..#sel)
|
||||
line=subs[i]
|
||||
text=line.text
|
||||
if defaref and line.style=="Default" then sr=defaref
|
||||
elseif lastref and laststyle==line.style then sr=lastref
|
||||
else sr=stylechk(line.style) end
|
||||
lastref=sr laststyle=line.style
|
||||
duration=line.end_time-line.start_time
|
||||
|
||||
-- get colors, border, shadow from style
|
||||
stylinfo(text)
|
||||
text=preprocess(text)
|
||||
line.text=text
|
||||
|
||||
if border~="0" or text:match("\\[xy]bord") then
|
||||
|
||||
-- WITH TWO BORDERS
|
||||
if res.double then
|
||||
|
||||
-- second border
|
||||
line1=line
|
||||
line1.text=text
|
||||
line1.text=borderline2(line1.text)
|
||||
line1.layer=line1.layer+1
|
||||
subs.insert(i+1,line1)
|
||||
|
||||
-- first border
|
||||
line2=line
|
||||
line2.text=text
|
||||
line2.text=borderline(line2.text)
|
||||
if shadow~="0" then line2.text=line2.text:gsub("^({\\[^}]+)}","%1\\shad"..shadow.."}") end
|
||||
if not res.s_mid then line2.text=line2.text:gsub("^({\\[^}]-)}","%1\\4a&HFF&}") end
|
||||
line2.layer=line2.layer+1
|
||||
subs.insert(i+2,line2)
|
||||
|
||||
-- top line
|
||||
line3=line
|
||||
line3.text=text
|
||||
line3.text=topline(line3.text)
|
||||
line3.layer=line3.layer+1
|
||||
subs.insert(i+3,line3)
|
||||
|
||||
-- bottom / glow
|
||||
text=borderline2(text)
|
||||
text=glowlayer(text,"3c","3")
|
||||
if res.botalpha and line.text:match("\\fad%(") then text=botalfa(text) end
|
||||
line.layer=line.layer-3
|
||||
line.text=text
|
||||
sls=3
|
||||
|
||||
else
|
||||
-- WITH ONE BORDER
|
||||
|
||||
-- border
|
||||
line2=line
|
||||
if not res.onlyg then
|
||||
line2.text=text
|
||||
line2.text=borderline(line2.text)
|
||||
end
|
||||
line2.layer=line2.layer+1
|
||||
subs.insert(i+1,line2)
|
||||
|
||||
-- top line
|
||||
line3=line
|
||||
line3.layer=line3.layer+1
|
||||
if not res.onlyg then
|
||||
line3.text=text
|
||||
line3.text=topline(line3.text)
|
||||
subs.insert(i+2,line3)
|
||||
end
|
||||
|
||||
-- bottom / glow
|
||||
text=glowlayer(text,"3c","3")
|
||||
if res.botalpha and line.text:match("\\fad%(") then text=botalfa(text) end
|
||||
line.layer=line.layer-2
|
||||
line.text=text
|
||||
sls=2
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
-- WITHOUT BORDER
|
||||
|
||||
line2=line
|
||||
line2.layer=line2.layer+1
|
||||
subs.insert(i+1,line2)
|
||||
text=glowlayer(text,"c","1")
|
||||
line.layer=line.layer-1
|
||||
line.text=text
|
||||
sls=1
|
||||
|
||||
end
|
||||
subs[i]=line
|
||||
for s=z,#sel do sel[s]=sel[s]+sls end
|
||||
end
|
||||
progress("Blur & Glow: DONE")
|
||||
return sel
|
||||
end
|
||||
|
||||
function layerblur(subs,sel)
|
||||
if res.autod then if res.clr or res.bsize then res.double=true end end
|
||||
for z=#sel,1,-1 do
|
||||
i=sel[z]
|
||||
progress("Blurring line: "..(#sel-z+1).."/"..#sel)
|
||||
line=subs[i]
|
||||
text=line.text
|
||||
if defaref~=nil and line.style=="Default" then sr=defaref
|
||||
elseif lastref~=nil and laststyle==line.style then sr=lastref
|
||||
else sr=stylechk(line.style) end
|
||||
lastref=sr laststyle=line.style
|
||||
duration=line.end_time-line.start_time
|
||||
|
||||
-- get colors, border, shadow from style
|
||||
stylinfo(text)
|
||||
text=preprocess(text)
|
||||
line.text=text
|
||||
|
||||
-- TWO BORDERS
|
||||
if res.double then
|
||||
|
||||
-- first border
|
||||
line2=line
|
||||
if not res.onlyb then
|
||||
line2.text=text
|
||||
line2.text=borderline(line2.text)
|
||||
if not res.s_mid then line2.text=line2.text:gsub("^({\\[^}]-)}","%1\\4a&HFF&}") end
|
||||
end
|
||||
line2.layer=line2.layer+1
|
||||
subs.insert(i+1,line2)
|
||||
|
||||
-- top line
|
||||
line3=line
|
||||
line3.layer=line3.layer+1
|
||||
if not res.onlyb then
|
||||
line3.text=text
|
||||
line3.text=topline(line3.text)
|
||||
subs.insert(i+2,line3)
|
||||
end
|
||||
|
||||
-- second border
|
||||
text=borderline2(text)
|
||||
line.layer=line.layer-2
|
||||
line.text=text
|
||||
sls=2
|
||||
|
||||
-- ONE BORDER
|
||||
else
|
||||
|
||||
-- top line
|
||||
line3=line
|
||||
line3.text=text
|
||||
line3.text=topline(line3.text)
|
||||
line3.layer=line3.layer+1
|
||||
subs.insert(i+1,line3)
|
||||
|
||||
-- bottom line
|
||||
text=borderline(text)
|
||||
line.layer=line.layer-1
|
||||
line.text=text
|
||||
sls=1
|
||||
end
|
||||
|
||||
subs[i]=line
|
||||
for s=z,#sel do sel[s]=sel[s]+sls end
|
||||
end
|
||||
progress("Blur: DONE")
|
||||
end
|
||||
|
||||
function topline(txt)
|
||||
txt=txt
|
||||
:gsub("(\\t%([^%)]*)\\bord[%d%.]+","%1")
|
||||
:gsub("(\\t%([^%)]*)\\shad[%d%.]+","%1")
|
||||
:gsub("\\t%([^\\]*%)","")
|
||||
if not txt:match("^{[^}]-\\bord") then txt=txt:gsub("^{\\","{\\bord0\\") end
|
||||
txt=txt
|
||||
:gsub("\\bord[%d%.]+","\\bord0")
|
||||
:gsub("(\\r[^}]-)}","%1\\bord0}")
|
||||
txt=txt:gsub("(\\[xy]bord)[%d%.]+","") :gsub("\\3c&H%x+&","")
|
||||
if shadow~="0" then txt=txt:gsub("^({\\[^}]+)}","%1\\shad"..shadow.."}") end
|
||||
txt=txt
|
||||
:gsub("^({\\[^}]-)}","%1\\4a&HFF&}")
|
||||
:gsub("(\\r[^}]-)}","%1\\shad"..shadow.."\\4a&HFF&}")
|
||||
:gsub("\\bord[%d%.%-]+([^}]-)(\\bord[%d%.%-]+)","%1%2")
|
||||
:gsub("\\shad[%d%.%-]+([^}]-)(\\shad[%d%.%-]+)","%1%2")
|
||||
if res.s_top then txt=txt:gsub("\\4a&HFF&","") end
|
||||
txt=txt:gsub("{}","")
|
||||
return txt
|
||||
end
|
||||
|
||||
function borderline(txt)
|
||||
txt=txt:gsub("\\c&H%x+&","")
|
||||
-- transform check
|
||||
if txt:match("^{[^}]-\\t%([^%)]-\\3c") then
|
||||
pretrans=text:match("^{(\\[^}]-)\\t")
|
||||
if not pretrans:match("^{[^}]-\\3c") then txt=txt:gsub("^{\\","{\\c"..soutline.."\\") end
|
||||
end
|
||||
if not txt:match("^{[^}]-\\3c&[^}]-}") then
|
||||
txt=txt:gsub("^({\\[^}]+)}","%1\\c"..soutline.."}")
|
||||
:gsub("(\\r[^}]-)}","%1\\c"..routline.."}")
|
||||
end
|
||||
txt=txt:gsub("(\\3c)(&H%x+&)","%1%2\\c%2")
|
||||
:gsub("(\\r[^}]-)}","%1\\c"..routline.."}")
|
||||
:gsub("(\\r[^}]-\\3c)(&H%x+&)([^}]-)}","%1%2\\c%2%3")
|
||||
:gsub("\\c&H%x+&([^}]-)(\\c&H%x+&)",function(a,b) if not a:match("\\t") then return a..b end end)
|
||||
:gsub("{%*?}","")
|
||||
if res.bbl and not res.double then txt=txt:gsub("\\blur[%d%.]+","\\blur"..res.bblur) end
|
||||
if res.botalpha and txt:match("\\fad%(") then txt=botalfa(txt) end
|
||||
return txt
|
||||
end
|
||||
|
||||
function borderline2(txt)
|
||||
outlinetwo=primary
|
||||
if res.clr then col3=res.c3:gsub("#(%x%x)(%x%x)(%x%x)","&H%3%2%1&") outlinetwo=col3 rimary=col3 end
|
||||
bordertwo=border
|
||||
if res.bsize then bordertwo=res.secbord end
|
||||
-- transform check
|
||||
if txt:match("^{[^}]-\\t%([^%)]-\\bord") then
|
||||
pretrans=text:match("^{(\\[^}]-)\\t")
|
||||
if not pretrans:match("^{[^}]-\\bord") then txt=txt:gsub("^{\\","{\\bord"..border.."\\") end
|
||||
end
|
||||
if not txt:match("^{[^}]-\\bord") then txt=txt:gsub("^{\\","{\\bord"..border.."\\") end
|
||||
txt=txt:gsub("(\\r[^\\}]-)([\\}])","%1\\bord"..rbord.."%2")
|
||||
:gsub("(\\r[^\\}]-)\\bord[%d%.%-]+([^}]-)(\\bord[%d%.%-]+)","%1%2%3")
|
||||
:gsub("(\\bord)([%d%.]+)",function(a,b) if res.bsize then brd=bordertwo else brd=b end return a..b+brd end)
|
||||
:gsub("(\\[xy]bord)([%d%.]+)",function(a,b) return a..b+b end)
|
||||
:gsub("\\3c&H%x+&","")
|
||||
:gsub("^({\\[^}]+)}","%1\\3c"..outlinetwo.."}")
|
||||
:gsub("(\\3c)(&H%x+&)","%1"..outlinetwo)
|
||||
if res.clr then txt=txt:gsub("\\c&H%x+&([^}]-)}","\\c"..rimary.."\\3c"..outlinetwo.."%1}")
|
||||
else txt=txt:gsub("(\\c)(&H%x+&)([^}]-)}","%1%2%3\\3c%2}") end
|
||||
txt=txt:gsub("(\\r[^}]+)}","%1\\3c"..rimary.."}")
|
||||
:gsub("\\c&H%x+&([^}]-)(\\c&H%x+&)",function(a,b) if not a:match("\\t") then return a..b end end)
|
||||
:gsub("\\3c&H%x+&([^}]-)(\\3c&H%x+&)",function(a,b) if not a:match("\\t") then return a..b end end)
|
||||
:gsub("{%*?}","")
|
||||
if res.bbl and res.double then txt=txt:gsub("\\blur[%d%.]+","\\blur"..res.bblur) end
|
||||
if res.botalpha and txt:match("\\fad%(") then txt=botalfa(txt) end
|
||||
return txt
|
||||
end
|
||||
|
||||
function glowlayer(txt,kol,alf)
|
||||
txt=txt:gsub("\\alpha&H(%x%x)&",function(a) if a>al then return "\\alpha&H"..a.."&" else return "\\alpha&H"..al.."&" end end)
|
||||
:gsub("\\"..alf.."a&H(%x%x)&",function(a) if a>al then return "\\"..alf.."a&H"..a.."&" else return "\\"..alf.."a&H"..al.."&" end end)
|
||||
:gsub("(\\blur)[%d%.]*([\\}])","%1"..bl.."%2")
|
||||
:gsub("(\\r[^}]-)}","%1\\alpha&H"..al.."&}")
|
||||
if not txt:match("^{[^}]-\\alpha") then txt=txt:gsub("^({\\[^}]-)}","%1\\alpha&H"..al.."&}") end
|
||||
if res.alfa=="00" then txt=txt:gsub("^({\\[^}]-)\\alpha&H00&","%1") end
|
||||
txt=txt:gsub("{%*?}","")
|
||||
if res.glowcol then
|
||||
if txt:match("^{\\[^}]-\\"..kol.."&") then txt=txt:gsub("\\"..kol.."&H%x+&","\\"..kol..glowc)
|
||||
else txt=txt:gsub("\\"..kol.."&H%x+&","\\"..kol..glowc) txt=txt:gsub("^({\\[^}]-)}","%1\\"..kol..glowc.."}")
|
||||
end
|
||||
end
|
||||
return txt
|
||||
end
|
||||
|
||||
function botalfa(txt)
|
||||
fadin,fadout=txt:match("\\fad%((%d+)%,(%d+)")
|
||||
alfadin=res.alphade alfadout=res.alphade
|
||||
if res.alphade=="max" then alfadin=fadin alfadout=fadout end
|
||||
if fadin==nil or fadout==nil then aegisub.log("\n ERROR: Failed to capture fade times from line:\n "..text) end
|
||||
if fadin~="0" then
|
||||
txt=txt:gsub("^({\\[^}]-)}","%1\\1a&HFF&\\t("..fadin-alfadin..","..fadin..",\\1a&H00&)}")
|
||||
end
|
||||
if fadout~="0" then
|
||||
txt=txt:gsub("^({\\[^}]-)}","%1\\t("..duration-fadout..","..duration-fadout+alfadout..",\\1a&HFF&)}")
|
||||
end
|
||||
return txt
|
||||
end
|
||||
|
||||
function stylinfo(text)
|
||||
startags=text:match("^{\\[^}]-}") or ""
|
||||
startags=startags:gsub("\\t%b()","")
|
||||
|
||||
primary=startags:match("^{[^}]-\\c(&H%x+&)") or sr.color1:gsub("H%x%x","H")
|
||||
soutline=sr.color3:gsub("H%x%x","H")
|
||||
outline=startags:match("^{[^}]-\\3c(&H%x+&)") or soutline
|
||||
border=startags:match("^{[^}]-\\bord([%d%.]+)") or tostring(sr.outline)
|
||||
shadow=startags:match("^{[^}]-\\shad([%d%.]+)") or tostring(sr.shadow)
|
||||
|
||||
if text:match("\\r%a") then
|
||||
rstyle=text:match("\\r([^\\}]+)")
|
||||
reref=stylechk(rstyle)
|
||||
rimary=reref.color1:gsub("H%x%x","H")
|
||||
routline=reref.color3:gsub("H%x%x","H")
|
||||
rbord=tostring(reref.outline)
|
||||
else routline=soutline rimary=primary rbord=border
|
||||
end
|
||||
end
|
||||
|
||||
function preprocess(text)
|
||||
if not text:match("^{\\") then text="{\\blur"..bdef.."}"..text -- default blur if no tags
|
||||
text=text:gsub("(\\r[^}]-)}","%1\\blur"..bdef.."}")
|
||||
end
|
||||
if not text:match("\\blur") then text=text:gsub("^{\\","{\\blur"..bdef.."\\") -- default blur if missing in tags
|
||||
text=text:gsub("(\\r[^}]-)}","%1\\blur"..bdef.."}")
|
||||
end
|
||||
if text:match("\\blur") and not text:match("^{[^}]*blur[^}]*}") then -- add blur if missing in first tag block
|
||||
text=text:gsub("^{\\","{\\blur"..bdef.."\\")
|
||||
end
|
||||
if text:match("^{[^}]-\\t[^}]-}") and not text:match("^{[^}]-\\3c[^}]-\\t") then -- \t workaround
|
||||
text=text:gsub("^{\\","{\\3c"..soutline.."\\")
|
||||
end
|
||||
text=text:gsub("\\1c","\\c")
|
||||
return text
|
||||
end
|
||||
|
||||
function fixfade(subs,sel)
|
||||
for z=#sel,1,-1 do
|
||||
i=sel[z]
|
||||
line=subs[i]
|
||||
text=line.text
|
||||
sr=stylechk(line.style)
|
||||
duration=line.end_time-line.start_time
|
||||
border=tostring(sr.outline)
|
||||
bord=text:match("^{[^}]-\\bord([%d%.]+)")
|
||||
if bord then border=bord end
|
||||
|
||||
if border~="0" and line.text:match("\\fad%(") then
|
||||
text=text:gsub("\\1a&H%x+&","") :gsub("\\t%([^\\%(%)]-%)","")
|
||||
text=botalfa(text)
|
||||
end
|
||||
line.text=text
|
||||
subs[i]=line
|
||||
end
|
||||
end
|
||||
|
||||
function layeraise(subs,sel)
|
||||
for z=#sel,1,-1 do
|
||||
i=sel[z]
|
||||
line=subs[i]
|
||||
if line.layer+res["layer"]>=0 then line.layer=line.layer+res["layer"] else t_error("You're dumb. Layers can't go below 0.",1) end
|
||||
subs[i]=line
|
||||
end
|
||||
end
|
||||
|
||||
function styleget(subs)
|
||||
styles={}
|
||||
for i=1,#subs do
|
||||
if subs[i].class=="style" then
|
||||
table.insert(styles,subs[i])
|
||||
end
|
||||
if subs[i].class=="dialogue" then break end
|
||||
end
|
||||
end
|
||||
|
||||
function stylechk(sn)
|
||||
for s=1,#styles do
|
||||
if sn==styles[s].name then
|
||||
sr=styles[s]
|
||||
if styles[s].name=="Default" then defaref=styles[s] end
|
||||
end
|
||||
end
|
||||
if sr==nil then t_error("Style '"..sn.."' doesn't exist.",1) end
|
||||
return sr
|
||||
end
|
||||
|
||||
function saveconfig()
|
||||
bgconf="Blur & Glow config\n\n"
|
||||
for key,val in ipairs(GUI) do
|
||||
if val.class=="floatedit" or val.class=="dropdown" or val.class=="color" then
|
||||
bgconf=bgconf..val.name..":"..res[val.name].."\n"
|
||||
end
|
||||
if val.class=="checkbox" and val.name~="save" then
|
||||
bgconf=bgconf..val.name..":"..tf(res[val.name]).."\n"
|
||||
end
|
||||
end
|
||||
blurkonfig=ADP("?user").."\\blurandglow.conf"
|
||||
file=io.open(blurkonfig,"w")
|
||||
file:write(bgconf)
|
||||
file:close()
|
||||
ADD({{class="label",label="Config saved to:\n"..blurkonfig}},{"OK"},{close='OK'})
|
||||
end
|
||||
|
||||
function loadconfig()
|
||||
blurkonfig=ADP("?user").."\\blurandglow.conf"
|
||||
file=io.open(blurkonfig)
|
||||
if file~=nil then
|
||||
konf=file:read("*all")
|
||||
io.close(file)
|
||||
for key,val in ipairs(GUI) do
|
||||
if val.class=="floatedit" or val.class=="checkbox" or val.class=="dropdown" or val.class=="color" then
|
||||
if konf:match(val.name) then val.value=detf(konf:match(val.name..":(.-)\n")) end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tf(val)
|
||||
if val==true then ret="true"
|
||||
elseif val==false then ret="false"
|
||||
else ret=val end
|
||||
return ret
|
||||
end
|
||||
|
||||
function detf(txt)
|
||||
if txt=="true" then ret=true
|
||||
elseif txt=="false" then ret=false
|
||||
else ret=txt end
|
||||
return ret
|
||||
end
|
||||
|
||||
function logg(m) m=tf(m) or "nil" aegisub.log("\n "..m) end
|
||||
|
||||
function progress(msg)
|
||||
if aegisub.progress.is_cancelled() then ak() end
|
||||
aegisub.progress.title(msg)
|
||||
end
|
||||
|
||||
function t_error(message,cancel)
|
||||
ADD({{class="label",label=message}},{"OK"},{close='OK'})
|
||||
if cancel then ak() end
|
||||
end
|
||||
|
||||
function blurandglow(subs,sel)
|
||||
ADD=aegisub.dialog.display
|
||||
ADP=aegisub.decode_path
|
||||
ak=aegisub.cancel
|
||||
GUI={
|
||||
--left
|
||||
{x=0,y=0,width=2,class="label",label=" = Blur and Glow version "..script_version.." ="},
|
||||
{x=0,y=1,class="label",label="Glow blur:"},
|
||||
{x=0,y=2,class="label",label="Glow alpha:"},
|
||||
|
||||
{x=1,y=1,width=2,class="floatedit",name="blur",value=3},
|
||||
{x=1,y=2,width=2,class="dropdown",name="alfa",items={"00","20","30","40","50","60","70","80","90","A0","B0","C0","D0","F0"},value="80"},
|
||||
|
||||
{x=0,y=3,class="checkbox",name="glowcol",label="glow c.:",hint="glow colour"},
|
||||
{x=1,y=3,width=2,class="color",name="glc"},
|
||||
|
||||
{x=0,y=4,width=2,class="checkbox",name="s_top",label="keep shadow on top layer"},
|
||||
|
||||
{x=0,y=5,width=5,class="checkbox",name="botalpha",label="fix \\1a for layers with border and fade --> transition:",value=true,
|
||||
hint="uses \\1a&HFF& for bottom layer during fade"},
|
||||
{x=5,y=5,class="dropdown",name="alphade",items={0,45,80,120,160,200,"max"},value=45},
|
||||
{x=6,y=5,width=2,class="label",label="ms"},
|
||||
|
||||
{x=0,y=6,width=4,class="checkbox",name="onlyg",label="only add glow (layers w/ border)"},
|
||||
|
||||
-- right
|
||||
{x=4,y=0,class="checkbox",name="double",label="double border"},
|
||||
{x=5,y=0,width=2,class="checkbox",name="onlyb",label="only add 2nd border"},
|
||||
|
||||
{x=4,y=1,class="checkbox",name="bbl",label="bottom blur:",
|
||||
hint="Blur for bottom layer \n[not the glow layer] \nif different from top layer."},
|
||||
{x=5,y=1,width=2,class="floatedit",name="bblur",value=1},
|
||||
|
||||
{x=4,y=2,class="checkbox",name="bsize",label="2nd b. size:",
|
||||
hint="Size for 2nd border \n[counts from first border out] \nif different from the current border."},
|
||||
{x=5,y=2,width=2,class="floatedit",name="secbord",value=2},
|
||||
|
||||
{x=4,y=3,class="checkbox",name="clr",label="2nd b. colour:",hint="Colour for 2nd border \nif different from primary."},
|
||||
{x=5,y=3,width=2,class="color",name="c3"},
|
||||
|
||||
{x=4,y=4,width=4,class="checkbox",name="s_mid",label="keep shadow on middle layer"},
|
||||
|
||||
{x=4,y=6,class="label",label=" Change layer:"},
|
||||
{x=5,y=6,class="dropdown",name="layer",items={"-5","-4","-3","-2","-1","+1","+2","+3","+4","+5"},value="+1"},
|
||||
|
||||
|
||||
{x=0,y=7,width=2,class="checkbox",name="rep",label="repeat with last settings"},
|
||||
{x=4,y=7,class="checkbox",name="autod",label="auto double",value=true,
|
||||
hint="automatically use double border\nif 2nd colour or 2nd border size is checked"},
|
||||
{x=6,y=6,class="dropdown",name="def",items={"0.3","0.4","0.5","0.6","0.7","0.8","0.9","1"},value="0.6",hint="config: default blur"},
|
||||
{x=5,y=7,width=2,class="checkbox",name="save",label="save configuration"},
|
||||
}
|
||||
loadconfig()
|
||||
buttons={"Blur / Layers","Blur + Glow","Fix fades","Change layer","cancel"}
|
||||
pressed,res=ADD(GUI,buttons,{ok='Blur / Layers',close='cancel'})
|
||||
if pressed=="cancel" then ak() end
|
||||
bdef=res.def
|
||||
if res.onlyg then res.double=false end
|
||||
if res.onlyb then res.double=true end
|
||||
if res.save then saveconfig()
|
||||
else
|
||||
if res.rep then res=lastres end
|
||||
styleget(subs)
|
||||
if pressed=="Blur / Layers" then layerblur(subs,sel) end
|
||||
if pressed=="Blur + Glow" then sel=glow(subs,sel) end
|
||||
if pressed=="Fix fades" then fixfade(subs,sel) end
|
||||
if pressed=="Change layer" then layeraise(subs,sel) end
|
||||
end
|
||||
if res.rep==false then lastres=res end
|
||||
aegisub.set_undo_point(script_name)
|
||||
return sel
|
||||
end
|
||||
|
||||
if haveDepCtrl then depRec:registerMacro(blurandglow) else aegisub.register_macro(script_name,script_description,blurandglow) end
|
148
automation/autoload/ua.ChangeCase.lua
Normal file
@ -0,0 +1,148 @@
|
||||
script_name="Change Case"
|
||||
script_description="Capitalises text or makes it lowercase / uppercase"
|
||||
script_author="unanimated"
|
||||
script_version="3.0"
|
||||
script_namespace="ua.ChangeCase"
|
||||
|
||||
local haveDepCtrl,DependencyControl,depRec=pcall(require,"l0.DependencyControl")
|
||||
if haveDepCtrl then
|
||||
script_version="3.0.0"
|
||||
depRec=DependencyControl{feed="https://raw.githubusercontent.com/TypesettingTools/unanimated-Aegisub-Scripts/master/DependencyControl.json"}
|
||||
end
|
||||
|
||||
re=require'aegisub.re'
|
||||
unicode=require'aegisub.unicode'
|
||||
|
||||
function case(subs,sel)
|
||||
for z,i in ipairs(sel) do
|
||||
line=subs[i]
|
||||
t=line.text
|
||||
if P=="lowercase" then t=lowercase(t) end
|
||||
if P=="UPPERCASE" then t=uppercase(t) end
|
||||
if P=="Lines" then t=capitalines(t) end
|
||||
if P=="Sentences" then
|
||||
if res.mod then res.mod=false t=lowercase(t) res.mod=true end
|
||||
t=sentences(t)
|
||||
end
|
||||
if P=="Words" then
|
||||
if not res.mod then t=lowercase(t) end
|
||||
t=capitalise(t)
|
||||
end
|
||||
line.text=t
|
||||
subs[i]=line
|
||||
end
|
||||
end
|
||||
|
||||
function lowercase(t)
|
||||
t=t
|
||||
:gsub("\\[Nnh]","{%1}")
|
||||
:gsub("^([^{]*)",function(l)
|
||||
if res.mod then l=re.sub(l,[[\b(\u\u+'?\u*)]],function(u) return ulower(u) end) return l
|
||||
else return ulower(l) end end)
|
||||
:gsub("}([^{]*)",function(l)
|
||||
if res.mod then l=re.sub(l,[[\b(\u\u+'?\u*)]],function(u) return ulower(u) end) return "}"..l
|
||||
else return "}"..ulower(l) end end)
|
||||
:gsub("{(\\[Nnh])}","%1")
|
||||
return t
|
||||
end
|
||||
|
||||
function uppercase(t)
|
||||
t=t
|
||||
:gsub("\\[Nnh]","{%1}")
|
||||
:gsub("^([^{]*)",function(u) return uupper(u) end)
|
||||
:gsub("}([^{]*)",function(u) return "}"..uupper(u) end)
|
||||
:gsub("{(\\[Nnh])}","%1")
|
||||
return t
|
||||
end
|
||||
|
||||
function capitalines(t)
|
||||
t=re.sub(t,[[^(["']?\l)]],function(l) return uupper(l) end)
|
||||
t=re.sub(t,[[^\{[^}]*\}(["']?\l)]],function(l) return uupper(l) end)
|
||||
if not res.mod then
|
||||
t=t:gsub(" i([' %?!%.,])"," I%1"):gsub("\\Ni([' ])","\\NI%1")
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
function sentences(t)
|
||||
somewords={"English","Japanese","American","British","German","French","Spanish","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday","January","February","April","June","July","August","September","October","November","December"}
|
||||
hnrfx={"%-san","%-kun","%-chan","%-sama","%-dono","%-se[nm]pai","%-on%a+an"}
|
||||
t=re.sub(t,[[^(["']?\l)]],function(l) return uupper(l) end)
|
||||
t=re.sub(t,[[^\{[^}]*\}(["']?\l)]],function(l) return uupper(l) end)
|
||||
t=re.sub(t,[[[\.\?!](\s|\s\\N|\\N)["']?(\l)]],function(l) return uupper(l) end)
|
||||
t=t
|
||||
:gsub(" i([' %?!%.,])"," I%1")
|
||||
:gsub("\\Ni([' ])","\\NI%1")
|
||||
:gsub(" m(arch %d)"," M%1")
|
||||
:gsub(" a(pril %d)"," A%1")
|
||||
for l=1,#somewords do t=t:gsub(somewords[l]:lower(),somewords[l]) end
|
||||
for h=1,#hnrfx do
|
||||
t=t:gsub("([ %p]%l)(%l*"..hnrfx[h]..")",function(h,f) return h:upper()..f end)
|
||||
t=t:gsub("(\\N%l)(%l*"..hnrfx[h]..")",function(h,f) return h:upper()..f end)
|
||||
end
|
||||
t=re.sub(t,"\\b(of|in|from|\\d+st|\\d+nd|\\d+rd|\\d+th) m(arch|ay)\\b","\\1 M\\2")
|
||||
t=re.sub(t,"\\bm(r|rs|s)\\.","M\\1.")
|
||||
t=re.sub(t,"\\bdr\\.","Dr.")
|
||||
return t
|
||||
end
|
||||
|
||||
function capitalise(txt)
|
||||
word={"A","About","Above","Across","After","Against","Along","Among","Amongst","An","And","Around","As","At","Before","Behind","Below","Beneath","Beside","Between","Beyond","But","By","Despite","During","Except","For","From","In","Inside","Into","Near","Nor","Of","On","Onto","Or","Over","Per","Sans","Since","Than","The","Through","Throughout","Till","To","Toward","Towards","Under","Underneath","Unlike","Until","Unto","Upon","Versus","Via","With","Within","Without","According to","Ahead of","Apart from","Aside from","Because of","Inside of","Instead of","Next to","Owing to","Prior to","Rather than","Regardless of","Such as","Thanks to","Up to","and Yet"}
|
||||
onore={"%-San","%-Kun","%-Chan","%-Sama","%-Dono","%-Se[nm]pai","%-On%a+an"}
|
||||
nokom={"^( ?)([^{]*)","(})([^{]*)"}
|
||||
for n=1,2 do
|
||||
txt=txt:gsub(nokom[n],function(no_t,t)
|
||||
t=t:gsub("\\[Nnh]","{%1}")
|
||||
t=re.sub(t,[[\b\l]],function(l) return uupper(l) end)
|
||||
t=re.sub(t,[[[I\l]'(\u)]],function(l) return ulower(l) end)
|
||||
|
||||
for r=1,#word do w=word[r]
|
||||
t=t
|
||||
:gsub("^ "..w.." "," "..w:lower().." ")
|
||||
:gsub("([^%.:%?!]) "..w.." ","%1 "..w:lower().." ")
|
||||
:gsub("([^%.:%?!]) (%b{})"..w.." ","%1 %2"..w:lower().." ")
|
||||
:gsub("([^%.:%?!]) (%*Large_break%* ?)"..w.." ","%1 %2"..w:lower().." ")
|
||||
end
|
||||
|
||||
-- Roman numbers (this may mismatch some legit words - sometimes there just are 2 options and it's a guess)
|
||||
t=t
|
||||
:gsub("$","#")
|
||||
:gsub("(%s?)([IVXLCDM])([ivxlcdm]+)([%s%p#])",function(s,r,m,e) return s..r..m:upper()..e end)
|
||||
:gsub("([DLM])ID","%1id")
|
||||
:gsub("DIM","Dim")
|
||||
:gsub("MIX","Mix")
|
||||
:gsub("Ok([%s%p#])","OK%1")
|
||||
for h=1,#onore do
|
||||
t=t:gsub(onore[h].."([%s%p#])",onore[h]:lower().."%1")
|
||||
end
|
||||
t=t
|
||||
:gsub("#$","")
|
||||
:gsub("{(\\[Nnh])}","%1")
|
||||
return no_t..t end)
|
||||
end
|
||||
return txt
|
||||
end
|
||||
|
||||
ulower=unicode.to_lower_case
|
||||
uupper=unicode.to_upper_case
|
||||
|
||||
function logg(m) m=m or "nil" aegisub.log("\n "..m) end
|
||||
|
||||
function capital(subs,sel)
|
||||
GUI={
|
||||
{x=1,y=0,class="label",label="Words - Capitalise Words Like in Titles"},
|
||||
{x=1,y=1,class="label",label=" Lines - Capitalise first word in selected lines"},
|
||||
{x=1,y=2,class="label",label=" Sentences - Capitalise first word in each sentence"},
|
||||
{x=1,y=3,class="label",label=" Lowercase - make text in selected lines lowercase"},
|
||||
{x=1,y=4,class="label",label=" Uppercase - MAKE TEXT IN SELECTED LINES UPPERCASE"},
|
||||
{x=2,y=5,class="label",label=script_name.." v "..script_version},
|
||||
{x=1,y=5,class="checkbox",name="mod",label="mod",hint="Words - leave uppercase words\nLines - don't capitalize 'i'\nSentences - run lowercase first\nlowercase - only for uppercase words"},
|
||||
}
|
||||
P,res=aegisub.dialog.display(GUI,{"Words","Lines","Sentences","lowercase","UPPERCASE","Cancel"},{ok='Words',close='Cancel'})
|
||||
if P=="Cancel" then aegisub.cancel() end
|
||||
case(subs,sel)
|
||||
aegisub.set_undo_point(script_name)
|
||||
return sel
|
||||
end
|
||||
|
||||
if haveDepCtrl then depRec:registerMacro(capital) else aegisub.register_macro(script_name,script_description,capital) end
|
1422
automation/autoload/ua.Colorize.lua
Normal file
116
automation/autoload/ua.Cycles.lua
Normal file
@ -0,0 +1,116 @@
|
||||
-- Manual: http://unanimated.hostfree.pw/ts/scripts-manuals.htm#cycle
|
||||
|
||||
script_name="Cycles"
|
||||
script_description="Cycles blur, border, shadow, alpha, alignment, font spacing"
|
||||
script_author="unanimated"
|
||||
script_version="2.0"
|
||||
script_namespace="ua.Cycles"
|
||||
|
||||
local haveDepCtrl,DependencyControl,depRec=pcall(require,"l0.DependencyControl")
|
||||
if haveDepCtrl then
|
||||
script_version="2.0.0"
|
||||
depRec=DependencyControl{feed="https://raw.githubusercontent.com/unanimated/luaegisub/master/DependencyControl.json"}
|
||||
end
|
||||
|
||||
-- SETTINGS - You can change these sequences
|
||||
blur_sequence={"0.6","0.8","1","1.2","1.5","2","2.5","3","4","5","6","8","10","0.4","0.5"}
|
||||
bord_sequence={"0","1","1.5","2","2.5","3","4","5","6","7","8","9","10","11","12","15","20"}
|
||||
shad_sequence={"0","1","1.5","2","2.5","3","4","5","6","7","8","9","10","11","12"}
|
||||
alpha_sequence={"FF","00","10","30","60","80","A0","C0","E0"}
|
||||
align_sequence={"1","2","3","4","5","6","7","8","9"}
|
||||
fsp_sequence={"0","1","2","3","4","5","6","7","8","10","12","15","20","30"}
|
||||
|
||||
--[[ Adding more tags
|
||||
You could make this also work for the following tags: frz, frx, fry, fax, fay, fs, fscx, fscy, be, xbord, xshad, ybord, yshad
|
||||
by doing 3 things:
|
||||
1. add a new sequence to the settings above for the tag you want to add
|
||||
2. add a function below here based on what the others look like (it's adjusted for negative values too)
|
||||
3. add "aegisub.register_macro("Cycles/YOUR_SCRIPT_NAME","Cycles WHATEVER_YOU_CHOOSE",FUNCTION_NAME_HERE)" at the end of the script
|
||||
If you at least roughly understand the basics, this should be easy. The main cycle function remains the same for all tags.
|
||||
Should you want to add other tags with different value patterns, check the existing exceptions for alpha in the cycle function.]]
|
||||
|
||||
function blur(subs,sel) cycle(subs,sel,"blur",blur_sequence) end
|
||||
function bord(subs,sel) cycle(subs,sel,"bord",bord_sequence) end
|
||||
function shad(subs,sel) cycle(subs,sel,"shad",shad_sequence) end
|
||||
function alph(subs,sel) cycle(subs,sel,"alpha",alpha_sequence) end
|
||||
function algn(subs,sel) cycle(subs,sel,"an",align_sequence) end
|
||||
function fsp(subs,sel) cycle(subs,sel,"fsp",fsp_sequence) end
|
||||
|
||||
function cycle(subs,sel,tag,sequence)
|
||||
if tag=="alpha" then base=16 else base=10 end
|
||||
for z,i in ipairs(sel) do
|
||||
line=subs[i]
|
||||
text=line.text
|
||||
local back
|
||||
if line.comment or text:match'{switch}$' then back=true end
|
||||
text=text:gsub("\\t(%b())",function(t) return "\\t"..t:gsub("\\","|") end)
|
||||
|
||||
if tag=="alpha" then val1=text:match("^{[^}]-\\alpha&H(%x%x)&") else val1=text:match("^{[^}]-\\"..tag.."(%-?[%d%.]+)") end
|
||||
if val1 then
|
||||
for n=1,#sequence do
|
||||
N=n+1
|
||||
if back then N=n-1 end
|
||||
if N==0 then N=#sequence end
|
||||
if val1==sequence[n] then val2=sequence[N] or sequence[1] break end
|
||||
end
|
||||
if val2==nil then
|
||||
for n=1,#sequence do
|
||||
if n>1 or sequence[1]~="FF" then
|
||||
local N=n
|
||||
if back then N=n-1 end
|
||||
if N==0 then N=#sequence end
|
||||
if tonumber(val1,base)<tonumber(sequence[n],base) then val2=sequence[N] break end
|
||||
end
|
||||
end
|
||||
end
|
||||
if val2==nil then if back then val2=sequence[#sequence] else val2=sequence[1] end end
|
||||
if tag=="alpha" then
|
||||
text=text:gsub("^({[^}]-\\alpha&H)%x%x","%1"..val2)
|
||||
else
|
||||
text=text:gsub("^({[^}]-\\"..tag..")%-?[%d%.]+","%1"..val2)
|
||||
end
|
||||
val2=nil
|
||||
else
|
||||
text="{\\"..tag..sequence[1].."}"..text
|
||||
text=text:gsub("alpha(%x%x)}","alpha&H%1&}")
|
||||
:gsub("{(\\.-)}{\\","{%1\\")
|
||||
end
|
||||
|
||||
text=text:gsub("{\\[^}]-}",function(t) return t:gsub("|","\\") end)
|
||||
line.text=text
|
||||
subs[i]=line
|
||||
end
|
||||
end
|
||||
|
||||
function switch(subs,sel)
|
||||
for z,i in ipairs(sel) do
|
||||
l=subs[i]
|
||||
t=l.text
|
||||
t=t.."{switch}"
|
||||
t=t:gsub("{switch}{switch}$","")
|
||||
l.text=t
|
||||
subs[i]=l
|
||||
end
|
||||
end
|
||||
|
||||
function logg(m) m=m or "nil" aegisub.log("\n "..m) end
|
||||
|
||||
if haveDepCtrl then
|
||||
depRec:registerMacros({
|
||||
{"Cycles/Blur Cycle","Cycles Blur",blur},
|
||||
{"Cycles/Border Cycle","Cycles Border",bord},
|
||||
{"Cycles/Shadow Cycle","Cycles Shadow",shad},
|
||||
{"Cycles/Alpha Cycle","Cycles Alpha",alph},
|
||||
{"Cycles/Alignment Cycle","Cycles Alignment",algn},
|
||||
{"Cycles/FontSpacing Cycle","Cycles Font Spacing",fsp},
|
||||
{"Cycles/Switch","Switches sequence direction",switch},
|
||||
},false)
|
||||
else
|
||||
aegisub.register_macro("Cycles/Blur Cycle","Cycles Blur",blur)
|
||||
aegisub.register_macro("Cycles/Border Cycle","Cycles Border",bord)
|
||||
aegisub.register_macro("Cycles/Shadow Cycle","Cycles Shadow",shad)
|
||||
aegisub.register_macro("Cycles/Alpha Cycle","Cycles Alpha",alph)
|
||||
aegisub.register_macro("Cycles/Alignment Cycle","Cycles Alignment",algn)
|
||||
aegisub.register_macro("Cycles/FontSpacing Cycle","Cycles Font Spacing",fsp)
|
||||
aegisub.register_macro("Cycles/Switch","Switches sequence direction",switch)
|
||||
end
|
1407
automation/autoload/ua.FadeWorks.lua
Normal file
2064
automation/autoload/ua.HYDRA.lua
Normal file
758
automation/autoload/ua.ScriptCleanup.lua
Normal file
@ -0,0 +1,758 @@
|
||||
-- Disclaimer: RTFM! - http://unanimated.hostfree.pw/ts/scripts-manuals.htm#cleanup
|
||||
|
||||
script_name="Script Cleanup"
|
||||
script_description="Garbage disposal and elimination of incriminating evidence"
|
||||
script_author="unanimated"
|
||||
script_version="5.0"
|
||||
script_namespace="ua.ScriptCleanup"
|
||||
|
||||
local haveDepCtrl,DependencyControl,depRec=pcall(require,"l0.DependencyControl")
|
||||
if haveDepCtrl then
|
||||
script_version="5.0.0"
|
||||
depRec=DependencyControl{feed="https://raw.githubusercontent.com/unanimated/luaegisub/master/DependencyControl.json"}
|
||||
end
|
||||
|
||||
dont_delete_empty_tags=false -- option to not delete {}
|
||||
|
||||
re=require'aegisub.re'
|
||||
|
||||
function cleanlines(subs,sel)
|
||||
if res.all then
|
||||
for k,v in ipairs(GUI) do
|
||||
if v.x==0 then res[v.name]=true end
|
||||
end
|
||||
end
|
||||
for z,i in ipairs(sel) do
|
||||
progress("Processing line: "..z.."/"..#sel)
|
||||
prog=math.floor(z/#sel*100)
|
||||
aegisub.progress.set(prog)
|
||||
line=subs[i]
|
||||
text=line.text
|
||||
stl=line.style
|
||||
|
||||
if res.nots and not res.nocom then text=text:gsub("{TS[^}]*} *","") end
|
||||
|
||||
if res.nocom then
|
||||
text=text:gsub("{[^\\}]-}","")
|
||||
:gsub("{[^\\}]-\\N[^\\}]-}","")
|
||||
:gsub("^({[^}]-}) *","%1")
|
||||
:gsub(" *$","")
|
||||
end
|
||||
|
||||
if res.clear_a then line.actor="" end
|
||||
if res.clear_e then line.effect="" end
|
||||
|
||||
if res.layers and line.layer<5 then
|
||||
if stl:match("Defa") or stl:match("Alt") or stl:match("Main") then line.layer=line.layer+5 end
|
||||
end
|
||||
|
||||
if res.cleantag and text:match("{[*>]?\\") then
|
||||
txt2=text
|
||||
text=text:gsub("{\\\\k0}",""):gsub(">\\","\\"):gsub("{(\\[^}]-)} *\\N *{(\\[^}]-)}","\\N{%1%2}")
|
||||
repeat text,r=text:gsub("{(\\[^}]-)}{(\\[^}]-)}","{%1%2}") until r==0
|
||||
text=text:gsub("({\\[^}]-){(\\[^}]-})","%1%2"):gsub("{.-\\r","{\\r"):gsub("^{\\r([\\}])","{%1")
|
||||
:gsub("\\fad%(0,0%)",""):gsub(ATAG.."$",""):gsub("^({\\[^}]-)\\frx0\\fry0","%1"):gsub("\\%a+%(%)","")
|
||||
text=text:gsub(ATAG,function(tgs)
|
||||
tgs2=tgs
|
||||
:gsub("\\+([\\}])","%1")
|
||||
:gsub("(\\[^\\})]+)",function(a) if not a:match'clip' and not a:match'\\fn' and not a:match'\\r' then a=a:gsub(' ','') end return a end)
|
||||
:gsub("(\\%a+)([%d%-]+%.%d+)",function(a,b) if not a:match("\\fn") then b=rnd2dec(b) end return a..b end)
|
||||
:gsub("(\\%a+)%(([%d%.%-]+),([%d%.%-]+)%)",function(a,b,c) b=rnd2dec(b) c=rnd2dec(c) return a.."("..b..","..c..")" end)
|
||||
:gsub("(\\%a+)%(([%d%.%-]+),([%d%.%-]+),([%d%.%-]+),([%d%.%-]+)",function(a,b,c,d,e)
|
||||
return a.."("..rnd2dec(b)..","..rnd2dec(c)..","..rnd2dec(d)..","..rnd2dec(e) end)
|
||||
tgs2=duplikill(tgs2)
|
||||
tgs2=extrakill(tgs2)
|
||||
return tgs2
|
||||
end)
|
||||
if txt2~=text then kleen=kleen+1 end
|
||||
end
|
||||
|
||||
if res.overlap then
|
||||
if line.comment==false and stl:match("Defa") then
|
||||
start=line.start_time
|
||||
endt=line.end_time
|
||||
if i<#subs then nextline=subs[i+1] nextart=nextline.start_time end
|
||||
prevline=subs[i-1]
|
||||
prevstart=prevline.start_time
|
||||
prevend=prevline.end_time
|
||||
dur=line.end_time-line.start_time
|
||||
ms2fr=aegisub.frame_from_ms
|
||||
fr2ms=aegisub.ms_from_frame
|
||||
keyframes=aegisub.keyframes()
|
||||
startf=ms2fr(start)
|
||||
endf=ms2fr(endt)
|
||||
prevendf=ms2fr(prevend)
|
||||
nextartf=ms2fr(nextart)
|
||||
|
||||
-- start gaps/overlaps
|
||||
if prevline.class=="dialogue" and prevline.style:match("Defa") and dur>50 then
|
||||
-- get keyframes
|
||||
kfst=0 kfprev=0
|
||||
for k,kf in ipairs(keyframes) do
|
||||
if kf==startf then kfst=1 end
|
||||
if kf==prevendf then kfprev=1 end
|
||||
end
|
||||
-- start overlap
|
||||
if start<prevend and prevend-start<=50 then
|
||||
if kfst==0 or kfprev==1 then nstart=prevend end
|
||||
end
|
||||
-- start gap
|
||||
if start>prevend and start-prevend<=50 then
|
||||
if kfst==0 and kfprev==1 then nstart=prevend end
|
||||
end
|
||||
end
|
||||
-- end gaps/overlaps
|
||||
if i<#subs and nextline.style:match("Defa") and dur>50 then
|
||||
--get keyframes
|
||||
kfend=0 kfnext=0
|
||||
for k,kf in ipairs(keyframes) do
|
||||
if kf==endf then kfend=1 end
|
||||
if kf==nextartf then kfnext=1 end
|
||||
end
|
||||
-- end overlap
|
||||
if endt>nextart and endt-nextart<=50 then
|
||||
if kfnext==1 and kfend==0 then nendt=nextart end
|
||||
end
|
||||
-- end gap
|
||||
if endt<nextart and nextart-endt<=50 then
|
||||
if kfend==0 or kfnext==1 then nendt=nextart end
|
||||
end
|
||||
end
|
||||
end
|
||||
if nstart then line.start_time=nstart end
|
||||
if nendt then line.end_time=nendt end
|
||||
nstart=nil nendt=nil
|
||||
end
|
||||
|
||||
if res.spaces then text=text:gsub(" +"," ") :gsub(" *$","") :gsub("^({\\[^}]-}) *","%1") end
|
||||
|
||||
if res.nobreak2 then text=text:gsub("\\[Nn]","")
|
||||
elseif res.nobreak then
|
||||
text=text
|
||||
:gsub(" *{\\i0}\\N{\\i1} *"," ")
|
||||
:gsub("%*","_ast_")
|
||||
:gsub("\\[Nn]","*")
|
||||
:gsub(" *%*+ *"," ")
|
||||
:gsub("_ast_","*")
|
||||
end
|
||||
|
||||
if res.hspace then text=text:gsub("\\h","") end
|
||||
if res.notag then text=text:gsub(ATAG,"") end
|
||||
if res.allcol then text=text:gsub("\\[1234]?c[^\\})]*","") end
|
||||
if res.alpha14 then text=text:gsub("\\[1234]a[^\\})]*","")
|
||||
elseif res.allphas then text=text:gsub("\\[1234]a[^\\})]*","") :gsub("\\alpha[^\\})]*","") end
|
||||
if res.xyshad then text=text:gsub("\\[xy]shad[^\\})]*","")
|
||||
elseif res.allshad then text=text:gsub("\\[xy]?shad[^\\})]*","") end
|
||||
if res.xyrot then text=text:gsub("\\fr[xy][^\\})]*","")
|
||||
elseif res.allrot then text=text:gsub("\\fr[^\\})]*","") end
|
||||
if res.allpers then text=text:gsub("\\f[ar][xyz][^\\})]*","") :gsub("\\org%b()","") end
|
||||
if res.scales then text=text:gsub("\\fsc[xy][^\\})]*","")
|
||||
elseif res.allsize then text=text:gsub("\\fs[%d.]+","") :gsub("\\fs([\\}%)])","%1") :gsub("\\fsc[xy][^\\})]*","") end
|
||||
if res.parent2 then text=text:gsub("(\\%a%a+)(%b())",function(a,b) if a=='\\pos' then return a..b else return "" end end)
|
||||
elseif res.parent then text=text:gsub("\\%a%a+%b()","") end
|
||||
if res.ctrans then text=text:gsub(ATAG,function(tg) return cleantr(tg) end) end
|
||||
if res.inline2 then repeat text,r=text:gsub("(.)"..ATAG.."(.-{%*?\\)","%1%2") until r==0
|
||||
elseif res.inline then text=text:gsub("(.)"..ATAG,"%1") end
|
||||
|
||||
if res.alphacol then
|
||||
text=text
|
||||
:gsub("alpha&(%x%x)&","alpha&H%1&")
|
||||
:gsub("alpha&?H?(%x%x)&?([\\}])","alpha&H%1&%2")
|
||||
:gsub("alpha&H0&","alpha&H00&")
|
||||
:gsub("alpha&H(%x%x)%x*&","alpha&H%1&")
|
||||
:gsub("(\\[1234]a)&(%x%x)&","%1&H%2&")
|
||||
:gsub("(\\[1234]a)(%x%x)([\\}])","%1&H%2&%3")
|
||||
:gsub("(\\[1234]?c&)(%x%x%x%x%x%x)&","%1H%2&")
|
||||
:gsub("(\\[1234]?c&H%x%x%x%x%x%x)([^&])","%1&%2")
|
||||
:gsub("(\\i?clip%([^%)]-) ?([\\}])","%1)%2")
|
||||
:gsub("(\\t%([^%)]-\\i?clip%([^%)]-%))([\\}])","%1)%2")
|
||||
:gsub("(fad%([%d,]+)([\\}])","%1)%2")
|
||||
:gsub("([1234]?[ac])H&(%x+)","%1&H%2")
|
||||
:gsub("([1234]?c&H)00(%x%x%x%x%x%x)","%1%2")
|
||||
end
|
||||
|
||||
text=text:gsub("^ *","") :gsub("\\t%([^\\%)]-%)","") :gsub("{%*}","")
|
||||
if not dont_delete_empty_tags then text=text:gsub("{}","") end
|
||||
if line.text~=text then chng=chng+1 end
|
||||
line.text=text
|
||||
subs[i]=line
|
||||
end
|
||||
if res.info then
|
||||
infotxt="Lines with modified Text field: "..chng
|
||||
if res.cleantag then infotxt=infotxt.."\nChanges from Clean Tags: "..kleen end
|
||||
P,rez=ADD({{class="label",label=infotxt}},{"OK"},{close='OK'})
|
||||
end
|
||||
return sel
|
||||
end
|
||||
|
||||
-- delete commented lines from selected lines
|
||||
function nocom_line(subs,sel)
|
||||
progress("Deleting commented lines")
|
||||
ncl_sel={}
|
||||
for s=#sel,1,-1 do
|
||||
line=subs[sel[s]]
|
||||
if line.comment then
|
||||
for z,i in ipairs(ncl_sel) do ncl_sel[z]=i-1 end
|
||||
subs.delete(sel[s])
|
||||
else
|
||||
table.insert(ncl_sel,sel[s])
|
||||
end
|
||||
end
|
||||
return ncl_sel
|
||||
end
|
||||
|
||||
-- delete empty lines
|
||||
function noempty(subs,sel)
|
||||
progress("Deleting empty lines")
|
||||
noe_sel={}
|
||||
for s=#sel,1,-1 do
|
||||
line=subs[sel[s]]
|
||||
if line.text=="" then
|
||||
for z,i in ipairs(noe_sel) do noe_sel[z]=i-1 end
|
||||
subs.delete(sel[s])
|
||||
else
|
||||
table.insert(noe_sel,sel[s])
|
||||
end
|
||||
end
|
||||
return noe_sel
|
||||
end
|
||||
|
||||
-- delete commented or empty lines
|
||||
function noemptycom(subs,sel)
|
||||
progress("Deleting commented/empty lines")
|
||||
noecom_sel={}
|
||||
for s=#sel,1,-1 do
|
||||
line=subs[sel[s]]
|
||||
if line.comment or line.text=="" then
|
||||
for z,i in ipairs(noecom_sel) do noecom_sel[z]=i-1 end
|
||||
subs.delete(sel[s])
|
||||
else
|
||||
table.insert(noecom_sel,sel[s])
|
||||
end
|
||||
end
|
||||
return noecom_sel
|
||||
end
|
||||
|
||||
-- delete unused styles
|
||||
function nostyle(subs,sel)
|
||||
stylist=",,"
|
||||
for i=#subs,1,-1 do
|
||||
if subs[i].class=="dialogue" then
|
||||
line=subs[i]
|
||||
text=line.text
|
||||
st2=text:match("\\r([^\\}]*)")
|
||||
st=line.style
|
||||
if not stylist:match(","..esc(st)..",") then stylist=stylist..st..",," end
|
||||
if st2 and st2~="" and not stylist:match(","..esc(st2)..",") then stylist=stylist..st2..",," end
|
||||
end
|
||||
if subs[i].class=="style" then
|
||||
style=subs[i]
|
||||
if res.nostyle2 and style.name:match("Defa") or res.nostyle2 and style.name:match("Alt") then nodel=1 else nodel=0 end
|
||||
if not stylist:match(","..esc(style.name)..",") and nodel==0 then
|
||||
subs.delete(i)
|
||||
logg("\n Deleted style: "..style.name)
|
||||
for s=1,#sel do sel[s]=sel[s]-1 end
|
||||
end
|
||||
end
|
||||
end
|
||||
return sel
|
||||
end
|
||||
|
||||
|
||||
-- kill everything
|
||||
function killemall(subs,sel)
|
||||
if res.inverse then
|
||||
for k,v in ipairs(GUI) do
|
||||
if v.x>4 and v.y>0 and v.name~="onlyt" then res[v.name]=not res[v.name] end
|
||||
end
|
||||
end
|
||||
for z,i in ipairs(sel) do
|
||||
progress("Processing line: "..z.."/"..#sel)
|
||||
line=subs[i]
|
||||
text=line.text
|
||||
if res.onlyt then res.trans=false
|
||||
text=text:gsub(ATAG,function(t) return t:gsub("\\","|") end)
|
||||
:gsub("|t(%b())",function(t) return "\\t"..t:gsub("|","\\") end)
|
||||
end
|
||||
tags=text:match(STAG) or ""
|
||||
inline=text:gsub(STAG,"")
|
||||
if res.skill and res.ikill then trgt=text tg=3
|
||||
elseif res.ikill then trgt=inline tg=2
|
||||
else trgt=tags tg=1 end
|
||||
if res.border then trgt=killtag("[xy]?bord",trgt) end
|
||||
if res.shadow then trgt=killtag("shad",trgt) end
|
||||
if res.blur then trgt=killtag("blur",trgt) end
|
||||
if res.bee then trgt=killtag("be",trgt) end
|
||||
if res.fsize then trgt=killtag("fs",trgt) end
|
||||
if res.fspace then trgt=killtag("fsp",trgt) end
|
||||
if res.scalex then trgt=killtag("fscx",trgt) end
|
||||
if res.scaley then trgt=killtag("fscy",trgt) end
|
||||
if res.fade then trgt=trgt:gsub("\\fade?%b()","") end
|
||||
if res.posi then trgt=trgt:gsub("\\pos%b()","") end
|
||||
if res.move then trgt=trgt:gsub("\\move%b()","") end
|
||||
if res.org then trgt=trgt:gsub("\\org%b()","") end
|
||||
if res.color1 then trgt=killctag("1?c",trgt) end
|
||||
if res.color2 then trgt=killctag("2c",trgt) end
|
||||
if res.color3 then trgt=killctag("3c",trgt) end
|
||||
if res.color4 then trgt=killctag("4c",trgt) end
|
||||
if res.alfa1 then trgt=killctag("1a",trgt) end
|
||||
if res.alfa2 then trgt=killctag("2a",trgt) end
|
||||
if res.alfa3 then trgt=killctag("3a",trgt) end
|
||||
if res.alfa4 then trgt=killctag("4a",trgt) end
|
||||
if res.alpha then trgt=killctag("alpha",trgt) end
|
||||
if res.clip then trgt=trgt:gsub("\\i?clip%b()","") end
|
||||
if res.fname then trgt=trgt:gsub("\\fn[^\\}]+","") end
|
||||
if res.frz then trgt=killtag("frz",trgt) end
|
||||
if res.frx then trgt=killtag("frx",trgt) end
|
||||
if res.fry then trgt=killtag("fry",trgt) end
|
||||
if res.fax then trgt=killtag("fax",trgt) end
|
||||
if res.fay then trgt=killtag("fay",trgt) end
|
||||
if res.anna then trgt=killtag("an",trgt) end
|
||||
if res.align then trgt=killtag("a",trgt) end
|
||||
if res.wrap then trgt=killtag("q",trgt) end
|
||||
if res["return"] then trgt=trgt:gsub("\\r.+([\\}])","%1") end
|
||||
if res.kara then trgt=trgt:gsub("\\[Kk][fo]?[%d%.]+([\\}])","%1") end
|
||||
if res.ital then repeat trgt,r=trgt:gsub("\\i[01]?([\\}])","%1") until r==0 end
|
||||
if res.bold then repeat trgt,r=trgt:gsub("\\b[01]?([\\}])","%1") until r==0 end
|
||||
if res.under then repeat trgt,r=trgt:gsub("\\u[01]?([\\}])","%1") until r==0 end
|
||||
if res.stri then repeat trgt,r=trgt:gsub("\\s[01]?([\\}])","%1") until r==0 end
|
||||
if res.trans then trgt=trgt:gsub("\\t%b()","") end
|
||||
trgt=trgt:gsub("\\t%([%d%.,]*%)","") :gsub("{%**}","")
|
||||
if tg==1 then tags=trgt elseif tg==2 then inline=trgt elseif tg==3 then text=trgt end
|
||||
if trgt~=text then text=tags..inline end
|
||||
if res.onlyt then text=text:gsub("{%*?|[^}]-}",function(t) return t:gsub("|","\\") end) end
|
||||
line.text=text
|
||||
subs[i]=line
|
||||
end
|
||||
end
|
||||
|
||||
function killtag(tag,t) repeat t,r=t:gsub("\\"..tag.."[%d%.%-]-([\\}])","%1") until r==0 return t end
|
||||
function killctag(tag,t) t=t:gsub("\\"..tag.."&H%x+&","") repeat t,r=t:gsub("\\"..tag.."([\\}])","%1") until r==0 return t end
|
||||
|
||||
|
||||
-- hide tags
|
||||
function hide_tags(subs,sel)
|
||||
hide=true
|
||||
if res.inverse then hide=nil end
|
||||
local numbers="\\i\\b\\u\\s\\q\\a\\be\\blur\\bord\\fs\\fscx\\fscy\\shad\\an\\frz\\fry\\frx\\fsp\\fax\\fay\\"
|
||||
local alphacol="\\1a\\2a\\3a\\4a\\1c\\2c\\3c\\4c\\alpha\\"
|
||||
local parent="\\fad\\pos\\move\\org\\clip\\"
|
||||
local fontret="\\r\\fn\\"
|
||||
if hide then
|
||||
hidem={}
|
||||
for k,v in ipairs(GUI) do
|
||||
if v.x>4 and v.y>0 and v.name~='onlyt' and v.name~='kara' then
|
||||
nom=v.label:gsub("c, 1c","1c"):gsub("%(i%)","")
|
||||
if res[v.name] then table.insert(hidem,nom) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for x,i in ipairs(sel) do
|
||||
line=subs[i]
|
||||
text=line.text:gsub("\\c&","\\1c&")
|
||||
startg=text:match("^{\\[^}]-}") or ""
|
||||
startg=trem(startg)
|
||||
t2=text:gsub("^{\\[^}]-}","")
|
||||
|
||||
if hide then
|
||||
for t=1,#hidem do
|
||||
local tag='\\'..hidem[t]
|
||||
local htag='//'..hidem[t]
|
||||
local chk=tag..'\\'
|
||||
tg=nil
|
||||
if numbers:match(chk) then
|
||||
tg=startg:match(tag.."([%d.-]+)")
|
||||
if tg then t2=t2.."{"..htag..tg.."}" end
|
||||
startg=startg:gsub(tag.."[%d.-]+","")
|
||||
if not tg and tag=="\\shad" then
|
||||
tg1=startg:match("\\xshad([%d.-]+)")
|
||||
tg2=startg:match("\\yshad([%d.-]+)")
|
||||
if tg1 then t2=t2.."{//xshad"..tg1.."}" end
|
||||
if tg2 then t2=t2.."{//yshad"..tg2.."}" end
|
||||
startg=startg:gsub("\\[xy]shad[%d.-]+","")
|
||||
end
|
||||
elseif alphacol:match(chk) then
|
||||
tg=startg:match(tag.."(&H%x+&)")
|
||||
if tg then t2=t2.."{"..htag..tg.."}" end
|
||||
startg=startg:gsub(tag.."&H%x+&","")
|
||||
elseif parent:match(chk) then
|
||||
tg=startg:match(tag.."(%b())")
|
||||
if not tg and tag=="\\clip" then tg=startg:match("\\iclip(%b())") tag='\\iclip' htag='//iclip' end
|
||||
if not tg and tag=="\\fad" then tg=startg:match("\\fade(%b())") tag='\\fade' htag='//fade' end
|
||||
if tg then t2=t2.."{"..htag..tg.."}" end
|
||||
startg=startg:gsub(tag.."%b()","")
|
||||
elseif fontret:match(chk) then
|
||||
tg=startg:match(tag.."([^\\}]*)")
|
||||
if tg then t2=t2.."{"..htag..tg.."}" end
|
||||
startg=startg:gsub(tag.."[^\\}]*","")
|
||||
elseif tag=='\\t' then
|
||||
t2=t2.."{"..trnsfrm:gsub("\\t","//t").."}"
|
||||
end
|
||||
end
|
||||
if res.hidline then
|
||||
-- hide inline
|
||||
inT=inline_pos(t2)
|
||||
t2=t2:gsub(ATAG,"")
|
||||
for k,v in ipairs(inT) do
|
||||
t2=t2..v.t:gsub("{%*?\\","{"..v.n.."//")
|
||||
end
|
||||
end
|
||||
else
|
||||
local vis1,vis2=t2:gsub("%b{}","")
|
||||
local c=0
|
||||
repeat
|
||||
-- Unhide regular
|
||||
if res.skill then
|
||||
for hidden in t2:gmatch("{(//.-)}") do
|
||||
t2=t2:gsub("{"..esc(hidden).."}","")
|
||||
hidden=hidden:gsub("//","\\")
|
||||
startg=startg.."{"..hidden.."}"
|
||||
end
|
||||
end
|
||||
-- unhide inline
|
||||
if t2:match("{%d+//[^}]+}") and res.ikill then
|
||||
inT={}
|
||||
stT=''
|
||||
for num,tag in t2:gmatch("{(%d+)//([^}]+)}") do
|
||||
table.insert(inT,{n=num,t=tag})
|
||||
end
|
||||
for tag in t2:gmatch("{//[^}]+}") do stT=stT..tag end
|
||||
table.sort(inT,function(a,b) return tonumber(a.n)<tonumber(b.n) end)
|
||||
t2=t2:gsub("{%d+//[^}]+}","")
|
||||
if t2:match"{" then orig=t2 t2=t2:gsub("%b{}","") end
|
||||
t2=inline_ret2(t2,inT)
|
||||
if orig then t2=textmod(orig,t2) orig=nil end
|
||||
t2=t2..stT
|
||||
end
|
||||
vis2=t2:gsub("%b{}","")
|
||||
c=c+1
|
||||
until vis1==vis2 or c==666
|
||||
if vis1~=vis2 then logg('Error:\n '..vis1..'\n> '..vis2) end
|
||||
end
|
||||
|
||||
if not hide or hide and not res.trans then startg=startg.."{"..trnsfrm.."}" end
|
||||
text=duplikill(startg:gsub("}{",""):gsub("\\1c","\\c"))..t2
|
||||
text=text:gsub("{}",""):gsub("\\1c","\\c")
|
||||
if line.text~=text then line.text=text subs[i]=line end
|
||||
end
|
||||
return sel
|
||||
end
|
||||
|
||||
-- save inline tags
|
||||
function inline_pos(t)
|
||||
inTags={}
|
||||
tl=t:len()
|
||||
if tl==0 then return {} end
|
||||
p=0
|
||||
t1=''
|
||||
repeat
|
||||
seg=t:match("^(%b{})") -- try to match tags/comments
|
||||
if seg then
|
||||
if seg:match("{%*?\\") then table.insert(inTags,{n=p,t=seg}) end
|
||||
else
|
||||
seg=t:match("^([^{]+)") -- or match text
|
||||
if not seg then t_error("Error: There appears to be a problem with the brackets here...\n"..t1..t,1) end
|
||||
SL=re.find(seg,".")
|
||||
p=p+#SL -- position of next '{' [or end]
|
||||
end
|
||||
t1=t1..seg
|
||||
t=t:gsub("^"..esc(seg),"")
|
||||
tl=t:len()
|
||||
until tl==0
|
||||
return inTags
|
||||
end
|
||||
|
||||
-- rebuild inline tags
|
||||
function inline_ret2(t,tab)
|
||||
tl=t:len()
|
||||
nt=''
|
||||
kill='_Z#W_' -- this is supposed to never match
|
||||
for k,v in ipairs(tab) do
|
||||
N=tonumber(v.n)
|
||||
if N==0 then nt=nt..v.t
|
||||
else
|
||||
m='.'
|
||||
-- match how many chars at the start
|
||||
m=m:rep(N)
|
||||
RS=re.find(t,m)
|
||||
seg=RS[1].str
|
||||
seg=re.sub(seg,'^'..kill,'')
|
||||
nt=nt..seg..'{\\'..v.t..'}'
|
||||
kill=m -- how many matched in the last round
|
||||
end
|
||||
end
|
||||
-- the rest
|
||||
seg=re.sub(t,'^'..kill,'')
|
||||
nt=nt..seg
|
||||
return nt
|
||||
end
|
||||
|
||||
-- reanimatools -------
|
||||
function esc(str) str=str:gsub("[%%%(%)%[%]%.%-%+%*%?%^%$]","%%%1") return str end
|
||||
function rnd2dec(num) num=math.floor((num*100)+0.5)/100 return num end
|
||||
function logg(m) m=m or "nil" aegisub.log("\n "..m) end
|
||||
function wrap(str) return "{"..str.."}" end
|
||||
function nobra(t) return t:gsub("%b{}","") end
|
||||
function nobrea(t) return t:gsub("%b{}",""):gsub("\\[Nh]","") end
|
||||
function nobrea1(t) return t:gsub("%b{}",""):gsub(" *\\[Nh] *"," ") end
|
||||
function tagmerge(t) repeat t,r=t:gsub("({\\[^}]-)}{(\\[^}]-})","%1%2") until r==0 return t end
|
||||
function progress(msg) if aegisub.progress.is_cancelled() then ak() end aegisub.progress.title(msg) end
|
||||
function t_error(message,cancel) ADD({{class="label",label=message}},{"OK"},{close='OK'}) if cancel then ak() end end
|
||||
|
||||
function duplikill(tagz)
|
||||
local tags1={"blur","be","bord","shad","xbord","xshad","ybord","yshad","fs","fsp","fscx","fscy","frz","frx","fry","fax","fay"}
|
||||
local tags2={"c","2c","3c","4c","1a","2a","3a","4a","alpha"}
|
||||
tagz=tagz:gsub("\\t%b()",function(t) return t:gsub("\\","|") end)
|
||||
for i=1,#tags1 do
|
||||
tag=tags1[i]
|
||||
repeat tagz,c=tagz:gsub("|"..tag.."[%d%.%-]+([^}]-)(\\"..tag.."[%d%.%-]+)","%1%2") until c==0
|
||||
repeat tagz,c=tagz:gsub("\\"..tag.."[%d%.%-]+([^}]-)(\\"..tag.."[%d%.%-]+)","%2%1") until c==0
|
||||
end
|
||||
tagz=tagz:gsub("\\1c&","\\c&")
|
||||
for i=1,#tags2 do
|
||||
tag=tags2[i]
|
||||
repeat tagz,c=tagz:gsub("|"..tag.."&H%x+&([^}]-)(\\"..tag.."&H%x+&)","%1%2") until c==0
|
||||
repeat tagz,c=tagz:gsub("\\"..tag.."&H%x+&([^}]-)(\\"..tag.."&H%x+&)","%2%1") until c==0
|
||||
end
|
||||
repeat tagz,c=tagz:gsub("\\fn[^\\}]+([^}]-)(\\fn[^\\}]+)","%2%1") until c==0
|
||||
repeat tagz,c=tagz:gsub("(\\[ibusq])%d(.-)(%1%d)","%2%3") until c==0
|
||||
repeat tagz,c=tagz:gsub("(\\an)%d(.-)(%1%d)","%3%2") until c==0
|
||||
tagz=tagz:gsub("(|i?clip%(%A-%))(.-)(\\i?clip%(%A-%))","%2%3")
|
||||
:gsub("(\\i?clip%b())(.-)(\\i?clip%b())",function(a,b,c)
|
||||
if a:match("m") and c:match("m") or not a:match("m") and not c:match("m") then return b..c else return a..b..c end end)
|
||||
tagz=tagz:gsub("|","\\"):gsub("\\t%([^\\%)]-%)","")
|
||||
return tagz
|
||||
end
|
||||
|
||||
function extrakill(text,o)
|
||||
local tags3={"pos","move","org","fad"}
|
||||
for i=1,#tags3 do
|
||||
tag=tags3[i]
|
||||
if o==2 then
|
||||
repeat text,c=text:gsub("(\\"..tag.."[^\\}]+)([^}]-)(\\"..tag.."[^\\}]+)","%3%2") until c==0
|
||||
else
|
||||
repeat text,c=text:gsub("(\\"..tag.."[^\\}]+)([^}]-)(\\"..tag.."[^\\}]+)","%1%2") until c==0
|
||||
end
|
||||
end
|
||||
repeat text,c=text:gsub("(\\pos[^\\}]+)([^}]-)(\\move[^\\}]+)","%1%2") until c==0
|
||||
repeat text,c=text:gsub("(\\move[^\\}]+)([^}]-)(\\pos[^\\}]+)","%1%2") until c==0
|
||||
return text
|
||||
end
|
||||
|
||||
function trem(tags)
|
||||
trnsfrm=""
|
||||
for t in tags:gmatch("\\t%b()") do trnsfrm=trnsfrm..t end
|
||||
tags=tags:gsub("\\t%b()","")
|
||||
return tags
|
||||
end
|
||||
|
||||
function cleantr(tags)
|
||||
trnsfrm=""
|
||||
zerotf=""
|
||||
for t in tags:gmatch("\\t%b()") do
|
||||
if t:match("\\t%(\\") then
|
||||
zerotf=zerotf..t:match("\\t%((.*)%)$")
|
||||
else
|
||||
trnsfrm=trnsfrm..t
|
||||
end
|
||||
end
|
||||
zerotf="\\t("..zerotf..")"
|
||||
tags=tags:gsub("\\t%b()",""):gsub("^({[^}]*)}","%1"..zerotf..trnsfrm.."}"):gsub("\\t%(%)","")
|
||||
return tags
|
||||
end
|
||||
|
||||
function retextmod(orig,text)
|
||||
local v1,v2,c,t2
|
||||
v1=nobrea(orig)
|
||||
c=0
|
||||
repeat
|
||||
t2=textmod(orig,text)
|
||||
v2=nobrea(text)
|
||||
c=c+1
|
||||
until v1==v2 or c==666
|
||||
if v1~=v2 then logg("Something went wrong with the text...") logg(v1) logg(v2) end
|
||||
return t2
|
||||
end
|
||||
|
||||
function textmod(orig,text)
|
||||
if text=="" then return orig end
|
||||
tk={}
|
||||
tg={}
|
||||
text=text:gsub("{\\\\k0}","")
|
||||
text=tagmerge(text)
|
||||
vis=nobra(text)
|
||||
ltrmatches=re.find(vis,".")
|
||||
if not ltrmatches then logg("text: "..text..'\nvisible: '..vis)
|
||||
logg("If you're seeing this, something really weird is happening with the re module.\nTry this again or rescan Autoload.")
|
||||
end
|
||||
for l=1,#ltrmatches do
|
||||
table.insert(tk,ltrmatches[l].str)
|
||||
end
|
||||
stags=text:match(STAG) or ""
|
||||
text=text:gsub(STAG,"") :gsub("{[^\\}]-}","")
|
||||
orig=orig:gsub("{([^\\}]+)}",function(c) return wrap("\\\\"..c.."|||") end)
|
||||
count=0
|
||||
for seq in orig:gmatch("[^{]-{%*?\\[^}]-}") do
|
||||
chars,as,tak=seq:match("([^{]-){(%*?)(\\[^}]-)}")
|
||||
pos=re.find(chars,".")
|
||||
if pos==nil then ps=0+count else ps=#pos+count end
|
||||
tgl={p=ps,t=tak,a=as}
|
||||
table.insert(tg,tgl)
|
||||
count=ps
|
||||
end
|
||||
count=0
|
||||
for seq in text:gmatch("[^{]-{%*?\\[^}]-}") do
|
||||
chars,as,tak=seq:match("([^{]-){(%*?)(\\[^}]-)}")
|
||||
pos=re.find(chars,".")
|
||||
if pos==nil then ps=0+count else ps=#pos+count end
|
||||
tgl={p=ps,t=tak,a=as}
|
||||
table.insert(tg,tgl)
|
||||
count=ps
|
||||
end
|
||||
newline=""
|
||||
for i=1,#tk do
|
||||
newline=newline..tk[i]
|
||||
newt=""
|
||||
for n,t in ipairs(tg) do
|
||||
if t.p==i then newt=newt..t.a..t.t end
|
||||
end
|
||||
if newt~="" then newline=newline.."{"..as..newt.."}" end
|
||||
end
|
||||
newtext=stags..newline:gsub("(|||)(\\\\)","%1}{%2"):gsub("({[^}]-)\\\\([^\\}]-)|||","{%2}%1")
|
||||
text=newtext:gsub("{}","")
|
||||
return text
|
||||
end
|
||||
|
||||
|
||||
function cleanup(subs,sel,act)
|
||||
ADD=aegisub.dialog.display
|
||||
ak=aegisub.cancel
|
||||
if #sel==0 then t_error("No selection",1) end
|
||||
ATAG="{[*>]?\\[^}]-}"
|
||||
STAG="^{>?\\[^}]-}"
|
||||
if act==0 then act=sel[1] end
|
||||
chng=0 kleen=0
|
||||
GUI={
|
||||
{x=0,y=0,class="checkbox",name="nots",label="Remove TS timecodes",hint="Removes timecodes like {TS 12:36}"},
|
||||
{x=0,y=1,class="checkbox",name="clear_a",label="Clear Actor field"},
|
||||
{x=0,y=2,class="checkbox",name="clear_e",label="Clear Effect field"},
|
||||
{x=0,y=3,class="checkbox",name="layers",label="Raise dialogue layer by 5"},
|
||||
{x=0,y=4,class="checkbox",name="cleantag",label="Clean up tags",hint="Fixes duplicates, \\\\, \\}, }{, and other garbage"},
|
||||
{x=0,y=5,class="checkbox",name="ctrans",label="Clean up transforms"},
|
||||
{x=0,y=6,class="checkbox",name="overlap",label="Fix 1-frame gaps/overlaps"},
|
||||
{x=0,y=7,class="checkbox",name="nocomline",label="Delete commented lines"},
|
||||
{x=0,y=8,class="checkbox",name="noempty",label="Delete empty lines"},
|
||||
{x=0,y=9,class="checkbox",name="alphacol",label="Try to fix alpha / colour tags"},
|
||||
{x=0,y=10,class="checkbox",name="spaces",label="Fix start/end/double spaces"},
|
||||
{x=0,y=12,class="checkbox",name="info",label="Print info"},
|
||||
{x=0,y=13,class="checkbox",name="all",label="ALL OF THE ABOVE"},
|
||||
|
||||
{x=1,y=0,class="label",label=" "},
|
||||
|
||||
{x=2,y=0,width=2,class="checkbox",name="allcol",label="Remove all colour tags"},
|
||||
{x=2,y=1,class="checkbox",name="allphas",label="Remove all alphas"},
|
||||
{x=3,y=1,class="checkbox",name="alpha14",label="Only 1a-4a"},
|
||||
{x=2,y=2,class="checkbox",name="allrot",label="Remove all rotations",hint="frx, fry, frz"},
|
||||
{x=3,y=2,class="checkbox",name="xyrot",label="Only x, y",hint="remove frx, fry"},
|
||||
{x=2,y=3,class="checkbox",name="allsize",label="Remove size/scaling",hint="fs, fscx, fscy"},
|
||||
{x=3,y=3,class="checkbox",name="scales",label="Only scaling",hint="remove fscx, fscy"},
|
||||
{x=2,y=4,class="checkbox",name="allshad",label="Remove all shadows",hint="shad, xshad, yshad"},
|
||||
{x=3,y=4,class="checkbox",name="xyshad",label="Only x, y",hint="remove xshad, yshad"},
|
||||
{x=2,y=5,class="checkbox",name="parent",label="Remove parentheses",hint="fad(e), (i)clip, pos, move, org\n(but not t)"},
|
||||
{x=3,y=5,class="checkbox",name="parent2",label="Except \\pos",hint="fad(e), (i)clip, move, org\n(but not t or pos)"},
|
||||
{x=2,y=6,width=2,class="checkbox",name="allpers",label="Remove all perspective",hint="frx, fry, frz, fax, fay, org"},
|
||||
|
||||
{x=2,y=7,width=2,class="label",label=" ~ Script Cleanup v"..script_version.." ~"},
|
||||
|
||||
{x=2,y=8,width=2,class="checkbox",name="hspace",label="Remove hard spaces - \\h"},
|
||||
{x=2,y=9,class="checkbox",name="nobreak",label="Remove line breaks"},
|
||||
{x=3,y=9,class="checkbox",name="nobreak2",label="...no space",hint="Remove line breaks, leave no spaces"},
|
||||
{x=2,y=10,class="checkbox",name="nostyle",label="Delete unused styles"},
|
||||
{x=3,y=10,class="checkbox",name="nostyle2",label="Except Def.",hint="Delete unused styles except Default"},
|
||||
{x=2,y=11,class="checkbox",name="inline",label="Remove inline tags"},
|
||||
{x=3,y=11,class="checkbox",name="inline2",label="Except last",hint="Remove inline tags except the last one"},
|
||||
{x=2,y=12,width=2,class="checkbox",name="nocom",label="Remove comments from lines",hint="Removes {comments} (not tags)"},
|
||||
{x=2,y=13,width=2,class="checkbox",name="notag",label="Remove all {\\tags} from selected lines"},
|
||||
|
||||
{x=4,y=0,height=14,class="label",label="| \n|\n|\n|\n|\n|\n|\n|\n|\n|\n|\n|\n|\n|\n|\n|\n|\n|"},
|
||||
|
||||
{x=5,y=0,class="checkbox",name="skill",label="[start]",value=true},
|
||||
{x=6,y=0,class="checkbox",name="ikill",label="[inline]",value=true,hint="only kill, not hide"},
|
||||
{x=7,y=0,width=2,class="checkbox",name="inverse",label="[inverse/unhide]",hint="kill all except checked ones\n\n'Unhide' for 'Hide Tags'"},
|
||||
{x=7,y=1,width=2,class="checkbox",name="onlyt",label="[from \\t]",hint="remove only from transforms\n\n n/a for 'Hide Tags'"},
|
||||
|
||||
{x=5,y=1,class="checkbox",name="blur",label="blur"},
|
||||
{x=5,y=2,class="checkbox",name="border",label="bord",hint="includes xbord and ybord [not for Hide]"},
|
||||
{x=5,y=3,class="checkbox",name="shadow",label="shad",hint="includes xshad and yshad for Hide"},
|
||||
{x=5,y=4,class="checkbox",name="fsize",label="fs"},
|
||||
{x=5,y=5,class="checkbox",name="fspace",label="fsp"},
|
||||
{x=5,y=6,class="checkbox",name="scalex",label="fscx"},
|
||||
{x=5,y=7,class="checkbox",name="scaley",label="fscy"},
|
||||
{x=5,y=8,class="checkbox",name="fname",label="fn"},
|
||||
{x=5,y=9,class="checkbox",name="ital",label="i"},
|
||||
{x=5,y=10,class="checkbox",name="bold",label="b"},
|
||||
{x=5,y=11,class="checkbox",name="under",label="u"},
|
||||
{x=5,y=12,class="checkbox",name="stri",label="s"},
|
||||
{x=5,y=13,class="checkbox",name="wrap",label="q"},
|
||||
|
||||
{x=6,y=1,class="checkbox",name="bee",label="be"},
|
||||
{x=6,y=2,class="checkbox",name="color1",label="c, 1c"},
|
||||
{x=6,y=3,class="checkbox",name="color2",label="2c"},
|
||||
{x=6,y=4,class="checkbox",name="color3",label="3c"},
|
||||
{x=6,y=5,class="checkbox",name="color4",label="4c"},
|
||||
{x=6,y=6,class="checkbox",name="alpha",label="alpha"},
|
||||
{x=6,y=7,class="checkbox",name="alfa1",label="1a"},
|
||||
{x=6,y=8,class="checkbox",name="alfa2",label="2a"},
|
||||
{x=6,y=9,class="checkbox",name="alfa3",label="3a"},
|
||||
{x=6,y=10,class="checkbox",name="alfa4",label="4a"},
|
||||
{x=6,y=11,class="checkbox",name="align",label="a"},
|
||||
{x=6,y=12,class="checkbox",name="anna",label="an"},
|
||||
{x=6,y=13,class="checkbox",name="clip",label="(i)clip"},
|
||||
|
||||
{x=7,y=2,class="checkbox",name="fade",label="fad"},
|
||||
{x=7,y=3,class="checkbox",name="posi",label="pos"},
|
||||
{x=7,y=4,class="checkbox",name="move",label="move"},
|
||||
{x=7,y=5,class="checkbox",name="org",label="org"},
|
||||
{x=7,y=6,class="checkbox",name="frz",label="frz"},
|
||||
{x=7,y=7,class="checkbox",name="frx",label="frx"},
|
||||
{x=7,y=8,class="checkbox",name="fry",label="fry"},
|
||||
{x=7,y=9,class="checkbox",name="fax",label="fax"},
|
||||
{x=7,y=10,class="checkbox",name="fay",label="fay"},
|
||||
{x=7,y=11,width=2,class="checkbox",name="kara",label="k/kf/ko"},
|
||||
{x=7,y=12,class="checkbox",name="return",label="r"},
|
||||
{x=7,y=13,class="checkbox",name="trans",label="t"},
|
||||
|
||||
{x=8,y=12,height=2,class="checkbox",name="hidline",label="hide\ninline",hint='Hide ALL inline tags'},
|
||||
}
|
||||
P,res=ADD(GUI,
|
||||
{"Run selected","Comments","Tags","Dial 5","Clean Tags","^ Kill Tags","Hide Tags","Cancer"},{ok='Run selected',cancel='Cancer'})
|
||||
if P=="Cancer" then ak() end
|
||||
if P=="^ Kill Tags" then killemall(subs,sel) end
|
||||
if P=="Hide Tags" then hide_tags(subs,sel) end
|
||||
if P=="Comments" then res.nocom=true cleanlines(subs,sel) end
|
||||
if P=="Tags" then res.notag=true cleanlines(subs,sel) end
|
||||
if P=="Dial 5" then res.layers=true cleanlines(subs,sel) end
|
||||
if P=="Clean Tags" then res.cleantag=true cleanlines(subs,sel) end
|
||||
if P=="Run selected" then
|
||||
C=0 for key,v in ipairs(GUI) do if v.x<=3 and res[v.name] then C=1 end end
|
||||
if C==0 then t_error("Run Selected: Error - nothing selected",1) end
|
||||
if res.all then
|
||||
for key,v in ipairs(GUI) do if v.x>0 and v.name then res[v.name]=false end end
|
||||
cleanlines(subs,sel)
|
||||
sel=noemptycom(subs,sel)
|
||||
else cleanlines(subs,sel)
|
||||
if res.nocomline and res.noempty then sel=noemptycom(subs,sel)
|
||||
else
|
||||
if res.nocomline then sel=nocom_line(subs,sel) end
|
||||
if res.noempty then sel=noempty(subs,sel) end
|
||||
end
|
||||
table.sort(sel)
|
||||
if res.nostyle or res.nostyle2 then sel=nostyle(subs,sel) end
|
||||
end
|
||||
end
|
||||
if act>#subs then act=#subs end
|
||||
return sel,act
|
||||
end
|
||||
|
||||
if haveDepCtrl then depRec:registerMacro(cleanup) else aegisub.register_macro(script_name,script_description,cleanup) end
|
43
automation/autoload/unkf.lua
Normal file
@ -0,0 +1,43 @@
|
||||
local tr = aegisub.gettext
|
||||
|
||||
script_name = tr"unkf"
|
||||
script_description = tr"replace kf/ko tags in selected lines by regular k tags"
|
||||
script_author = "amoethyst"
|
||||
script_version = "1.0"
|
||||
|
||||
|
||||
function split_line(subs, sel)
|
||||
local expr_kof = "^(.-{[^}]*\\k)[of](.*)$"
|
||||
local expr_K = "^(.-{[^}]*\\)K(.*)$"
|
||||
local before, after
|
||||
|
||||
for _, i in ipairs(sel) do
|
||||
line = subs[i]
|
||||
|
||||
-- replace ko and kf tags
|
||||
while true do
|
||||
before, after = line.text:match(expr_kof)
|
||||
if before == nil then
|
||||
break
|
||||
else
|
||||
line.text = before .. after
|
||||
end
|
||||
end
|
||||
|
||||
-- replace K tags
|
||||
while true do
|
||||
before, after = line.text:match(expr_K)
|
||||
if before == nil then
|
||||
break
|
||||
else
|
||||
line.text = before .. "k" .. after
|
||||
end
|
||||
end
|
||||
|
||||
subs[i] = line
|
||||
end
|
||||
|
||||
aegisub.set_undo_point(script_name)
|
||||
end
|
||||
|
||||
aegisub.register_macro(script_name, script_description, split_line)
|
@ -22,7 +22,6 @@ namespace agi {
|
||||
line_iterator_base::line_iterator_base(std::istream &stream, std::string encoding)
|
||||
: stream(&stream)
|
||||
{
|
||||
boost::to_lower(encoding);
|
||||
if (encoding != "utf-8") {
|
||||
agi::charset::IconvWrapper c("utf-8", encoding.c_str());
|
||||
c.Convert("\r", 1, reinterpret_cast<char *>(&cr), sizeof(int));
|
||||
|
@ -50,6 +50,8 @@ ArchitecturesAllowed=x64
|
||||
#include "fragment_automation.iss"
|
||||
#include "fragment_translations.iss"
|
||||
#include "fragment_spelling.iss"
|
||||
#include "fragment_fonts.iss"
|
||||
#ifdef DEPCTRL
|
||||
#include "fragment_runtimes.iss"
|
||||
|
||||
[Code]
|
||||
|
@ -36,10 +36,22 @@
|
||||
|
||||
[Files]
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\cleantags-autoload.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\karaoke-auto-leadin.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\kara-templater.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\select-overlaps.moon; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\strip-tags.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\cleantags-autoload.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\duetto-meika.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\karaoke-adjust-1sec.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\karaoke-split.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\kara-templater.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\ua.BlurAndGlow.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\ua.ChangeCase.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\ua.Colorize.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\ua.Cycles.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\ua.FadeWorks.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\ua.HYDRA.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\ua.ScriptCleanup.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
DestDir: {app}\automation\autoload; Source: ..\..\automation\autoload\unkf.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\bundled
|
||||
|
||||
|
||||
DestDir: {app}\automation\demos; Source: ..\..\automation\demos\future-windy-blur.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\demos
|
||||
DestDir: {app}\automation\demos; Source: ..\..\automation\demos\raytracer.lua; Flags: ignoreversion overwritereadonly uninsremovereadonly; Attribs: readonly; Components: macros\demos
|
||||
|
@ -34,8 +34,8 @@
|
||||
|
||||
[Files]
|
||||
; Avisynth
|
||||
DestDir: {app}; Source: vendor\AvisynthPlus64\devil.dll; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: vendor\AvisynthPlus64\avisynth.dll; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: vendor\AvisynthPlus64\DirectShowSource.dll; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: ..\..\bin\devil.dll; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: ..\..\bin\avisynth.dll; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: ..\..\bin\DirectShowSource.dll; Flags: ignoreversion; Components: main
|
||||
; VSFilter
|
||||
DestDir: {app}\csri; Source: vendor\xy-vsfilter\xy-vsfilter-aegisub64.dll; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}\csri; Source: ..\..\bin\csri\xy-vsfilter-aegisub64.dll; Flags: ignoreversion; Components: main
|
||||
|
7
packages/win_installer/fragment_fonts.iss
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
[Files]
|
||||
DestDir: {app}\FontsLicenses; DestName: Amaranth-OFL.txt; Source: ..\..\vendor\japan7-fonts\Amaranth\OFL.txt; Flags: ignoreversion; Components: fonts
|
||||
DestDir: "{fonts}"; FontInstall: "Amaranth"; Source: ..\..\vendor\japan7-fonts\Amaranth\Amaranth-Regular.ttf; Flags: onlyifdoesntexist uninsneveruninstall; Components: fonts
|
||||
DestDir: "{fonts}"; FontInstall: "Amaranth"; Source: ..\..\vendor\japan7-fonts\Amaranth\Amaranth-Bold.ttf; Flags: onlyifdoesntexist uninsneveruninstall; Components: fonts
|
||||
DestDir: "{fonts}"; FontInstall: "Amaranth"; Source: ..\..\vendor\japan7-fonts\Amaranth\Amaranth-Italic.ttf; Flags: onlyifdoesntexist uninsneveruninstall; Components: fonts
|
||||
DestDir: "{fonts}"; FontInstall: "Amaranth"; Source: ..\..\vendor\japan7-fonts\Amaranth\Amaranth-BoldItalic.ttf; Flags: onlyifdoesntexist uninsneveruninstall; Components: fonts
|
@ -46,6 +46,7 @@ Name: "macros\modules\luajson"; Description: "LuaJSON"; Types: full
|
||||
Name: "dictionaries"; Description: "Spellcheck Dictionaries"; Types: full
|
||||
Name: "dictionaries\en_US"; Description: "English (US)"; Types: full
|
||||
Name: "translations"; Description: "Aegisub Translations"; Types: full
|
||||
Name: "fonts"; Description: "Bundled fonts"; Types: full
|
||||
|
||||
[Tasks]
|
||||
Name: "startmenuicon"; Description: "{cm:StartMenuIcon}"; GroupDescription: "{cm:AdditionalIcons}"
|
||||
@ -55,6 +56,8 @@ Name: "checkforupdates"; Description: "{cm:CheckForUpdates}"; GroupDescription:
|
||||
; main
|
||||
DestDir: {app}; Source: ..\..\bin\aegisub{#ARCH}.exe; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: license.txt; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: ..\..\bin\libcrypto-1_1-x64.dll; Flags: ignoreversion; Components: main
|
||||
DestDir: {app}; Source: ..\..\bin\libssl-1_1-x64.dll; Flags: ignoreversion; Components: main
|
||||
|
||||
[Icons]
|
||||
Name: {commonprograms}\Aegisub; Filename: {app}\aegisub{#ARCH}.exe; WorkingDir: {app}; IconIndex: 0; Tasks: startmenuicon; Comment: Create and edit subtitle files
|
||||
|
@ -32,7 +32,8 @@
|
||||
; Contact: mailto:nielsm@indvikleren.dk
|
||||
;
|
||||
|
||||
#include "../../build/git_version.h"
|
||||
#define BUILD_GIT_VERSION_STRING "Japan7 0.9"
|
||||
#define INSTALLER_VERSION 1
|
||||
|
||||
#define CURRENT_YEAR GetDateTimeString('yyyy', '', '');
|
||||
|
||||
@ -64,27 +65,22 @@ UninstallDisplayIcon={app}\aegisub{#ARCH}.exe
|
||||
WizardImageFile=welcome-large.bmp
|
||||
WizardSmallImageFile=aegisub-large.bmp
|
||||
|
||||
OutputBaseFilename=Aegisub-{#BUILD_GIT_VERSION_STRING}-{#ARCH}
|
||||
VersionInfoDescription=Aegisub {#BUILD_GIT_VERSION_STRING} {#ARCH}-bit
|
||||
OutputBaseFilename=Aegisub-Japan7-x64
|
||||
VersionInfoDescription=Aegisub {#BUILD_GIT_VERSION_STRING} x64
|
||||
|
||||
[Languages]
|
||||
Name: "en"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "bg"; MessagesFile: "compiler:Languages\Bulgarian.isl"
|
||||
Name: "ca"; MessagesFile: "compiler:Languages\Catalan.isl"
|
||||
Name: "cz"; MessagesFile: "compiler:Languages\Czech.isl"
|
||||
Name: "da"; MessagesFile: "compiler:Languages\Danish.isl"
|
||||
Name: "de"; MessagesFile: "compiler:Languages\German.isl"
|
||||
Name: "el"; MessagesFile: "compiler:Languages\Greek.isl"
|
||||
Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
|
||||
Name: "eu"; MessagesFile: "compiler:Languages\Basque.isl"
|
||||
Name: "fi"; MessagesFile: "compiler:Languages\Finnish.isl"
|
||||
Name: "fr_FR"; MessagesFile: "compiler:Languages\French.isl"
|
||||
Name: "gl"; MessagesFile: "compiler:Languages\Galician.isl"
|
||||
Name: "hu"; MessagesFile: "compiler:Languages\Hungarian.isl"
|
||||
Name: "id"; MessagesFile: "compiler:Languages\Indonesian.isl"
|
||||
Name: "it"; MessagesFile: "compiler:Languages\Italian.isl"
|
||||
Name: "ja"; MessagesFile: "compiler:Languages\Japanese.isl"
|
||||
Name: "ko"; MessagesFile: "compiler:Languages\Korean.isl"
|
||||
Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
|
||||
Name: "pl"; MessagesFile: "compiler:Languages\Polish.isl"
|
||||
Name: "pt_BR"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
|
||||
@ -93,8 +89,6 @@ Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||
Name: "sr_RS"; MessagesFile: "compiler:Languages\SerbianCyrillic.isl"
|
||||
Name: "sr_RS_latin"; MessagesFile: "compiler:Languages\SerbianLatin.isl"
|
||||
Name: "uk_UA"; MessagesFile: "compiler:Languages\Ukrainian.isl"
|
||||
Name: "zh_CN"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
|
||||
Name: "zh_TW"; MessagesFile: "compiler:Languages\ChineseTraditional.isl"
|
||||
|
||||
[Files]
|
||||
; small bitmaps (used by beautify code)
|
||||
|
@ -1,44 +1,24 @@
|
||||
[CustomMessages]
|
||||
InstallRuntime=Installing runtime libraries...
|
||||
el.InstallRuntime=Εγκατάσταση βιβλιοθηκών...
|
||||
eu.InstallRuntime=Runtime liburutegiak ezartzen...
|
||||
id.InstallRuntime=Memasang runtime libraries...
|
||||
pt_PT.InstallRuntime=A instalar livrarias de runtime...
|
||||
uk_UA.InstallRuntime=Встановлюю бібліотеки реального часу...
|
||||
zh_CN.InstallRuntime=正在安装运行库……
|
||||
zh_TW.InstallRuntime=正在安裝運行庫……
|
||||
StartMenuIcon=Create a start menu icon
|
||||
el.StartMenuIcon=Δημιουργία εικονιδίου στο μενού έναρξης
|
||||
eu.StartMenuIcon=Sortu hasiera menuko ikur bat
|
||||
id.StartMenuIcon=Buat ikon di menu awal
|
||||
pt_PT.StartMenuIcon=Criar ícone no menu iniciar
|
||||
uk_UA.StartMenuIcon=Створити піктограму в меню Запустити
|
||||
zh_CN.StartMenuIcon=创建开始菜单图标
|
||||
zh_TW.StartMenuIcon=創建開始功能表圖示
|
||||
CheckForUpdates=Automatically check for new versions of Aegisub
|
||||
el.CheckForUpdates=Αυτόματος έλεγχος για καινούριες εκδόσεις του Aegisub
|
||||
eu.CheckForUpdates=Berezgaitasunez egiaztatu Aegisub-ren bertsio berririk dagoen
|
||||
id.CheckForUpdates=Otomatis cek versi terbaru Aegisub
|
||||
pt_PT.CheckForUpdates=Verifica automaticamente a existência de novas versões do Aegisub
|
||||
uk_UA.CheckForUpdates=Автоматично перевіряти Aegisub на нові версії
|
||||
zh_CN.CheckForUpdates=自动检查Aegisub的新版本
|
||||
zh_TW.CheckForUpdates=自動檢查Aegisub的新版本
|
||||
UpdatesGroup=Update Checker:
|
||||
el.UpdatesGroup=Έλεγχος Ενημερώσεων:
|
||||
eu.UpdatesGroup=Eguneraketa Egiaztatzailea:
|
||||
id.UpdatesGroup=Pemeriksa Pembaharuan
|
||||
pt_PT.UpdatesGroup=Verificar Actualizações:
|
||||
uk_UA.UpdatesGroup=Модуль Перевірки на Оновлення:
|
||||
zh_CN.UpdatesGroup=自动更新:
|
||||
zh_TW.UpdatesGroup=自動更新:
|
||||
|
||||
; Replacement for License page, no need to bother the user with legal mumbo-jumbo
|
||||
[Messages]
|
||||
WelcomeLabel2=This will install Aegisub {#BUILD_GIT_VERSION_STRING} on your computer.%n%nAegisub is covered by the GNU General Public License version 2. This means you may use the application for any purpose without charge, but that no warranties of any kind are given either.%n%nSee the Aegisub website for information on obtaining the source code.
|
||||
el.WelcomeLabel2=Αυτό θα εγκαταστήσει το Aegisub {#BUILD_GIT_VERSION_STRING} στον υπολογιστή σας.%n%nΤο Aegisub καλύπτεται από τον άδεια GNU General Public License version 2. Αυτό σημαίνει ότι μπορείτε να χρησιμοποιήσετε την εφαρμογή για κάθε σκοπό χωρίς χρέωση, αλλά δεν υπάρχουν εγγυήσεις καμίας φύσης.%n%nΔείτε την ιστοσελίδα του Aegisub για πληροφορίες σχετικά με την απόκτηση του πηγαίου κώδικα.
|
||||
eu.WelcomeLabel2=Honek Aegisub {#BUILD_GIT_VERSION_STRING} ezarriko du zure ordenagailuan.%n%nAegisub GNU Baimen Publiko Orokorra 2. bertsioa Baimenak estalia dago. Honek esanahi du aplikazio hau edozein asmotarako erabili dezakezula ordaindu behar izan gabe, baina ez da inolako berme motarik ematen.%n%nIkusi Aegisub webgunea iturburu kodea lortzeko argibideetarako.
|
||||
id.WelcomeLabel2=Ini akan memasang Aegisub {#BUILD_GIT_VERSION_STRING} di komputer Anda.%n%nAegisub dilindungi oleh Lisensi Publik Umum GNU versi 2. Artinya Anda bisa menggunakan aplikasi ini untuk tujuan apa pun tanpad dipungut biaya, tapi tidak ada jaminan yang bisa diberikan.%n%nLihat laman situs Aegisub untuk memperoleh informasi sumber kode.
|
||||
pt_PT.WelcomeLabel2=Irá ser instalado no seu computador a versão {#BUILD_GIT_VERSION_STRING} do Aegisub.%n%nO Aegisub está protegido sob a Licença Pública Geral GNU (GPL version 2). O que significa que poderá fazer uso da aplicação para qualquer propósito, sem que seja cobrado, mas não serão dadas quaisquer tipos de garantias.%n%nVeja a página do Aegisub para mais informações sobre como obter o código-fonte.
|
||||
uk_UA.WelcomeLabel2=Зараз буде встанвлено Aegisub {#BUILD_GIT_VERSION_STRING} на ваш комп'ютер.%n%nAegisub захищено універсальною громадською ліцензією GNU, версія 2. Це означає, що ви можете використосувати цю програму для будь яких цілей безкоштовно, але, в будь-якому випадку, ми не даємо жодних гарантій.%n%nДивіться сайт Aegisub для інформації щодо отримання вихідного коду.
|
||||
zh_CN.WelcomeLabel2=将会在您的电脑上安装Aegisub {#BUILD_GIT_VERSION_STRING} 。%n%n Aegisub适用于GNU通用公共许可证第二版(GPLv2),这意味着您可以将该应用程序用于任何目的而不需要支付费用,但同时也不会得到任何形式的担保。%n%n您可以到Aegisub官网获取源代码信息。
|
||||
zh_TW.WelcomeLabel2=將會在您的電腦上安裝Aegisub {#BUILD_GIT_VERSION_STRING} 。%n%n Aegisub適用於GNU通用公共許可證第二版(GPLv2),這意味著您可以將該應用程式用於任何目的而不需要支付費用,但同時也不會得到任何形式的擔保。%n%n您可以到Aegisub官網獲取原始程式碼資訊。
|
||||
|
@ -38,61 +38,61 @@
|
||||
[Files]
|
||||
; localization (commented out ones are out of date; some don't have wxstd.mo)
|
||||
Source: ..\..\po\ar.mo; DestDir: {app}\locale\ar; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-ar.mo; DestDir: {app}\locale\ar; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-ar.mo; DestDir: {app}\locale\ar; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\bg.mo; DestDir: {app}\locale\bg; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
; Missing wxstd for Bulgarian
|
||||
Source: ..\..\po\ca.mo; DestDir: {app}\locale\ca; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-ca.mo; DestDir: {app}\locale\ca; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-ca.mo; DestDir: {app}\locale\ca; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\cs.mo; DestDir: {app}\locale\cs; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-cs.mo; DestDir: {app}\locale\cs; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-cs.mo; DestDir: {app}\locale\cs; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\da.mo; DestDir: {app}\locale\da; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-da.mo; DestDir: {app}\locale\da; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-da.mo; DestDir: {app}\locale\da; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\de.mo; DestDir: {app}\locale\de; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-de.mo; DestDir: {app}\locale\de; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-de.mo; DestDir: {app}\locale\de; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\el.mo; DestDir: {app}\locale\el; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-el.mo; DestDir: {app}\locale\el; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-el.mo; DestDir: {app}\locale\el; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\es.mo; DestDir: {app}\locale\es; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-es.mo; DestDir: {app}\locale\es; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-es.mo; DestDir: {app}\locale\es; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\eu.mo; DestDir: {app}\locale\eu; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-eu.mo; DestDir: {app}\locale\eu; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-eu.mo; DestDir: {app}\locale\eu; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\fa.mo; DestDir: {app}\locale\fa; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
; Farsi wxstd missing
|
||||
;Source: src\mo\wxstd-fa.mo; DestDir: {app}\locale\fa; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
;Source: ..\..\po\wxstd-fa.mo; DestDir: {app}\locale\fa; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\fi.mo; DestDir: {app}\locale\fi; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-fi.mo; DestDir: {app}\locale\fi; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-fi.mo; DestDir: {app}\locale\fi; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\fr_FR.mo; DestDir: {app}\locale\fr_FR; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-fr.mo; DestDir: {app}\locale\fr_FR; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-fr.mo; DestDir: {app}\locale\fr_FR; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\gl.mo; DestDir: {app}\locale\gl; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-gl_ES.mo; DestDir: {app}\locale\gl; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-gl_ES.mo; DestDir: {app}\locale\gl; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\hu.mo; DestDir: {app}\locale\hu; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-hu.mo; DestDir: {app}\locale\hu; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-hu.mo; DestDir: {app}\locale\hu; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\id.mo; DestDir: {app}\locale\id; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-id.mo; DestDir: {app}\locale\id; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-id.mo; DestDir: {app}\locale\id; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\it.mo; DestDir: {app}\locale\it; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-it.mo; DestDir: {app}\locale\it; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-it.mo; DestDir: {app}\locale\it; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\ja.mo; DestDir: {app}\locale\ja; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-ja.mo; DestDir: {app}\locale\ja; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-ja.mo; DestDir: {app}\locale\ja; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\ko.mo; DestDir: {app}\locale\ko; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-ko_KR.mo; DestDir: {app}\locale\ko; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-ko_KR.mo; DestDir: {app}\locale\ko; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\nl.mo; DestDir: {app}\locale\nl; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-nl.mo; DestDir: {app}\locale\nl; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-nl.mo; DestDir: {app}\locale\nl; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\pl.mo; DestDir: {app}\locale\pl; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-pl.mo; DestDir: {app}\locale\pl; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-pl.mo; DestDir: {app}\locale\pl; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\pt_BR.mo; DestDir: {app}\locale\pt_BR; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-pt_BR.mo; DestDir: {app}\locale\pt_BR; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-pt_BR.mo; DestDir: {app}\locale\pt_BR; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\pt_PT.mo; DestDir: {app}\locale\pt_PT; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-pt.mo; DestDir: {app}\locale\pt_PT; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-pt.mo; DestDir: {app}\locale\pt_PT; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\ru.mo; DestDir: {app}\locale\ru; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-ru.mo; DestDir: {app}\locale\ru; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-ru.mo; DestDir: {app}\locale\ru; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\sr_RS.mo; DestDir: {app}\locale\sr_RS; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\sr_RS@latin.mo; DestDir: {app}\locale\sr_RS@latin; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
; Missing wxstd for Serbian
|
||||
Source: ..\..\po\uk_UA.mo; DestDir: {app}\locale\uk_UA; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-uk_UA.mo; DestDir: {app}\locale\uk_UA; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-uk_UA.mo; DestDir: {app}\locale\uk_UA; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\vi.mo; DestDir: {app}\locale\vi; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-vi.mo; DestDir: {app}\locale\vi; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-vi.mo; DestDir: {app}\locale\vi; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\zh_CN.mo; DestDir: {app}\locale\zh_CN; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-zh_CN.mo; DestDir: {app}\locale\zh_CN; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-zh_CN.mo; DestDir: {app}\locale\zh_CN; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\zh_TW.mo; DestDir: {app}\locale\zh_TW; DestName: aegisub.mo; Flags: ignoreversion; Components: translations
|
||||
Source: src\mo\wxstd-zh_TW.mo; DestDir: {app}\locale\zh_TW; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
Source: ..\..\po\wxstd-zh_TW.mo; DestDir: {app}\locale\zh_TW; DestName: wxstd.mo; Flags: ignoreversion; Components: translations
|
||||
|
||||
|
@ -3069,6 +3069,18 @@ msgstr ""
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
#: ../src/command/help.cpp
|
||||
msgid "&Joysound Exporter"
|
||||
msgstr ""
|
||||
|
||||
#: ../src/command/help.cpp
|
||||
msgid "Joysound Exporter"
|
||||
msgstr ""
|
||||
|
||||
#: ../src/command/help.cpp
|
||||
msgid "Export karaoke from Joysound"
|
||||
msgstr ""
|
||||
|
||||
#: ../src/command/help.cpp:119
|
||||
msgid "Visit Aegisub's official website"
|
||||
msgstr ""
|
||||
|
16
po/fr_FR.po
@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Aegisub 3.2.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-08-24 16:41+0200\n"
|
||||
"POT-Creation-Date: 2014-07-01 10:53-0700\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Cirrus Wazza <cirrus_wazza@gmx.fr>\n"
|
||||
"Language-Team: Céréales Killer <cerkil@free.fr>\n"
|
||||
@ -12,7 +12,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"X-Poedit-Bookmarks: -1,596,-1,-1,-1,-1,-1,-1,-1,-1\n"
|
||||
"X-Generator: Poedit 1.8.4\n"
|
||||
"X-Generator: Poedit 2.2.4\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: ../src/dialog_shift_times.cpp:92
|
||||
@ -3189,6 +3189,18 @@ msgstr "Site &web"
|
||||
msgid "Website"
|
||||
msgstr "Site web"
|
||||
|
||||
#: ../src/command/help.cpp
|
||||
msgid "&Joysound Exporter"
|
||||
msgstr "&Joysound Exporter"
|
||||
|
||||
#: ../src/command/help.cpp
|
||||
msgid "Joysound Exporter"
|
||||
msgstr "Joysound Exporter"
|
||||
|
||||
#: ../src/command/help.cpp
|
||||
msgid "Export karaoke from Joysound"
|
||||
msgstr "Exporter un karaoke Joysound"
|
||||
|
||||
#: ../src/command/help.cpp:119
|
||||
msgid "Visit Aegisub's official website"
|
||||
msgstr "Visitez le site officiel d'Aegisub"
|
||||
|
@ -6,7 +6,7 @@ src_CPPFLAGS := -I$(d) -I.. -I$(d)include -I$(TOP)libaegisub/include -I$(TOP)bui
|
||||
$(CFLAGS_PTHREAD) $(CFLAGS_FFTW3) $(CFLAGS_ICU) $(CPPFLAGS_BOOST)
|
||||
src_CXXFLAGS := $(CXXFLAGS_WX)
|
||||
src_LIBS := $(LIBS_GL) $(LIBS_PTHREAD) $(LIBS_WX) $(LIBS_FREETYPE) \
|
||||
$(LIBS_LIBASS) $(LIBS_FONTCONFIG) $(LIBS_FFTW3) $(LIBS_BOOST) $(LIBS_ICU)
|
||||
$(LIBS_LIBASS) $(LIBS_FONTCONFIG) $(LIBS_FFTW3) $(LIBS_BOOST) $(LIBS_ICU)
|
||||
src_PCH := $(d)agi_pre.h
|
||||
src_INSTALLNAME := $(AEGISUB_COMMAND)
|
||||
|
||||
@ -111,11 +111,16 @@ src_OBJ := \
|
||||
$(d)video_provider_yuv4mpeg.o \
|
||||
$(d)video_slider.o \
|
||||
$(d)visual_feature.o \
|
||||
$(LIBS_LUA) \
|
||||
$(TOP)lib/libaegisub.a \
|
||||
$(TOP)lib/libluabins.a \
|
||||
$(TOP)lib/libresrc.a \
|
||||
|
||||
ifeq (no, $(SYSTEM_LUAJIT))
|
||||
src_OBJ += $(LIBS_LUA)
|
||||
else
|
||||
src_LIBS += $(LIBS_LUA)
|
||||
endif
|
||||
|
||||
ifeq (yes, $(BUILD_DARWIN))
|
||||
src_OBJ += $(d)font_file_lister_coretext.o
|
||||
src_OBJ += $(patsubst %.mm,%.o,$(sort $(wildcard $(d)osx/*.mm)))
|
||||
|
@ -1088,8 +1088,9 @@ static void parseSegmentInfo(MatroskaFile *mf,uint64_t toplen) {
|
||||
|
||||
static void parseFirstCluster(MatroskaFile *mf,uint64_t toplen) {
|
||||
uint64_t end = filepos(mf) + toplen;
|
||||
int tracknum = -1;
|
||||
int i = 0;
|
||||
|
||||
mf->seen.Cluster = 1;
|
||||
mf->firstTimecode = 0;
|
||||
|
||||
FOREACH(mf,toplen)
|
||||
@ -1097,22 +1098,40 @@ static void parseFirstCluster(MatroskaFile *mf,uint64_t toplen) {
|
||||
mf->firstTimecode += readUInt(mf,(unsigned)len);
|
||||
break;
|
||||
case 0xa3: // BlockEx
|
||||
readVLUInt(mf); // track number
|
||||
mf->firstTimecode += readSInt(mf, 2);
|
||||
start = filepos(mf);
|
||||
tracknum = readVLUInt(mf); // track number
|
||||
|
||||
skipbytes(mf,end - filepos(mf));
|
||||
return;
|
||||
for (i = 0; i < mf->nTracks; ++i) {
|
||||
if (mf->Tracks[i]->Number == tracknum && mf->Tracks[i]->Type == TT_VIDEO) {
|
||||
mf->firstTimecode += readSInt(mf, 2);
|
||||
mf->seen.Cluster = 1;
|
||||
skipbytes(mf,end - filepos(mf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
skipbytes(mf, len - (filepos(mf) - start));
|
||||
break;
|
||||
case 0xa0: // BlockGroup
|
||||
FOREACH(mf,len)
|
||||
case 0xa1: // Block
|
||||
readVLUInt(mf); // track number
|
||||
mf->firstTimecode += readSInt(mf,2);
|
||||
case 0xa1: // Block
|
||||
start = filepos(mf);
|
||||
tracknum = readVLUInt(mf); // track number
|
||||
|
||||
skipbytes(mf,end - filepos(mf));
|
||||
return;
|
||||
for (i = 0; i < mf->nTracks; ++i) {
|
||||
if (mf->Tracks[i]->Number == tracknum && mf->Tracks[i]->Type == TT_VIDEO) {
|
||||
mf->firstTimecode += readSInt(mf, 2);
|
||||
mf->seen.Cluster = 1;
|
||||
skipbytes(mf,end - filepos(mf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
skipbytes(mf, len - (filepos(mf) - start));
|
||||
break;
|
||||
ENDFOR(mf);
|
||||
break;
|
||||
ENDFOR(mf);
|
||||
|
||||
}
|
||||
|
||||
static void parseVideoInfo(MatroskaFile *mf,uint64_t toplen,struct TrackInfo *ti) {
|
||||
|
@ -262,3 +262,11 @@ void AssKaraoke::SetLineTimes(int start_time, int end_time) {
|
||||
}
|
||||
syls[idx].duration = end_time - syls[idx].start_time;
|
||||
}
|
||||
|
||||
std::string AssKaraoke::GetStrippedText(int syl_idx) const {
|
||||
return syls[syl_idx].text;
|
||||
}
|
||||
|
||||
void AssKaraoke::SetStrippedText(int syl_idx, std::string new_text) {
|
||||
syls[syl_idx].text = new_text;
|
||||
}
|
||||
|
@ -82,5 +82,10 @@ public:
|
||||
/// Set the tag type for all karaoke tags in this line
|
||||
void SetTagType(std::string const& new_type);
|
||||
|
||||
/// Get syllab's text stripped of k tag
|
||||
std::string GetStrippedText(int syl_idx) const;
|
||||
/// Set syllab's text stripped of k tag
|
||||
void SetStrippedText(int syl_idx, std::string new_text);
|
||||
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceSyllablesChanged, AddSyllablesChangedListener)
|
||||
};
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include <wx/intl.h>
|
||||
|
||||
AssStyle::AssStyle() {
|
||||
std::fill(Margin.begin(), Margin.end(), 10);
|
||||
std::fill(Margin.begin(), Margin.end(), 30);
|
||||
|
||||
UpdateData();
|
||||
}
|
||||
|
@ -40,11 +40,11 @@ class AssStyle final : public AssEntry, public AssEntryListHook {
|
||||
|
||||
public:
|
||||
std::string name = "Default"; ///< Name of the style; must be case-insensitively unique within a file despite being case-sensitive
|
||||
std::string font = "Arial"; ///< Font face name
|
||||
double fontsize = 20.; ///< Font size
|
||||
std::string font = "Amaranth"; ///< Font face name
|
||||
double fontsize = 60.; ///< Font size
|
||||
|
||||
agi::Color primary{ 255, 255, 255 }; ///< Default text color
|
||||
agi::Color secondary{ 255, 0, 0 }; ///< Text color for not-yet-reached karaoke syllables
|
||||
agi::Color primary{ 255, 132, 0 }; ///< Default text color
|
||||
agi::Color secondary{ 255, 255, 255 }; ///< Text color for not-yet-reached karaoke syllables
|
||||
agi::Color outline{ 0, 0, 0 }; ///< Outline color
|
||||
agi::Color shadow{ 0, 0, 0 }; ///< Shadow color
|
||||
|
||||
@ -60,7 +60,7 @@ public:
|
||||
int borderstyle = 1; ///< 1: Normal; 3: Opaque box; others are unused in Aegisub
|
||||
double outline_w = 2.; ///< Outline width in pixels
|
||||
double shadow_w = 2.; ///< Shadow distance in pixels
|
||||
int alignment = 2; ///< \an-style line alignment
|
||||
int alignment = 8; ///< \an-style line alignment
|
||||
std::array<int, 3> Margin; ///< Left / Right / Vertical
|
||||
int encoding = 1; ///< ASS font encoding needed for some non-unicode fonts
|
||||
|
||||
|
@ -891,6 +891,14 @@ void AudioDisplay::PaintMarkers(wxDC &dc, TimeRange updtime)
|
||||
if (marker->GetFeet() & AudioMarker::Feet_Right)
|
||||
PaintFoot(dc, marker_x, 1);
|
||||
}
|
||||
|
||||
|
||||
if (OPT_GET("Timing/Tap To Time")->GetBool()) {
|
||||
dc.SetBrush(wxBrush(*wxGREEN));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
int marker_x = RelativeXFromTime(controller->GetTimingController()->GetTapMarkerPosition());
|
||||
PaintTapMarker(dc, marker_x);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDisplay::PaintFoot(wxDC &dc, int marker_x, int dir)
|
||||
@ -901,6 +909,12 @@ void AudioDisplay::PaintFoot(wxDC &dc, int marker_x, int dir)
|
||||
dc.DrawPolygon(3, foot_bot, marker_x, audio_top+audio_height);
|
||||
}
|
||||
|
||||
void AudioDisplay::PaintTapMarker(wxDC &dc, int marker_x)
|
||||
{
|
||||
wxPoint arrow[3] = { wxPoint(-foot_size * 2, 0), wxPoint(0, -foot_size * 2), wxPoint(foot_size * 2, 0) };
|
||||
dc.DrawPolygon(3, arrow, marker_x, audio_top+audio_height);
|
||||
}
|
||||
|
||||
void AudioDisplay::PaintLabels(wxDC &dc, TimeRange updtime)
|
||||
{
|
||||
std::vector<AudioLabelProvider::AudioLabel> labels;
|
||||
@ -1229,6 +1243,7 @@ void AudioDisplay::OnAudioOpen(agi::AudioProvider *provider)
|
||||
OPT_SUB("Colour/Audio Display/Spectrum", &AudioDisplay::ReloadRenderingSettings, this),
|
||||
OPT_SUB("Colour/Audio Display/Waveform", &AudioDisplay::ReloadRenderingSettings, this),
|
||||
OPT_SUB("Audio/Renderer/Spectrum/Quality", &AudioDisplay::ReloadRenderingSettings, this),
|
||||
OPT_SUB("Timing/Tap To Time", &AudioDisplay::OnTapMarkerChanged, this),
|
||||
});
|
||||
OnTimingController();
|
||||
}
|
||||
@ -1254,10 +1269,12 @@ void AudioDisplay::OnTimingController()
|
||||
timing_controller->AddMarkerMovedListener(&AudioDisplay::OnMarkerMoved, this);
|
||||
timing_controller->AddUpdatedPrimaryRangeListener(&AudioDisplay::OnSelectionChanged, this);
|
||||
timing_controller->AddUpdatedStyleRangesListener(&AudioDisplay::OnStyleRangesChanged, this);
|
||||
timing_controller->AddUpdatedTapMarkerListener(&AudioDisplay::OnTapMarkerChanged, this);
|
||||
|
||||
OnStyleRangesChanged();
|
||||
OnMarkerMoved();
|
||||
OnSelectionChanged();
|
||||
OnTapMarkerChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1341,6 +1358,12 @@ void AudioDisplay::OnStyleRangesChanged()
|
||||
RefreshRect(wxRect(0, audio_top, GetClientSize().GetWidth(), audio_height), false);
|
||||
}
|
||||
|
||||
void AudioDisplay::OnTapMarkerChanged()
|
||||
{
|
||||
RefreshRect(wxRect(0, audio_top, GetClientSize().GetWidth(), audio_height), false);
|
||||
}
|
||||
|
||||
|
||||
void AudioDisplay::OnMarkerMoved()
|
||||
{
|
||||
RefreshRect(wxRect(0, audio_top, GetClientSize().GetWidth(), audio_height), false);
|
||||
|
@ -169,6 +169,11 @@ class AudioDisplay: public wxWindow {
|
||||
/// @param dir -1 for left, 1 for right
|
||||
void PaintFoot(wxDC &dc, int marker_x, int dir);
|
||||
|
||||
/// Draw an indicator for the tap marker
|
||||
/// @param dc DC to paint to
|
||||
/// @param marker_x Position of the tap marker
|
||||
void PaintTapMarker(wxDC &dc, int marker_x);
|
||||
|
||||
/// Paint the labels in a time range
|
||||
/// @param dc DC to paint to
|
||||
/// @param updtime Time range to repaint
|
||||
@ -205,6 +210,7 @@ class AudioDisplay: public wxWindow {
|
||||
void OnStyleRangesChanged();
|
||||
void OnTimingController();
|
||||
void OnMarkerMoved();
|
||||
void OnTapMarkerChanged();
|
||||
|
||||
public:
|
||||
AudioDisplay(wxWindow *parent, AudioController *controller, agi::Context *context);
|
||||
|
@ -64,6 +64,7 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c)
|
||||
, file_changed(c->ass->AddCommitListener(&AudioKaraoke::OnFileChanged, this))
|
||||
, audio_opened(c->project->AddAudioProviderListener(&AudioKaraoke::OnAudioOpened, this))
|
||||
, active_line_changed(c->selectionController->AddActiveLineListener(&AudioKaraoke::OnActiveLineChanged, this))
|
||||
, tap_to_time_toggled(OPT_SUB("Timing/Tap To Time", &AudioKaraoke::OnTapMarkerChanged, this))
|
||||
, kara(agi::make_unique<AssKaraoke>())
|
||||
{
|
||||
using std::bind;
|
||||
@ -134,6 +135,7 @@ void AudioKaraoke::SetEnabled(bool en) {
|
||||
if (enabled) {
|
||||
LoadFromLine();
|
||||
c->audioController->SetTimingController(CreateKaraokeTimingController(c, kara.get(), file_changed));
|
||||
c->audioController->GetTimingController()->AddUpdatedTapMarkerListener(&AudioKaraoke::OnTapMarkerChanged, this);
|
||||
Refresh(false);
|
||||
}
|
||||
else {
|
||||
@ -218,7 +220,16 @@ void AudioKaraoke::RenderText() {
|
||||
|
||||
// Draw each character in the line
|
||||
int y = (bmp_size.GetHeight() - char_height) / 2;
|
||||
for (size_t i = 0; i < spaced_text.size(); ++i)
|
||||
for (size_t i = 0; i < spaced_text.size(); ++i) {
|
||||
if (!(tap_syl_start <= i && i < tap_syl_end)) {
|
||||
// Only draw with normal color if _not_ the tap syllable
|
||||
dc.DrawText(spaced_text[i], char_x[i], y);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw marked syllable
|
||||
dc.SetTextForeground(*wxGREEN);
|
||||
for (size_t i = tap_syl_start; i < tap_syl_end; ++i)
|
||||
dc.DrawText(spaced_text[i], char_x[i], y);
|
||||
|
||||
// Draw the lines between each syllable
|
||||
@ -329,6 +340,26 @@ void AudioKaraoke::OnScrollTimer(wxTimerEvent &) {
|
||||
split_area->Refresh(false);
|
||||
}
|
||||
|
||||
void AudioKaraoke::OnTapMarkerChanged() {
|
||||
tap_syl_start = 0;
|
||||
tap_syl_end = 0;
|
||||
|
||||
if (OPT_GET("Timing/Tap To Time")->GetBool() && kara->size() > 0) {
|
||||
const AudioTimingController *tc = c->audioController->GetTimingController();
|
||||
const size_t marker_idx = tc->GetTapMarkerIndex();
|
||||
if (marker_idx > 0) {
|
||||
tap_syl_start = syl_start_points[marker_idx - 1];
|
||||
tap_syl_end =
|
||||
(marker_idx < syl_start_points.size() ?
|
||||
syl_start_points[marker_idx] :
|
||||
spaced_text.size());
|
||||
}
|
||||
}
|
||||
|
||||
RenderText();
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
void AudioKaraoke::LoadFromLine() {
|
||||
scroll_x = 0;
|
||||
scroll_timer.Stop();
|
||||
|
@ -67,6 +67,7 @@ class AudioKaraoke final : public wxWindow {
|
||||
agi::signal::Connection audio_opened; ///< Audio opened connection
|
||||
agi::signal::Connection audio_closed; ///< Audio closed connection
|
||||
agi::signal::Connection active_line_changed;
|
||||
agi::signal::Connection tap_to_time_toggled;
|
||||
|
||||
/// Currently active dialogue line
|
||||
AssDialogue *active_line = nullptr;
|
||||
@ -105,6 +106,9 @@ class AudioKaraoke final : public wxWindow {
|
||||
|
||||
wxFont split_font; ///< Font used in the split/join interface
|
||||
|
||||
size_t tap_syl_start = 0; ///< Tap-to-time syllable start character index
|
||||
size_t tap_syl_end = 0; ///< Tap-to-time syllable end character index
|
||||
|
||||
bool enabled = false; ///< Is karaoke mode enabled?
|
||||
|
||||
wxButton *accept_button; ///< Accept pending splits button
|
||||
@ -143,6 +147,7 @@ class AudioKaraoke final : public wxWindow {
|
||||
void OnSize(wxSizeEvent &event);
|
||||
void OnAudioOpened(agi::AudioProvider *provider);
|
||||
void OnScrollTimer(wxTimerEvent &event);
|
||||
void OnTapMarkerChanged();
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
|
@ -57,6 +57,9 @@ protected:
|
||||
/// One or more rendering style ranges have changed in the timing controller.
|
||||
agi::signal::Signal<> AnnounceUpdatedStyleRanges;
|
||||
|
||||
/// The tap marker has changed in the timing controller.
|
||||
agi::signal::Signal<> AnnounceUpdatedTapMarker;
|
||||
|
||||
public:
|
||||
/// @brief Get any warning message to show in the audio display
|
||||
/// @return The warning message to show, may be empty if there is none
|
||||
@ -86,6 +89,12 @@ public:
|
||||
/// @param[out] ranges Rendering ranges will be added to this
|
||||
virtual void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const = 0;
|
||||
|
||||
/// @brief Return the position of the tap marker
|
||||
virtual int GetTapMarkerPosition() const = 0;
|
||||
|
||||
/// @brief Return the index of the tap marker
|
||||
virtual size_t GetTapMarkerIndex() const = 0;
|
||||
|
||||
enum NextMode {
|
||||
/// Advance to the next timing unit, whether it's a line or a sub-part
|
||||
/// of a line such as a karaoke syllable
|
||||
@ -138,6 +147,15 @@ public:
|
||||
/// @param delta Amount to add in centiseconds
|
||||
virtual void ModifyStart(int delta) = 0;
|
||||
|
||||
/// Move tap marker position to given position
|
||||
/// @param position to move marker to
|
||||
virtual void MoveTapMarker(int ms) = 0;
|
||||
|
||||
/// Go to next tap marker
|
||||
/// @return True if moved to the next marker, False if tap marker is already
|
||||
/// the last marker of the line
|
||||
virtual bool NextTapMarker() = 0;
|
||||
|
||||
/// @brief Determine if a position is close to a draggable marker
|
||||
/// @param ms The time in milliseconds to test
|
||||
/// @param sensitivity Distance in milliseconds to consider markers as nearby
|
||||
@ -147,9 +165,16 @@ public:
|
||||
/// controlling the mouse cursor.
|
||||
virtual bool IsNearbyMarker(int ms, int sensitivity, bool alt_down) const = 0;
|
||||
|
||||
/// @brief Return the text of the currently selected syllab
|
||||
virtual std::string GetCurrentSylText() const { return ""; }
|
||||
|
||||
/// @ brief Set the text for the currently selected syllab
|
||||
virtual void SetCurrentSylText(std::string new_text) {}
|
||||
|
||||
/// @brief The user pressed the left mouse button on the audio
|
||||
/// @param ms The time in milliseconds the user clicked
|
||||
/// @param ctrl_down Is the user currently holding the ctrl key down?
|
||||
/// @param alt_down Is the user currently holding the alt key down?
|
||||
/// @param sensitivity Distance in milliseconds to consider existing markers
|
||||
/// @param snap_range Maximum snapping range in milliseconds
|
||||
/// @return All audio markers at the clicked position which are eligible
|
||||
@ -177,6 +202,7 @@ public:
|
||||
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedPrimaryRange, AddUpdatedPrimaryRangeListener)
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedStyleRanges, AddUpdatedStyleRangesListener)
|
||||
DEFINE_SIGNAL_ADDERS(AnnounceUpdatedTapMarker, AddUpdatedTapMarkerListener)
|
||||
};
|
||||
|
||||
/// @brief Create a standard dialogue audio timing controller
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "ass_dialogue.h"
|
||||
#include "ass_file.h"
|
||||
#include "audio_controller.h"
|
||||
#include "audio_marker.h"
|
||||
#include "audio_rendering_style.h"
|
||||
#include "audio_timing.h"
|
||||
@ -327,6 +328,12 @@ class AudioTimingControllerDialogue final : public AudioTimingController {
|
||||
/// The time which was clicked on for alt-dragging mode
|
||||
int clicked_ms;
|
||||
|
||||
/// Index of marker serving as tap marker
|
||||
/// For AudioTimingControllerDialogue:
|
||||
/// - 0 is left marker
|
||||
/// - 1 is right marker
|
||||
size_t tap_marker_idx = 0;
|
||||
|
||||
/// Autocommit option
|
||||
const agi::OptionValue *auto_commit = OPT_GET("Audio/Auto/Commit");
|
||||
const agi::OptionValue *inactive_line_mode = OPT_GET("Audio/Inactive Lines Display Mode");
|
||||
@ -384,6 +391,8 @@ class AudioTimingControllerDialogue final : public AudioTimingController {
|
||||
public:
|
||||
// AudioMarkerProvider interface
|
||||
void GetMarkers(const TimeRange &range, AudioMarkerVector &out_markers) const override;
|
||||
int GetTapMarkerPosition() const override;
|
||||
size_t GetTapMarkerIndex() const override;
|
||||
|
||||
// AudioTimingController interface
|
||||
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const override;
|
||||
@ -395,9 +404,11 @@ public:
|
||||
void AddLeadOut() override;
|
||||
void ModifyLength(int delta, bool shift_following) override;
|
||||
void ModifyStart(int delta) override;
|
||||
void MoveTapMarker(int ms) override;
|
||||
bool NextTapMarker() override;
|
||||
bool IsNearbyMarker(int ms, int sensitivity, bool alt_down) const override;
|
||||
std::vector<AudioMarker*> OnLeftClick(int ms, bool ctrl_down, bool alt_down, int sensitivity, int snap_range) override;
|
||||
std::vector<AudioMarker*> OnRightClick(int ms, bool, int sensitivity, int snap_range) override;
|
||||
std::vector<AudioMarker*> OnRightClick(int ms, bool ctrl_down, int sensitivity, int snap_range) override;
|
||||
void OnMarkerDrag(std::vector<AudioMarker*> const& markers, int new_position, int snap_range) override;
|
||||
|
||||
// We have no warning messages currently, maybe add the old "Modified" message back later?
|
||||
@ -447,6 +458,24 @@ void AudioTimingControllerDialogue::GetMarkers(const TimeRange &range, AudioMark
|
||||
video_position_provider.GetMarkers(range, out_markers);
|
||||
}
|
||||
|
||||
int AudioTimingControllerDialogue::GetTapMarkerPosition() const
|
||||
{
|
||||
assert(tap_marker_idx <= 1);
|
||||
|
||||
if (tap_marker_idx == 0) {
|
||||
return *active_line.GetLeftMarker();
|
||||
}
|
||||
else {
|
||||
return *active_line.GetRightMarker();
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioTimingControllerDialogue::GetTapMarkerIndex() const
|
||||
{
|
||||
assert(tap_marker_idx <= 1);
|
||||
return tap_marker_idx;
|
||||
}
|
||||
|
||||
void AudioTimingControllerDialogue::OnSelectedSetChanged()
|
||||
{
|
||||
RegenerateSelectedLines();
|
||||
@ -526,6 +555,7 @@ void AudioTimingControllerDialogue::DoCommit(bool user_triggered)
|
||||
void AudioTimingControllerDialogue::Revert()
|
||||
{
|
||||
commit_id = -1;
|
||||
tap_marker_idx = 0;
|
||||
|
||||
if (AssDialogue *line = context->selectionController->GetActiveLine())
|
||||
{
|
||||
@ -535,6 +565,7 @@ void AudioTimingControllerDialogue::Revert()
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
if (inactive_line_mode->GetInt() == 0)
|
||||
AnnounceUpdatedStyleRanges();
|
||||
AnnounceUpdatedTapMarker();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -570,6 +601,35 @@ void AudioTimingControllerDialogue::ModifyStart(int delta) {
|
||||
std::min<int>(*m + delta * 10, *active_line.GetRightMarker()), 0);
|
||||
}
|
||||
|
||||
void AudioTimingControllerDialogue::MoveTapMarker(int ms) {
|
||||
// Fix rounding error
|
||||
ms = (ms + 5) / 10 * 10;
|
||||
|
||||
DialogueTimingMarker *left = active_line.GetLeftMarker();
|
||||
DialogueTimingMarker *right = active_line.GetRightMarker();
|
||||
|
||||
clicked_ms = INT_MIN;
|
||||
if (tap_marker_idx == 0) {
|
||||
// Moving left marker (start time of the line)
|
||||
if (ms > *right) SetMarkers({ right }, ms, 0);
|
||||
SetMarkers({ left }, ms, 0);
|
||||
}
|
||||
else {
|
||||
// Moving right marker (end time of the line)
|
||||
if (ms < *left) SetMarkers({ left }, ms, 0);
|
||||
SetMarkers({ right }, ms, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioTimingControllerDialogue::NextTapMarker() {
|
||||
if (tap_marker_idx == 0) {
|
||||
tap_marker_idx = 1;
|
||||
AnnounceUpdatedTapMarker();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioTimingControllerDialogue::IsNearbyMarker(int ms, int sensitivity, bool alt_down) const
|
||||
{
|
||||
assert(sensitivity >= 0);
|
||||
@ -609,6 +669,8 @@ std::vector<AudioMarker*> AudioTimingControllerDialogue::OnLeftClick(int ms, boo
|
||||
ret = drag_timing->GetBool() ? GetRightMarkers() : jump;
|
||||
// Get ret before setting as setting may swap left/right
|
||||
SetMarkers(jump, ms, snap_range);
|
||||
// Also change tap marker to left marker
|
||||
tap_marker_idx = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -627,18 +689,36 @@ std::vector<AudioMarker*> AudioTimingControllerDialogue::OnLeftClick(int ms, boo
|
||||
|
||||
// Left-click within drag range should still move the left marker to the
|
||||
// clicked position, but not the right marker
|
||||
if (clicked == left)
|
||||
if (clicked == left) {
|
||||
SetMarkers(ret, ms, snap_range);
|
||||
}
|
||||
|
||||
// Also change tap marker
|
||||
if (clicked == left) {
|
||||
tap_marker_idx = 0;
|
||||
}
|
||||
else {
|
||||
tap_marker_idx = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<AudioMarker*> AudioTimingControllerDialogue::OnRightClick(int ms, bool, int sensitivity, int snap_range)
|
||||
std::vector<AudioMarker*> AudioTimingControllerDialogue::OnRightClick(int ms, bool ctrl_down, int sensitivity, int snap_range)
|
||||
{
|
||||
clicked_ms = INT_MIN;
|
||||
std::vector<AudioMarker*> ret = GetRightMarkers();
|
||||
SetMarkers(ret, ms, snap_range);
|
||||
return ret;
|
||||
if (ctrl_down) {
|
||||
// Ctrl-right-click: play audio
|
||||
context->audioController->PlayToEnd(ms);
|
||||
return {};
|
||||
}
|
||||
else {
|
||||
// Normal right-click: move right marker
|
||||
clicked_ms = INT_MIN;
|
||||
std::vector<AudioMarker*> ret = GetRightMarkers();
|
||||
SetMarkers(ret, ms, snap_range);
|
||||
tap_marker_idx = 1;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioTimingControllerDialogue::OnMarkerDrag(std::vector<AudioMarker*> const& markers, int new_position, int snap_range)
|
||||
|
@ -81,6 +81,13 @@ class AudioTimingControllerKaraoke final : public AudioTimingController {
|
||||
|
||||
size_t cur_syl = 0; ///< Index of currently selected syllable in the line
|
||||
|
||||
/// Index of marker serving as tap marker
|
||||
/// For AudioControllerTimingKaraoke:
|
||||
/// - 0 is start marker
|
||||
/// - 1 to markers.size() is a regular syllable marker
|
||||
/// - markers.size() + 1 is end marker
|
||||
size_t tap_marker_idx = 0;
|
||||
|
||||
/// Pen used for the mid-syllable markers
|
||||
Pen separator_pen{"Colour/Audio Display/Syllable Boundaries", "Audio/Line Boundaries Thickness", wxPENSTYLE_DOT};
|
||||
/// Pen used for the start-of-line marker
|
||||
@ -112,11 +119,16 @@ class AudioTimingControllerKaraoke final : public AudioTimingController {
|
||||
void DoCommit();
|
||||
void ApplyLead(bool announce_primary);
|
||||
int MoveMarker(KaraokeMarker *marker, int new_position);
|
||||
void AnnounceChanges(int syl);
|
||||
void MoveStartMarker(int new_position);
|
||||
void MoveEndMarker(int new_position);
|
||||
void CompressMarkers(size_t from, size_t to, int new_position);
|
||||
void AnnounceChanges(bool announce_primary);
|
||||
|
||||
public:
|
||||
// AudioTimingController implementation
|
||||
void GetMarkers(const TimeRange &range, AudioMarkerVector &out_markers) const override;
|
||||
int GetTapMarkerPosition() const override;
|
||||
size_t GetTapMarkerIndex() const override;
|
||||
wxString GetWarningMessage() const override { return ""; }
|
||||
TimeRange GetIdealVisibleTimeRange() const override;
|
||||
void GetRenderingStyles(AudioRenderingStyleRanges &ranges) const override;
|
||||
@ -131,10 +143,14 @@ public:
|
||||
void AddLeadOut() override;
|
||||
void ModifyLength(int delta, bool shift_following) override;
|
||||
void ModifyStart(int delta) override;
|
||||
void MoveTapMarker(int ms) override;
|
||||
bool NextTapMarker() override;
|
||||
bool IsNearbyMarker(int ms, int sensitivity, bool) const override;
|
||||
std::vector<AudioMarker*> OnLeftClick(int ms, bool, bool, int sensitivity, int) override;
|
||||
std::vector<AudioMarker*> OnRightClick(int ms, bool, int, int) override;
|
||||
std::vector<AudioMarker*> OnRightClick(int ms, bool ctrl_down, int, int) override;
|
||||
void OnMarkerDrag(std::vector<AudioMarker*> const& marker, int new_position, int) override;
|
||||
std::string GetCurrentSylText() const override;
|
||||
void SetCurrentSylText(std::string new_text) override;
|
||||
|
||||
AudioTimingControllerKaraoke(agi::Context *c, AssKaraoke *kara, agi::signal::Connection& file_changed);
|
||||
};
|
||||
@ -235,10 +251,29 @@ void AudioTimingControllerKaraoke::GetMarkers(TimeRange const& range, AudioMarke
|
||||
video_position_provider.GetMarkers(range, out);
|
||||
}
|
||||
|
||||
int AudioTimingControllerKaraoke::GetTapMarkerPosition() const {
|
||||
assert(tap_marker_idx <= markers.size() + 1);
|
||||
|
||||
if (tap_marker_idx == 0) {
|
||||
return start_marker;
|
||||
}
|
||||
else if (tap_marker_idx < markers.size() + 1) {
|
||||
return markers[tap_marker_idx-1];
|
||||
}
|
||||
else {
|
||||
return end_marker;
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioTimingControllerKaraoke::GetTapMarkerIndex() const {
|
||||
assert(tap_marker_idx <= markers.size() + 1);
|
||||
return tap_marker_idx;
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::DoCommit() {
|
||||
active_line->Text = kara->GetText();
|
||||
file_changed_slot.Block();
|
||||
commit_id = c->ass->Commit(_("karaoke timing"), AssFile::COMMIT_DIAG_TEXT, commit_id, active_line);
|
||||
commit_id = c->ass->Commit(_("karaoke timing"), AssFile::COMMIT_DIAG_TEXT | AssFile::COMMIT_DIAG_TIME, commit_id, active_line);
|
||||
file_changed_slot.Unblock();
|
||||
pending_changes = false;
|
||||
}
|
||||
@ -254,6 +289,7 @@ void AudioTimingControllerKaraoke::Revert() {
|
||||
cur_syl = 0;
|
||||
commit_id = -1;
|
||||
pending_changes = false;
|
||||
tap_marker_idx = 0;
|
||||
|
||||
start_marker.Move(active_line->Start);
|
||||
end_marker.Move(active_line->End);
|
||||
@ -273,6 +309,7 @@ void AudioTimingControllerKaraoke::Revert() {
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
AnnounceUpdatedStyleRanges();
|
||||
AnnounceMarkerMoved();
|
||||
AnnounceUpdatedTapMarker();
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::AddLeadIn() {
|
||||
@ -293,7 +330,7 @@ void AudioTimingControllerKaraoke::ApplyLead(bool announce_primary) {
|
||||
kara->SetLineTimes(start_marker, end_marker);
|
||||
if (!announce_primary)
|
||||
AnnounceUpdatedStyleRanges();
|
||||
AnnounceChanges(announce_primary ? cur_syl : cur_syl + 2);
|
||||
AnnounceChanges(announce_primary);
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::ModifyLength(int delta, bool shift_following) {
|
||||
@ -314,13 +351,63 @@ void AudioTimingControllerKaraoke::ModifyLength(int delta, bool shift_following)
|
||||
for (; cur != end; cur += step) {
|
||||
MoveMarker(&markers[cur], markers[cur] + delta * 10);
|
||||
}
|
||||
AnnounceChanges(cur_syl);
|
||||
AnnounceChanges(true);
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::ModifyStart(int delta) {
|
||||
if (cur_syl == 0) return;
|
||||
MoveMarker(&markers[cur_syl - 1], markers[cur_syl - 1] + delta * 10);
|
||||
AnnounceChanges(cur_syl);
|
||||
AnnounceChanges(true);
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::MoveTapMarker(int ms) {
|
||||
// Fix rounding error
|
||||
ms = (ms + 5) / 10 * 10;
|
||||
|
||||
// Get syllable this time falls within
|
||||
const size_t syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), ms));
|
||||
|
||||
// Tapping automatically moves all of the necessary markers for the tap
|
||||
// marker to land at the current audio position. Intuitively, it "pushes" or
|
||||
// "compresses" the markers blocking the tap marker's way so they all end up
|
||||
// in the same position. The expectation is that the markers will reach their
|
||||
// proper position once the user finishes tapping to the line
|
||||
if (tap_marker_idx == 0) {
|
||||
// Moving the start time of first syllable (i.e. start time of the line)
|
||||
if (ms > end_marker) MoveEndMarker(ms);
|
||||
if (syl > 0) CompressMarkers(syl-1, 0, ms);
|
||||
MoveStartMarker(ms);
|
||||
}
|
||||
else if (tap_marker_idx < markers.size() + 1) {
|
||||
// Moving the end time of a non-end syllable
|
||||
if (ms < start_marker) MoveStartMarker(ms);
|
||||
else if (ms > end_marker) MoveEndMarker(ms);
|
||||
if (syl < tap_marker_idx) {
|
||||
// Moving markers left
|
||||
CompressMarkers(syl, tap_marker_idx-1, ms);
|
||||
}
|
||||
else {
|
||||
// Moving markers right
|
||||
CompressMarkers(syl-1, tap_marker_idx-1, ms);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Moving the end time of last syllable (i.e. end time of the line)
|
||||
if (ms < start_marker) MoveStartMarker(ms);
|
||||
if (syl < markers.size()) CompressMarkers(0, markers.size()-1, ms);
|
||||
MoveEndMarker(ms);
|
||||
}
|
||||
|
||||
AnnounceChanges(true);
|
||||
}
|
||||
|
||||
bool AudioTimingControllerKaraoke::NextTapMarker() {
|
||||
if (tap_marker_idx < markers.size() + 1) {
|
||||
++tap_marker_idx;
|
||||
AnnounceUpdatedTapMarker();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioTimingControllerKaraoke::IsNearbyMarker(int ms, int sensitivity, bool) const {
|
||||
@ -350,18 +437,36 @@ std::vector<AudioMarker*> AudioTimingControllerKaraoke::OnLeftClick(int ms, bool
|
||||
|
||||
cur_syl = syl;
|
||||
|
||||
// Change tap marker
|
||||
// Selecting a syllable moves the marker to the _end_ of that syllable, such
|
||||
// that the next tap determines when that syllable ends. This behavior is
|
||||
// more intuitive when coupled with AudioKaraoke's tap syllable highlight.
|
||||
if (ms < start_marker.GetPosition()) {
|
||||
tap_marker_idx = 0;
|
||||
}
|
||||
else {
|
||||
tap_marker_idx = cur_syl + 1;
|
||||
}
|
||||
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
AnnounceUpdatedStyleRanges();
|
||||
AnnounceUpdatedTapMarker();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<AudioMarker*> AudioTimingControllerKaraoke::OnRightClick(int ms, bool, int, int) {
|
||||
cur_syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), ms));
|
||||
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
AnnounceUpdatedStyleRanges();
|
||||
c->audioController->PlayPrimaryRange();
|
||||
std::vector<AudioMarker*> AudioTimingControllerKaraoke::OnRightClick(int ms, bool ctrl_down, int, int) {
|
||||
if (ctrl_down) {
|
||||
// Ctrl-right-click: play audio
|
||||
c->audioController->PlayToEnd(ms);
|
||||
}
|
||||
else {
|
||||
// Normal right-click: select new syllable and play range
|
||||
cur_syl = distance(markers.begin(), lower_bound(markers.begin(), markers.end(), ms));
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
AnnounceUpdatedStyleRanges();
|
||||
c->audioController->PlayPrimaryRange();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
@ -379,7 +484,7 @@ int AudioTimingControllerKaraoke::MoveMarker(KaraokeMarker *marker, int new_posi
|
||||
marker->Move(new_position);
|
||||
|
||||
size_t syl = marker - &markers.front() + 1;
|
||||
kara->SetStartTime(syl, (new_position + 5) / 10 * 10);
|
||||
kara->SetStartTime(syl, new_position);
|
||||
|
||||
labels[syl - 1].range = TimeRange(labels[syl - 1].range.begin(), new_position);
|
||||
labels[syl].range = TimeRange(new_position, labels[syl].range.end());
|
||||
@ -387,10 +492,58 @@ int AudioTimingControllerKaraoke::MoveMarker(KaraokeMarker *marker, int new_posi
|
||||
return syl;
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::AnnounceChanges(int syl) {
|
||||
if (syl < 0) return;
|
||||
void AudioTimingControllerKaraoke::MoveStartMarker(int new_position) {
|
||||
// No rearranging of syllables allowed
|
||||
new_position = mid(
|
||||
0,
|
||||
new_position,
|
||||
markers[0].GetPosition());
|
||||
|
||||
if (syl == cur_syl || syl == cur_syl + 1) {
|
||||
if (new_position == start_marker.GetPosition())
|
||||
return;
|
||||
|
||||
start_marker.Move(new_position);
|
||||
|
||||
active_line->Start = (int)start_marker;
|
||||
kara->SetLineTimes(start_marker, end_marker);
|
||||
|
||||
labels.front().range = TimeRange(start_marker, labels.front().range.end());
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::MoveEndMarker(int new_position) {
|
||||
// No rearranging of syllables allowed
|
||||
new_position = mid(
|
||||
markers.back().GetPosition(),
|
||||
new_position,
|
||||
INT_MAX);
|
||||
|
||||
if (new_position == end_marker.GetPosition())
|
||||
return;
|
||||
|
||||
end_marker.Move(new_position);
|
||||
|
||||
active_line->End = (int)end_marker;
|
||||
kara->SetLineTimes(start_marker, end_marker);
|
||||
|
||||
labels.back().range = TimeRange(labels.back().range.begin(), end_marker);
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::CompressMarkers(size_t from, size_t to, int new_position) {
|
||||
int incr = (from < to ? 1 : -1);
|
||||
size_t i = from;
|
||||
for (;;) {
|
||||
MoveMarker(&markers[i], new_position);
|
||||
if (i == to) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
i += incr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::AnnounceChanges(bool announce_primary) {
|
||||
if (announce_primary) {
|
||||
AnnounceUpdatedPrimaryRange();
|
||||
AnnounceUpdatedStyleRanges();
|
||||
}
|
||||
@ -406,18 +559,21 @@ void AudioTimingControllerKaraoke::AnnounceChanges(int syl) {
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::OnMarkerDrag(std::vector<AudioMarker*> const& m, int new_position, int) {
|
||||
// Fix rounding error
|
||||
new_position = (new_position + 5) / 10 * 10;
|
||||
int old_position = m[0]->GetPosition();
|
||||
int syl = MoveMarker(static_cast<KaraokeMarker *>(m[0]), new_position);
|
||||
if (syl < 0) return;
|
||||
|
||||
bool announce_primary = (syl == cur_syl || syl == cur_syl + 1);
|
||||
if (m.size() > 1) {
|
||||
int delta = m[0]->GetPosition() - old_position;
|
||||
for (AudioMarker *marker : m | boost::adaptors::sliced(1, m.size()))
|
||||
MoveMarker(static_cast<KaraokeMarker *>(marker), marker->GetPosition() + delta);
|
||||
syl = cur_syl;
|
||||
announce_primary = true;
|
||||
}
|
||||
|
||||
AnnounceChanges(syl);
|
||||
AnnounceChanges(announce_primary);
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::GetLabels(TimeRange const& range, std::vector<AudioLabel> &out) const {
|
||||
@ -425,3 +581,12 @@ void AudioTimingControllerKaraoke::GetLabels(TimeRange const& range, std::vector
|
||||
return range.overlaps(l.range);
|
||||
}), back_inserter(out));
|
||||
}
|
||||
|
||||
std::string AudioTimingControllerKaraoke::GetCurrentSylText() const {
|
||||
return kara->GetStrippedText(cur_syl);
|
||||
}
|
||||
|
||||
void AudioTimingControllerKaraoke::SetCurrentSylText(std::string new_text) {
|
||||
kara->SetStrippedText(cur_syl, new_text);
|
||||
AnnounceChanges(true);
|
||||
}
|
||||
|
BIN
src/bitmaps/button/time_opt_tap_to_time_16.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
src/bitmaps/button/time_opt_tap_to_time_24.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
src/bitmaps/button/time_opt_tap_to_time_32.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
src/bitmaps/button/time_opt_tap_to_time_48.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
src/bitmaps/button/time_opt_tap_to_time_64.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
src/bitmaps/button/time_tap_connect_16.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/bitmaps/button/time_tap_connect_24.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
src/bitmaps/button/time_tap_connect_32.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/bitmaps/button/time_tap_connect_48.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
src/bitmaps/button/time_tap_connect_64.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
src/bitmaps/button/time_tap_no_connect_16.png
Normal file
After Width: | Height: | Size: 859 B |
BIN
src/bitmaps/button/time_tap_no_connect_24.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
src/bitmaps/button/time_tap_no_connect_32.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
src/bitmaps/button/time_tap_no_connect_48.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/bitmaps/button/time_tap_no_connect_64.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
@ -441,6 +441,21 @@ button/substart_to_video_24.png
|
||||
button/substart_to_video_32.png
|
||||
button/substart_to_video_48.png
|
||||
button/substart_to_video_64.png
|
||||
button/time_tap_connect_16.png
|
||||
button/time_tap_connect_24.png
|
||||
button/time_tap_connect_32.png
|
||||
button/time_tap_connect_48.png
|
||||
button/time_tap_connect_64.png
|
||||
button/time_tap_no_connect_16.png
|
||||
button/time_tap_no_connect_24.png
|
||||
button/time_tap_no_connect_32.png
|
||||
button/time_tap_no_connect_48.png
|
||||
button/time_tap_no_connect_64.png
|
||||
button/time_opt_tap_to_time_16.png
|
||||
button/time_opt_tap_to_time_24.png
|
||||
button/time_opt_tap_to_time_32.png
|
||||
button/time_opt_tap_to_time_48.png
|
||||
button/time_opt_tap_to_time_64.png
|
||||
button/timing_processor_toolbutton_16.png
|
||||
button/timing_processor_toolbutton_24.png
|
||||
button/timing_processor_toolbutton_32.png
|
||||
|
@ -47,8 +47,11 @@ namespace CharSetDetect {
|
||||
|
||||
std::string GetEncoding(agi::fs::path const& filename) {
|
||||
auto encoding = agi::charset::Detect(filename);
|
||||
if (!encoding.empty())
|
||||
if (!encoding.empty()) {
|
||||
if (!encoding.compare("ASCII") || !encoding.compare("UTF-8"))
|
||||
encoding = "utf-8";
|
||||
return encoding;
|
||||
}
|
||||
|
||||
auto choices = agi::charset::GetEncodingsList<wxArrayString>();
|
||||
int choice = wxGetSingleChoiceIndex(
|
||||
|
@ -110,8 +110,22 @@ struct help_website final : public Command {
|
||||
wxLaunchDefaultBrowser("http://www.aegisub.org/", wxBROWSER_NEW_WINDOW);
|
||||
}
|
||||
};
|
||||
|
||||
struct help_joysound_export final : public Command {
|
||||
CMD_NAME("help/joysound_exporter")
|
||||
CMD_ICON(website_button)
|
||||
STR_MENU("&Joysound Exporter")
|
||||
STR_DISP("Joysound Exporter")
|
||||
STR_HELP("Export karaoke from Joysound")
|
||||
|
||||
void operator()(agi::Context *) override {
|
||||
wxLaunchDefaultBrowser("https://joysound.rhiobet.ninja/", wxBROWSER_NEW_WINDOW);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace cmd {
|
||||
void init_help() {
|
||||
reg(agi::make_unique<help_bugs>());
|
||||
@ -119,5 +133,6 @@ namespace cmd {
|
||||
reg(agi::make_unique<help_irc>());
|
||||
reg(agi::make_unique<help_video>());
|
||||
reg(agi::make_unique<help_website>());
|
||||
reg(agi::make_unique<help_joysound_export>());
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "../dialogs.h"
|
||||
#include "../include/aegisub/context.h"
|
||||
#include "../libresrc/libresrc.h"
|
||||
#include "../options.h"
|
||||
#include "../project.h"
|
||||
#include "../selection_controller.h"
|
||||
#include "../video_controller.h"
|
||||
@ -50,6 +51,10 @@
|
||||
namespace {
|
||||
using cmd::Command;
|
||||
|
||||
static inline void toggle(const char *opt) {
|
||||
OPT_SET(opt)->SetBool(!OPT_GET(opt)->GetBool());
|
||||
}
|
||||
|
||||
struct validate_video_loaded : public Command {
|
||||
CMD_TYPE(COMMAND_VALIDATE)
|
||||
bool Validate(const agi::Context *c) override {
|
||||
@ -373,6 +378,107 @@ struct time_prev final : public Command {
|
||||
c->audioController->GetTimingController()->Prev();
|
||||
}
|
||||
};
|
||||
|
||||
struct time_tap_connect final : public Command {
|
||||
CMD_NAME("time/tap/connect")
|
||||
CMD_ICON(time_tap_connect)
|
||||
STR_MENU("Time tap connect")
|
||||
STR_DISP("Time tap connect")
|
||||
STR_HELP("Set tap marker to audio position, connect next line's start")
|
||||
CMD_TYPE(COMMAND_VALIDATE)
|
||||
|
||||
bool Validate(const agi::Context *c) override {
|
||||
return
|
||||
OPT_GET("Timing/Tap To Time")->GetBool() &&
|
||||
c->audioController->IsPlaying();
|
||||
}
|
||||
|
||||
void operator()(agi::Context *c) override {
|
||||
if (c->audioController->IsPlaying()) {
|
||||
AudioTimingController *tc = c->audioController->GetTimingController();
|
||||
if (tc) {
|
||||
int ms = c->audioController->GetPlaybackPosition();
|
||||
|
||||
tc->MoveTapMarker(ms);
|
||||
bool moved_marker = tc->NextTapMarker();
|
||||
if (!moved_marker &&
|
||||
OPT_GET("Audio/Auto/Commit")->GetBool() &&
|
||||
OPT_GET("Audio/Next Line on Commit")->GetBool()) {
|
||||
// go to next line, and then tap again to connect start to the same
|
||||
// time
|
||||
c->selectionController->NextLine();
|
||||
tc->MoveTapMarker(ms);
|
||||
tc->NextTapMarker();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct time_tap_no_connect final : public Command {
|
||||
CMD_NAME("time/tap/no_connect")
|
||||
CMD_ICON(time_tap_no_connect)
|
||||
STR_MENU("Tap marker no connect")
|
||||
STR_DISP("Tap marker no connect")
|
||||
STR_HELP("Set tap marker to audio position, do not connect next line's start")
|
||||
CMD_TYPE(COMMAND_VALIDATE)
|
||||
|
||||
bool Validate(const agi::Context *c) override {
|
||||
return
|
||||
OPT_GET("Timing/Tap To Time")->GetBool() &&
|
||||
c->audioController->IsPlaying();
|
||||
}
|
||||
|
||||
void operator()(agi::Context *c) override {
|
||||
if (c->audioController->IsPlaying()) {
|
||||
AudioTimingController *tc = c->audioController->GetTimingController();
|
||||
if (tc) {
|
||||
int ms = c->audioController->GetPlaybackPosition();
|
||||
|
||||
tc->MoveTapMarker(ms);
|
||||
bool moved_marker = tc->NextTapMarker();
|
||||
if (!moved_marker &&
|
||||
OPT_GET("Audio/Auto/Commit")->GetBool() &&
|
||||
OPT_GET("Audio/Next Line on Commit")->GetBool()) {
|
||||
// go to next line, but don't do anything more
|
||||
c->selectionController->NextLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct time_opt_tap_to_time final : public Command {
|
||||
CMD_NAME("time/opt/tap_to_time")
|
||||
CMD_ICON(time_opt_tap_to_time)
|
||||
STR_MENU("Enable tap-to-time UI")
|
||||
STR_DISP("Enable tap-to-time UI")
|
||||
STR_HELP("Enable tap-to-time UI")
|
||||
CMD_TYPE(COMMAND_TOGGLE)
|
||||
|
||||
bool IsActive(const agi::Context *) override {
|
||||
return OPT_GET("Timing/Tap To Time")->GetBool();
|
||||
}
|
||||
|
||||
void operator()(agi::Context *) override {
|
||||
toggle("Timing/Tap To Time");
|
||||
}
|
||||
};
|
||||
|
||||
struct time_add_space final : public Command {
|
||||
CMD_NAME("time/add_space")
|
||||
STR_MENU("Add Space")
|
||||
STR_DISP("Add Space")
|
||||
STR_HELP("Add a space at the end of the current syllab")
|
||||
void operator()(agi::Context *c) override {
|
||||
if (c->audioController->GetTimingController()) {
|
||||
AudioTimingController *tc = c->audioController->GetTimingController();
|
||||
tc->SetCurrentSylText(tc->GetCurrentSylText() + " ");
|
||||
// tc->Next(AudioTimingController::TIMING_UNIT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace cmd {
|
||||
@ -387,7 +493,10 @@ namespace cmd {
|
||||
reg(agi::make_unique<time_length_decrease_shift>());
|
||||
reg(agi::make_unique<time_length_increase>());
|
||||
reg(agi::make_unique<time_length_increase_shift>());
|
||||
reg(agi::make_unique<time_tap_connect>());
|
||||
reg(agi::make_unique<time_tap_no_connect>());
|
||||
reg(agi::make_unique<time_next>());
|
||||
reg(agi::make_unique<time_opt_tap_to_time>());
|
||||
reg(agi::make_unique<time_prev>());
|
||||
reg(agi::make_unique<time_shift>());
|
||||
reg(agi::make_unique<time_snap_end_video>());
|
||||
@ -395,5 +504,6 @@ namespace cmd {
|
||||
reg(agi::make_unique<time_snap_start_video>());
|
||||
reg(agi::make_unique<time_start_decrease>());
|
||||
reg(agi::make_unique<time_start_increase>());
|
||||
reg(agi::make_unique<time_add_space>());
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,13 @@
|
||||
#include <libaegisub/split.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <boost/beast/core.hpp>
|
||||
#include <boost/beast/http.hpp>
|
||||
#include <boost/beast/version.hpp>
|
||||
#include <boost/asio/connect.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl/error.hpp>
|
||||
#include <boost/asio/ssl/stream.hpp>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
@ -67,15 +73,65 @@
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace {
|
||||
std::mutex VersionCheckLock;
|
||||
|
||||
namespace ssl = boost::asio::ssl;
|
||||
namespace http = boost::beast::http;
|
||||
|
||||
struct AegisubUpdateDescription {
|
||||
std::string url;
|
||||
std::string friendly_name;
|
||||
int major;
|
||||
int minor;
|
||||
int patch;
|
||||
std::string extra;
|
||||
std::string description;
|
||||
};
|
||||
|
||||
AegisubUpdateDescription ParseVersionString(std::string version_string) {
|
||||
std::vector<std::string> maj_min;
|
||||
std::vector<std::string> patch;
|
||||
agi::Split(maj_min, version_string, '.');
|
||||
agi::Split(patch, maj_min[2], '-');
|
||||
|
||||
std::string extra = "";
|
||||
if (patch.size() > 1) {
|
||||
extra = patch[1];
|
||||
}
|
||||
|
||||
return AegisubUpdateDescription{
|
||||
atoi(maj_min[0].c_str()),
|
||||
atoi(maj_min[1].c_str()),
|
||||
atoi(patch[0].c_str()),
|
||||
extra,
|
||||
""
|
||||
};
|
||||
}
|
||||
|
||||
bool IsNewer(AegisubUpdateDescription update) {
|
||||
AegisubUpdateDescription current = ParseVersionString(GetReleaseVersion());
|
||||
|
||||
if (update.major != current.major)
|
||||
return update.major > current.major;
|
||||
|
||||
if (update.minor != current.minor)
|
||||
return update.minor > current.minor;
|
||||
|
||||
if (update.patch != current.patch)
|
||||
return update.patch > current.patch;
|
||||
|
||||
return update.extra.compare(current.extra) > 0;
|
||||
}
|
||||
|
||||
std::string AegisubVersion(AegisubUpdateDescription update) {
|
||||
std::ostringstream s;
|
||||
s << update.major << "." << update.minor << "." << update.patch;
|
||||
if (!update.extra.empty())
|
||||
s << "-" << update.extra;
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
class VersionCheckerResultDialog final : public wxDialog {
|
||||
void OnCloseButton(wxCommandEvent &evt);
|
||||
void OnRemindMeLater(wxCommandEvent &evt);
|
||||
@ -84,12 +140,12 @@ class VersionCheckerResultDialog final : public wxDialog {
|
||||
wxCheckBox *automatic_check_checkbox;
|
||||
|
||||
public:
|
||||
VersionCheckerResultDialog(wxString const& main_text, const std::vector<AegisubUpdateDescription> &updates);
|
||||
VersionCheckerResultDialog(wxString const& main_text, const AegisubUpdateDescription update);
|
||||
|
||||
bool ShouldPreventAppExit() const override { return false; }
|
||||
};
|
||||
|
||||
VersionCheckerResultDialog::VersionCheckerResultDialog(wxString const& main_text, const std::vector<AegisubUpdateDescription> &updates)
|
||||
VersionCheckerResultDialog::VersionCheckerResultDialog(wxString const& main_text, const AegisubUpdateDescription update)
|
||||
: wxDialog(nullptr, -1, _("Version Checker"))
|
||||
{
|
||||
const int controls_width = 500;
|
||||
@ -100,10 +156,10 @@ VersionCheckerResultDialog::VersionCheckerResultDialog(wxString const& main_text
|
||||
text->Wrap(controls_width);
|
||||
main_sizer->Add(text, 0, wxBOTTOM|wxEXPAND, 6);
|
||||
|
||||
for (auto const& update : updates) {
|
||||
main_sizer->Add(new wxStaticLine(this), 0, wxEXPAND|wxALL, 6);
|
||||
main_sizer->Add(new wxStaticLine(this), 0, wxEXPAND|wxALL, 6);
|
||||
|
||||
text = new wxStaticText(this, -1, to_wx(update.friendly_name));
|
||||
if (IsNewer(update)) {
|
||||
text = new wxStaticText(this, -1, to_wx("Aegisub-Japan7"));
|
||||
wxFont boldfont = text->GetFont();
|
||||
boldfont.SetWeight(wxFONTWEIGHT_BOLD);
|
||||
text->SetFont(boldfont);
|
||||
@ -112,21 +168,25 @@ VersionCheckerResultDialog::VersionCheckerResultDialog(wxString const& main_text
|
||||
wxTextCtrl *descbox = new wxTextCtrl(this, -1, to_wx(update.description), wxDefaultPosition, wxSize(controls_width,60), wxTE_MULTILINE|wxTE_READONLY);
|
||||
main_sizer->Add(descbox, 0, wxEXPAND|wxBOTTOM, 6);
|
||||
|
||||
main_sizer->Add(new wxHyperlinkCtrl(this, -1, to_wx(update.url), to_wx(update.url)), 0, wxALIGN_LEFT|wxBOTTOM, 6);
|
||||
std::ostringstream surl;
|
||||
surl << "https://" << UPDATE_CHECKER_SERVER << UPDATE_CHECKER_BASE_URL << "/Aegisub-Japan7-" << AegisubVersion(update) << "-x64.exe";
|
||||
std::string url = surl.str();
|
||||
|
||||
main_sizer->Add(new wxHyperlinkCtrl(this, -1, to_wx(url), to_wx(url)), 0, wxALIGN_LEFT|wxBOTTOM, 6);
|
||||
}
|
||||
|
||||
automatic_check_checkbox = new wxCheckBox(this, -1, _("&Auto Check for Updates"));
|
||||
automatic_check_checkbox->SetValue(OPT_GET("App/Auto/Check For Updates")->GetBool());
|
||||
|
||||
wxButton *remind_later_button = nullptr;
|
||||
if (updates.size() > 0)
|
||||
if (IsNewer(update))
|
||||
remind_later_button = new wxButton(this, wxID_NO, _("Remind me again in a &week"));
|
||||
|
||||
wxButton *close_button = new wxButton(this, wxID_OK, _("&Close"));
|
||||
SetAffirmativeId(wxID_OK);
|
||||
SetEscapeId(wxID_OK);
|
||||
|
||||
if (updates.size())
|
||||
if (IsNewer(update))
|
||||
main_sizer->Add(new wxStaticLine(this), 0, wxEXPAND|wxALL, 6);
|
||||
main_sizer->Add(automatic_check_checkbox, 0, wxEXPAND|wxBOTTOM, 6);
|
||||
|
||||
@ -280,72 +340,82 @@ static wxString GetAegisubLanguage() {
|
||||
return to_wx(OPT_GET("App/Language")->GetString());
|
||||
}
|
||||
|
||||
void DoCheck(bool interactive) {
|
||||
boost::asio::ip::tcp::iostream stream;
|
||||
stream.connect(UPDATE_CHECKER_SERVER, "http");
|
||||
if (!stream)
|
||||
throw VersionCheckError(from_wx(_("Could not connect to updates server.")));
|
||||
AegisubUpdateDescription GetLatestVersion() {
|
||||
|
||||
agi::format(stream,
|
||||
"GET %s?rev=%d&rel=%d&os=%s&lang=%s&aegilang=%s HTTP/1.0\r\n"
|
||||
"User-Agent: Aegisub %s\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"Connection: close\r\n\r\n"
|
||||
, UPDATE_CHECKER_BASE_URL
|
||||
, GetSVNRevision()
|
||||
, (GetIsOfficialRelease() ? 1 : 0)
|
||||
, GetOSShortName()
|
||||
, GetSystemLanguage()
|
||||
, GetAegisubLanguage()
|
||||
, GetAegisubLongVersionString()
|
||||
, UPDATE_CHECKER_SERVER);
|
||||
boost::asio::io_context ioc;
|
||||
boost::asio::ssl::context ctx(ssl::context::method::sslv23_client);
|
||||
|
||||
std::string http_version;
|
||||
stream >> http_version;
|
||||
int status_code;
|
||||
stream >> status_code;
|
||||
if (!stream || http_version.substr(0, 5) != "HTTP/")
|
||||
throw VersionCheckError(from_wx(_("Could not download from updates server.")));
|
||||
if (status_code != 200)
|
||||
throw VersionCheckError(agi::format(_("HTTP request failed, got HTTP response %d."), status_code));
|
||||
boost::asio::ip::tcp::resolver resolver(ioc);
|
||||
ssl::stream<boost::asio::ip::tcp::socket> stream(ioc, ctx);
|
||||
|
||||
stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
||||
if(! SSL_set_tlsext_host_name(stream.native_handle(), UPDATE_CHECKER_SERVER)) {
|
||||
boost::system::error_code ec{static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category()};
|
||||
throw boost::system::system_error{ec};
|
||||
}
|
||||
|
||||
// Skip the headers since we don't care about them
|
||||
for (auto const& header : agi::line_iterator<std::string>(stream))
|
||||
if (header.empty()) break;
|
||||
auto const results = resolver.resolve(UPDATE_CHECKER_SERVER, "443");
|
||||
|
||||
std::vector<AegisubUpdateDescription> results;
|
||||
for (auto const& line : agi::line_iterator<std::string>(stream)) {
|
||||
if (line.empty()) continue;
|
||||
boost::asio::connect(stream.next_layer(), results.begin(), results.end());
|
||||
stream.handshake(boost::asio::ssl::stream_base::handshake_type::client);
|
||||
|
||||
std::vector<std::string> parsed;
|
||||
agi::Split(parsed, line, '|');
|
||||
if (parsed.size() != 6) continue;
|
||||
std::ostringstream s;
|
||||
s << UPDATE_CHECKER_BASE_URL;
|
||||
s << "/latest";
|
||||
std::string target = s.str();
|
||||
http::request<http::string_body> req(http::verb::get, target, 11);
|
||||
req.set(http::field::host, UPDATE_CHECKER_SERVER);
|
||||
req.set(http::field::user_agent, "Aegisub-Japan7");
|
||||
|
||||
if (atoi(parsed[1].c_str()) <= GetSVNRevision())
|
||||
continue;
|
||||
http::write(stream, req);
|
||||
|
||||
// 0 and 2 being things that never got used
|
||||
results.push_back(AegisubUpdateDescription{
|
||||
inline_string_decode(parsed[3]),
|
||||
inline_string_decode(parsed[4]),
|
||||
inline_string_decode(parsed[5])
|
||||
});
|
||||
boost::beast::flat_buffer buffer;
|
||||
|
||||
http::response<http::string_body> res;
|
||||
|
||||
http::read(stream, buffer, res);
|
||||
|
||||
// Gracefully close the stream
|
||||
boost::system::error_code ec;
|
||||
stream.shutdown(ec);
|
||||
if(ec == boost::asio::error::eof)
|
||||
{
|
||||
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
|
||||
ec.assign(0, ec.category());
|
||||
}
|
||||
if(ec)
|
||||
throw boost::system::system_error{ec};
|
||||
|
||||
std::string line;
|
||||
std::stringstream body(res.body().data());
|
||||
|
||||
std::getline(body, line, '\n');
|
||||
|
||||
AegisubUpdateDescription version = ParseVersionString(line);
|
||||
|
||||
std::ostringstream desc;
|
||||
while (std::getline(body, line, '\n')) {
|
||||
desc << line;
|
||||
}
|
||||
|
||||
if (!results.empty() || interactive) {
|
||||
version.description = desc.str();
|
||||
return version;
|
||||
|
||||
throw VersionCheckError(from_wx(_("Could not get update from updates server.")));
|
||||
}
|
||||
|
||||
|
||||
void DoCheck(bool interactive) {
|
||||
AegisubUpdateDescription update = GetLatestVersion();
|
||||
|
||||
if (IsNewer(update) || interactive) {
|
||||
agi::dispatch::Main().Async([=]{
|
||||
wxString text;
|
||||
if (results.size() == 1)
|
||||
if (IsNewer(update))
|
||||
text = _("An update to Aegisub was found.");
|
||||
else if (results.size() > 1)
|
||||
text = _("Several possible updates to Aegisub were found.");
|
||||
else
|
||||
text = _("There are no updates to Aegisub.");
|
||||
|
||||
new VersionCheckerResultDialog(text, results);
|
||||
new VersionCheckerResultDialog(text, update);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,47 @@
|
||||
#include <unicode/utf16.h>
|
||||
#include <Usp10.h>
|
||||
|
||||
static void read_fonts_from_key(HKEY hkey, agi::fs::path font_dir, std::vector<agi::fs::path> &files) {
|
||||
static const auto fonts_key_name = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
||||
|
||||
HKEY key;
|
||||
auto ret = RegOpenKeyExW(hkey, fonts_key_name, 0, KEY_QUERY_VALUE, &key);
|
||||
if (ret != ERROR_SUCCESS) return;
|
||||
BOOST_SCOPE_EXIT_ALL(=) { RegCloseKey(key); };
|
||||
|
||||
DWORD name_buf_size = SHRT_MAX;
|
||||
DWORD data_buf_size = MAX_PATH;
|
||||
|
||||
auto font_name = new wchar_t[name_buf_size];
|
||||
auto font_filename = new wchar_t[data_buf_size];
|
||||
|
||||
for (DWORD i = 0;; ++i) {
|
||||
retry:
|
||||
DWORD name_len = name_buf_size;
|
||||
DWORD data_len = data_buf_size;
|
||||
|
||||
ret = RegEnumValueW(key, i, font_name, &name_len, NULL, NULL, reinterpret_cast<BYTE*>(font_filename), &data_len);
|
||||
if (ret == ERROR_MORE_DATA) {
|
||||
data_buf_size = data_len;
|
||||
delete font_filename;
|
||||
font_filename = new wchar_t[data_buf_size];
|
||||
goto retry;
|
||||
}
|
||||
if (ret == ERROR_NO_MORE_ITEMS) break;
|
||||
if (ret != ERROR_SUCCESS) continue;
|
||||
|
||||
agi::fs::path font_path(font_filename);
|
||||
if (!agi::fs::FileExists(font_path))
|
||||
// Doesn't make a ton of sense to do this with user fonts, but they seem to be stored as full paths anyway
|
||||
font_path = font_dir / font_path;
|
||||
if (agi::fs::FileExists(font_path)) // The path might simply be invalid
|
||||
files.push_back(font_path);
|
||||
}
|
||||
|
||||
delete font_name;
|
||||
delete font_filename;
|
||||
}
|
||||
|
||||
namespace {
|
||||
uint32_t murmur3(const char *data, uint32_t len) {
|
||||
static const uint32_t c1 = 0xcc9e2d51;
|
||||
@ -62,33 +103,17 @@ uint32_t murmur3(const char *data, uint32_t len) {
|
||||
}
|
||||
|
||||
std::vector<agi::fs::path> get_installed_fonts() {
|
||||
static const auto fonts_key_name = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
||||
|
||||
std::vector<agi::fs::path> files;
|
||||
|
||||
HKEY key;
|
||||
auto ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fonts_key_name, 0, KEY_QUERY_VALUE, &key);
|
||||
if (ret != ERROR_SUCCESS) return files;
|
||||
BOOST_SCOPE_EXIT_ALL(=) { RegCloseKey(key); };
|
||||
|
||||
wchar_t fdir[MAX_PATH];
|
||||
SHGetFolderPathW(NULL, CSIDL_FONTS, NULL, 0, fdir);
|
||||
agi::fs::path font_dir(fdir);
|
||||
|
||||
for (DWORD i = 0;; ++i) {
|
||||
wchar_t font_name[SHRT_MAX], font_filename[MAX_PATH];
|
||||
DWORD name_len = sizeof(font_name);
|
||||
DWORD data_len = sizeof(font_filename);
|
||||
// System fonts
|
||||
read_fonts_from_key(HKEY_LOCAL_MACHINE, font_dir, files);
|
||||
|
||||
ret = RegEnumValueW(key, i, font_name, &name_len, NULL, NULL, reinterpret_cast<BYTE *>(font_filename), &data_len);
|
||||
if (ret == ERROR_NO_MORE_ITEMS) break;
|
||||
if (ret != ERROR_SUCCESS) continue;
|
||||
|
||||
agi::fs::path font_path(font_filename);
|
||||
if (!agi::fs::FileExists(font_path))
|
||||
font_path = font_dir / font_path;
|
||||
files.push_back(font_path);
|
||||
}
|
||||
// User fonts
|
||||
read_fonts_from_key(HKEY_CURRENT_USER, font_dir, files);
|
||||
|
||||
return files;
|
||||
}
|
||||
|
@ -52,6 +52,12 @@ namespace {
|
||||
{nullptr}
|
||||
};
|
||||
|
||||
const char *added_hotkeys_time_tap[][3] = {
|
||||
{"time/tap/connect", "Audio", "I"},
|
||||
{"time/tap/no_connect", "Audio", "O"},
|
||||
{nullptr}
|
||||
};
|
||||
|
||||
void migrate_hotkeys(const char *added[][3]) {
|
||||
auto hk_map = hotkey::inst->GetHotkeyMap();
|
||||
bool changed = false;
|
||||
@ -121,6 +127,11 @@ void init() {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (boost::find(migrations, "time/tap") == end(migrations)) {
|
||||
migrate_hotkeys(added_hotkeys_time_tap);
|
||||
migrations.emplace_back("time/tap");
|
||||
}
|
||||
|
||||
OPT_SET("App/Hotkey Migrations")->SetListString(std::move(migrations));
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@
|
||||
|
||||
"Audio" : {
|
||||
"Auto" : {
|
||||
"Commit" : false,
|
||||
"Focus" : false,
|
||||
"Commit" : true,
|
||||
"Focus" : true,
|
||||
"Scroll" : true
|
||||
},
|
||||
"Cache" : {
|
||||
@ -49,7 +49,7 @@
|
||||
"Waveform Style" : 0
|
||||
},
|
||||
"Downmixer" : "ConvertToMono",
|
||||
"Drag Timing" : true,
|
||||
"Drag Timing" : false,
|
||||
"Inactive Lines Display Mode" : 3,
|
||||
"Karaoke" : {
|
||||
"Font Face" : "Verdana",
|
||||
@ -60,7 +60,7 @@
|
||||
"OUT" : 350
|
||||
},
|
||||
"Line Boundaries Thickness" : 2,
|
||||
"Link" : true,
|
||||
"Link" : false,
|
||||
"Lock Scroll on Cursor" : false,
|
||||
"Medusa Timing Hotkeys" : false,
|
||||
"Next Line on Commit" : true,
|
||||
@ -76,7 +76,7 @@
|
||||
},
|
||||
"Snap" : {
|
||||
"Distance" : 8,
|
||||
"Enable" : true
|
||||
"Enable" : false
|
||||
},
|
||||
"Spectrum" : true,
|
||||
"Start Drag Sensitivity" : 8,
|
||||
@ -366,7 +366,7 @@
|
||||
},
|
||||
"Character Limit" : 40,
|
||||
"Default Resolution" : {
|
||||
"Auto" : true,
|
||||
"Auto" : false,
|
||||
"Height" : 720,
|
||||
"Width" : 1280
|
||||
},
|
||||
@ -428,7 +428,8 @@
|
||||
},
|
||||
|
||||
"Timing" : {
|
||||
"Default Duration" : 3000
|
||||
"Default Duration" : 3000,
|
||||
"Tap To Time" : false
|
||||
},
|
||||
|
||||
"Tool" : {
|
||||
@ -606,11 +607,11 @@
|
||||
"Open Audio" : true,
|
||||
"Overscan Mask" : false,
|
||||
"Provider" : "ffmpegsource",
|
||||
"Script Resolution Mismatch" : 1,
|
||||
"Script Resolution Mismatch" : 0,
|
||||
"Slider" : {
|
||||
"Fast Jump Step" : 10,
|
||||
"Show Keyframes" : true
|
||||
},
|
||||
"Subtitle Sync" : true
|
||||
}
|
||||
}
|
||||
}
|
@ -16,10 +16,10 @@
|
||||
"KP_8"
|
||||
],
|
||||
"time/length/decrease" : [
|
||||
"KP_7"
|
||||
"Z"
|
||||
],
|
||||
"time/length/increase" : [
|
||||
"KP_9"
|
||||
"E"
|
||||
],
|
||||
"time/next" : [
|
||||
"KP_2"
|
||||
@ -28,10 +28,16 @@
|
||||
"KP_0"
|
||||
],
|
||||
"time/start/decrease" : [
|
||||
"KP_4"
|
||||
"Shift-Z"
|
||||
],
|
||||
"time/start/increase" : [
|
||||
"KP_6"
|
||||
"Shift-E"
|
||||
],
|
||||
"time/mark/connect" : [
|
||||
"I"
|
||||
],
|
||||
"time/mark/no_connect" : [
|
||||
"O"
|
||||
]
|
||||
},
|
||||
"Audio" : {
|
||||
@ -46,20 +52,20 @@
|
||||
"Shift-G"
|
||||
],
|
||||
"audio/play/line" : [
|
||||
"R"
|
||||
"C"
|
||||
],
|
||||
"audio/play/selection" : [
|
||||
"S",
|
||||
"Space"
|
||||
"Space",
|
||||
"X"
|
||||
],
|
||||
"audio/play/selection/after" : [
|
||||
"W"
|
||||
"F"
|
||||
],
|
||||
"audio/play/selection/before" : [
|
||||
"Q"
|
||||
],
|
||||
"audio/play/selection/begin" : [
|
||||
"E"
|
||||
"S"
|
||||
],
|
||||
"audio/play/selection/end" : [
|
||||
"D"
|
||||
@ -71,10 +77,10 @@
|
||||
"B"
|
||||
],
|
||||
"audio/scroll/left" : [
|
||||
"A"
|
||||
"W"
|
||||
],
|
||||
"audio/scroll/right" : [
|
||||
"F"
|
||||
"V"
|
||||
],
|
||||
"audio/stop" : [
|
||||
"H"
|
||||
@ -98,12 +104,15 @@
|
||||
"Shift-KP_Add"
|
||||
],
|
||||
"time/next" : [
|
||||
"Right",
|
||||
"X"
|
||||
"R",
|
||||
"Right"
|
||||
],
|
||||
"time/prev" : [
|
||||
"Left",
|
||||
"Z"
|
||||
"A",
|
||||
"Left"
|
||||
],
|
||||
"time/add_space" : [
|
||||
"Ctrl-Space"
|
||||
]
|
||||
},
|
||||
"Default" : {
|
||||
@ -113,6 +122,33 @@
|
||||
"app/options" : [
|
||||
"Alt-O"
|
||||
],
|
||||
"automation/lua/duetto-meika/Deduetto Meika" : [
|
||||
"Ctrl-Shift-D"
|
||||
],
|
||||
"automation/lua/duetto-meika/Duetto Meika" : [
|
||||
"Ctrl-D"
|
||||
],
|
||||
"automation/lua/kara-templater/Apply karaoke template" : [
|
||||
"Ctrl-Alt-Shift-K"
|
||||
],
|
||||
"automation/lua/karaoke-adjust-1sec/Karaoke 1sec adjust lead-in" : [
|
||||
"Ctrl-K"
|
||||
],
|
||||
"automation/lua/karaoke-adjust-1sec/Mugenizer" : [
|
||||
"Ctrl-Shift-K"
|
||||
],
|
||||
"automation/lua/karaoke-split/Split karaoke line" : [
|
||||
"Ctrl-Shift-P"
|
||||
],
|
||||
"automation/lua/ua.ChangeCase/Change Case" : [
|
||||
"Ctrl-Shift-C"
|
||||
],
|
||||
"automation/lua/ua.HYDRA/HYDRA" : [
|
||||
"Ctrl-Shift-H"
|
||||
],
|
||||
"automation/lua/ua.ScriptCleanup/Script Cleanup" : [
|
||||
"Ctrl-Shift-O"
|
||||
],
|
||||
"edit/find_replace" : [
|
||||
"Ctrl-H"
|
||||
],
|
||||
@ -125,18 +161,18 @@
|
||||
"edit/line/delete" : [
|
||||
"Ctrl-Delete"
|
||||
],
|
||||
"edit/line/duplicate/shift" : [
|
||||
"Ctrl-D"
|
||||
],
|
||||
"edit/line/duplicate/shift_back" : [
|
||||
"Ctrl-Shift-D"
|
||||
],
|
||||
"edit/line/paste" : [
|
||||
"Ctrl-V"
|
||||
],
|
||||
"edit/line/paste/over" : [
|
||||
"Ctrl-Shift-V"
|
||||
],
|
||||
"edit/line/split/after" : [
|
||||
"Ctrl-Alt-Shift-D"
|
||||
],
|
||||
"edit/line/split/before" : [
|
||||
"Ctrl-Alt-D"
|
||||
],
|
||||
"edit/redo" : [
|
||||
"Ctrl-Y"
|
||||
],
|
||||
@ -193,7 +229,7 @@
|
||||
"Ctrl-3"
|
||||
],
|
||||
"video/focus_seek" : [
|
||||
"Ctrl-Space"
|
||||
"Alt-Space"
|
||||
],
|
||||
"video/frame/next" : [
|
||||
"Ctrl-KP_6"
|
||||
@ -359,4 +395,4 @@
|
||||
"J"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,6 +203,7 @@
|
||||
{ "command" : "help/contents" },
|
||||
{},
|
||||
{ "command" : "help/website" },
|
||||
{ "command" : "help/joysound_exporter" },
|
||||
{ "command" : "help/bugs" },
|
||||
{},
|
||||
{ "command" : "help/irc" },
|
||||
|
@ -15,6 +15,9 @@
|
||||
"time/lead/in",
|
||||
"time/lead/out",
|
||||
"",
|
||||
"time/tap/connect",
|
||||
"time/tap/no_connect",
|
||||
"",
|
||||
"audio/commit",
|
||||
"audio/go_to",
|
||||
"",
|
||||
@ -23,6 +26,7 @@
|
||||
"audio/opt/autoscroll",
|
||||
"audio/opt/spectrum",
|
||||
"app/toggle/global_hotkeys",
|
||||
"time/opt/tap_to_time",
|
||||
"",
|
||||
"audio/karaoke"
|
||||
],
|
||||
|
@ -428,7 +428,8 @@
|
||||
},
|
||||
|
||||
"Timing" : {
|
||||
"Default Duration" : 3000
|
||||
"Default Duration" : 3000,
|
||||
"Tap To Time" : false
|
||||
},
|
||||
|
||||
"Tool" : {
|
||||
|
@ -16,10 +16,10 @@
|
||||
"KP_8"
|
||||
],
|
||||
"time/length/decrease" : [
|
||||
"KP_7"
|
||||
"Z"
|
||||
],
|
||||
"time/length/increase" : [
|
||||
"KP_9"
|
||||
"E"
|
||||
],
|
||||
"time/next" : [
|
||||
"KP_2"
|
||||
@ -28,10 +28,10 @@
|
||||
"KP_0"
|
||||
],
|
||||
"time/start/decrease" : [
|
||||
"KP_4"
|
||||
"Shift-Z"
|
||||
],
|
||||
"time/start/increase" : [
|
||||
"KP_6"
|
||||
"Shift-E"
|
||||
]
|
||||
},
|
||||
"Audio" : {
|
||||
@ -46,20 +46,20 @@
|
||||
"Shift-G"
|
||||
],
|
||||
"audio/play/line" : [
|
||||
"R"
|
||||
"C"
|
||||
],
|
||||
"audio/play/selection" : [
|
||||
"S",
|
||||
"Space"
|
||||
"Space",
|
||||
"X"
|
||||
],
|
||||
"audio/play/selection/after" : [
|
||||
"W"
|
||||
"F"
|
||||
],
|
||||
"audio/play/selection/before" : [
|
||||
"Q"
|
||||
],
|
||||
"audio/play/selection/begin" : [
|
||||
"E"
|
||||
"S"
|
||||
],
|
||||
"audio/play/selection/end" : [
|
||||
"D"
|
||||
@ -71,10 +71,10 @@
|
||||
"B"
|
||||
],
|
||||
"audio/scroll/left" : [
|
||||
"A"
|
||||
"W"
|
||||
],
|
||||
"audio/scroll/right" : [
|
||||
"F"
|
||||
"V"
|
||||
],
|
||||
"audio/stop" : [
|
||||
"H"
|
||||
@ -98,12 +98,12 @@
|
||||
"Shift-KP_Add"
|
||||
],
|
||||
"time/next" : [
|
||||
"Right",
|
||||
"X"
|
||||
"R",
|
||||
"Right"
|
||||
],
|
||||
"time/prev" : [
|
||||
"Left",
|
||||
"Z"
|
||||
"A",
|
||||
"Left"
|
||||
]
|
||||
},
|
||||
"Default" : {
|
||||
@ -116,6 +116,33 @@
|
||||
"app/toggle/toolbar" : [
|
||||
"Ctrl-Alt-T"
|
||||
],
|
||||
"automation/lua/duetto-meika/Deduetto Meika" : [
|
||||
"Ctrl-Shift-D"
|
||||
],
|
||||
"automation/lua/duetto-meika/Duetto Meika" : [
|
||||
"Ctrl-D"
|
||||
],
|
||||
"automation/lua/kara-templater/Apply karaoke template" : [
|
||||
"Ctrl-Alt-Shift-K"
|
||||
],
|
||||
"automation/lua/karaoke-adjust-1sec/Karaoke 1sec adjust lead-in" : [
|
||||
"Ctrl-K"
|
||||
],
|
||||
"automation/lua/karaoke-adjust-1sec/Mugenizer" : [
|
||||
"Ctrl-Shift-K"
|
||||
],
|
||||
"automation/lua/karaoke-split/Split karaoke line" : [
|
||||
"Ctrl-Shift-P"
|
||||
],
|
||||
"automation/lua/ua.ChangeCase/Change Case" : [
|
||||
"Ctrl-Shift-C"
|
||||
],
|
||||
"automation/lua/ua.HYDRA/HYDRA" : [
|
||||
"Ctrl-Shift-H"
|
||||
],
|
||||
"automation/lua/ua.ScriptCleanup/Script Cleanup" : [
|
||||
"Ctrl-Shift-O"
|
||||
],
|
||||
"edit/find_replace" : [
|
||||
"Ctrl-Alt-F"
|
||||
],
|
||||
@ -126,13 +153,7 @@
|
||||
"Ctrl-X"
|
||||
],
|
||||
"edit/line/delete" : [
|
||||
"Ctrl-Backspace"
|
||||
],
|
||||
"edit/line/duplicate/shift" : [
|
||||
"Ctrl-D"
|
||||
],
|
||||
"edit/line/duplicate/shift_back" : [
|
||||
"Ctrl-Shift-D"
|
||||
"Ctrl-Delete"
|
||||
],
|
||||
"edit/line/paste" : [
|
||||
"Ctrl-V"
|
||||
@ -140,6 +161,12 @@
|
||||
"edit/line/paste/over" : [
|
||||
"Ctrl-Shift-V"
|
||||
],
|
||||
"edit/line/split/after" : [
|
||||
"Ctrl-Alt-Shift-D"
|
||||
],
|
||||
"edit/line/split/before" : [
|
||||
"Ctrl-Alt-D"
|
||||
],
|
||||
"edit/redo" : [
|
||||
"Ctrl-Shift-Z"
|
||||
],
|
||||
|
@ -213,6 +213,7 @@
|
||||
{ "command" : "help/contents" },
|
||||
{},
|
||||
{ "command" : "help/website" },
|
||||
{ "command" : "help/joysound_exporter" },
|
||||
{ "command" : "help/bugs" },
|
||||
{},
|
||||
{ "command" : "help/irc" },
|
||||
|
@ -74,6 +74,10 @@ const char *GetVersionNumber() {
|
||||
return BUILD_GIT_VERSION_STRING;
|
||||
}
|
||||
|
||||
const char *GetReleaseVersion() {
|
||||
return RELEASE_VERSION;
|
||||
}
|
||||
|
||||
int GetSVNRevision() {
|
||||
#ifdef BUILD_GIT_VERSION_NUMBER
|
||||
return BUILD_GIT_VERSION_NUMBER;
|
||||
|
@ -46,3 +46,5 @@ bool GetIsOfficialRelease();
|
||||
const char *GetVersionNumber();
|
||||
/// Get SVN revision
|
||||
int GetSVNRevision();
|
||||
/// Get Release Version
|
||||
const char *GetReleaseVersion();
|
||||
|
1
subprojects/japan7-fonts
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 74ef0dea87e3c10bbf0b4df90b663b8868d9cbd5
|
@ -12,6 +12,8 @@ repack-thes-dict_CPPFLAGS := -I$(TOP) -I$(TOP)libaegisub/include $(CFLAGS_ICU)
|
||||
|
||||
PROGRAM += $(d)repack-thes-dict
|
||||
|
||||
$(TOP)tools/respack.lua: $(shell command -v "$(BIN_LUA)")
|
||||
ifeq (no, $(SYSTEM_LUAJIT))
|
||||
$(TOP)tools/respack.lua: $(BIN_LUA)
|
||||
endif
|
||||
|
||||
include $(TOP)Makefile.target
|
||||
|
@ -45,10 +45,13 @@ else
|
||||
tagged_release=0
|
||||
fi
|
||||
|
||||
last_release=$(git describe --tags)
|
||||
|
||||
|
||||
new_version_h="\
|
||||
#define BUILD_GIT_VERSION_NUMBER ${git_revision}
|
||||
#define BUILD_GIT_VERSION_STRING \"${git_version_str}\"
|
||||
#define RELEASE_VERSION \"${last_release#v}\"
|
||||
#define TAGGED_RELEASE ${tagged_release}
|
||||
#define INSTALLER_VERSION \"${installer_version}\"
|
||||
#define RESOURCE_BASE_VERSION ${resource_version}"
|
||||
@ -68,7 +71,7 @@ export VERSION_SOURCE="from git"
|
||||
|
||||
cat << EOF > "${builddir}/git_version.xml"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<GitVersionNumber>${git_revision}</GitVersionNumber>
|
||||
<GitVersionString>${git_version_str}</GitVersionString>
|
||||
|