Skip to content

Commit 193aad6

Browse files
committed
Update to 3.18.28.0
1 parent 85d1956 commit 193aad6

26 files changed

+2695
-2034
lines changed

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@typescript-eslint/ban-ts-comment": "off",
4747
"eqeqeq": "error",
4848
"@typescript-eslint/ban-types": "off",
49-
"@typescript-eslint/no-namespace": "off"
49+
"@typescript-eslint/no-namespace": "off",
50+
"prefer-const": ["error", { "destructuring": "all" }]
5051
}
5152
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<p><b><i>Ranne</i></b></p>
77
<p>
88
<img src="https://img.shields.io/badge/STATE-STABLE-green?style=flat-square" alt="Badge" />
9-
<img src="https://img.shields.io/badge/VERSION-3.15.30.0-orange?style=flat-square" alt="Badge" />
9+
<img src="https://img.shields.io/badge/VERSION-3.18.28.0-orange?style=flat-square" alt="Badge" />
1010
<!-- <img src="https://img.shields.io/github/downloads/otomad/om_midi/total.svg?style=flat-square&label=DOWNLOADS" alt="Downloads"> -->
1111
</p>
1212
<p><a href="https://github.com/otomad/om_midi/releases/latest"><img src="https://img.shields.io/badge/-Get%20the%20download%20link%20now!-brightgreen?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTEuMiAwYS44LjggMCAwIDAtLjguOHYxMS40TDcuMjYgOS40NGEuODAzLjgwMyAwIDAgMC0xLjEzLjA3NGwtMS4wNSAxLjJhLjguOCAwIDAgMCAuMDczIDEuMTNsNi4zMyA1LjU0YS43OTUuNzk1IDAgMCAwIDEuMDUgMGw2LjMyLTUuNTRhLjguOCAwIDAgMCAuMDc0LTEuMTNsLTEuMDUtMS4yYS44MDQuODA0IDAgMCAwLTEuMTMtLjA3NGwtMy4xNCAyLjc2Vi44YS44LjggMCAwIDAtLjgtLjh6bS04IDIwLjhhLjguOCAwIDAgMC0uOC44djEuNmEuOC44IDAgMCAwIC44LjhoMTcuNmEuOC44IDAgMCAwIC44LS44di0xLjZhLjguOCAwIDAgMC0uOC0uOHoiIGZpbGw9IndoaXRlIi8+PC9zdmc+" alt="Download" /></a></p>

custom_modules/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
## Place my custom Node.js Rollup plugins here
22

3-
I wanted to find some similar plugins on [npm](https://www.npmjs.com/) and found that I couldn't find them, so I wrote some of them myself.
3+
I wanted to find some similar plugins on [npm](https://www.npmjs.com/) and found that I couldn't find them, so I wrote some of them by self.

dist/om midi.jsx

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

dist/om midi.jsxbin

Lines changed: 2373 additions & 1982 deletions
Large diffs are not rendered by default.

src/components/MappingVelocityCheckbox.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import ConfigJsonNS from "../core/ConfigJsonNS";
22
import MappingVelocityDialog from "../dialogs/MappingVelocityDialog";
3-
import { ZString } from "../languages/ui-str";
3+
import { DIALOG_SIGN, ZString } from "../languages/ui-str";
44
import addControl from "../modules/addControl";
55
import clamp from "../modules/clamp";
66
import map from "../modules/map";
@@ -23,7 +23,7 @@ export default class MappingVelocityCheckbox {
2323
this.mapping = new ConfigJsonNS.MappingVelocity({ targetLess: defaultRange[0], targetMore: defaultRange[1] });
2424
this.group = addControl(parent, "group", { orientation: "row" });
2525
this.checkbox = addControl(this.group, "checkbox", { text });
26-
this.advanceBtn = addControl(this.group, "button", { text: "...", size: [MIDI_BUTTON_WIDTH, 18] });
26+
this.advanceBtn = addControl(this.group, "button", { text: DIALOG_SIGN, size: [MIDI_BUTTON_WIDTH, 18] });
2727
this.checkbox.onClick = () => this.value = this.checkbox.value;
2828
this.advanceBtn.onClick = () => {
2929
const result = new MappingVelocityDialog(targetText, targetRange, this.mapping).showDialog();

src/core/Core.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CannotFindCompositionError, CannotSetTimeRemapError, CannotTuningError, HasNoVideoError, MyError, NoLayerSelectedError, NoMidiError, NoOptionsCheckedError, NotOneTrackForApplyEffectsOnlyError } from "../errors";
1+
import { CannotFindCompositionError, CannotSetTimeRemapError, CannotTuningError, EmptySubtitlesError, HasNoVideoError, InvalidDurationError, MyError, NoLayerSelectedError, NoMidiError, NoOptionsCheckedError, NotOneTrackForApplyEffectsOnlyError } from "../errors";
22
import Portal from "../ui/Portal";
33
import getComp from "../modules/getComp";
44
import Setting from "../settings/Setting";
@@ -46,6 +46,8 @@ export default class Core {
4646
this.applyMarkerConductor(comp);
4747
else if (tool === this.portal.toolsTab.ease)
4848
this.applyEase100Percent(comp);
49+
else if (tool === this.portal.toolsTab.subtitle)
50+
this.applyGenerateSubtitles(comp);
4951
}
5052
} catch (error) {
5153
throw new MyError(error as Error);
@@ -544,7 +546,8 @@ export default class Core {
544546
const layers = comp.selectedLayers;
545547
for (const layer of layers) {
546548
if (layer === undefined) continue;
547-
for (const property of layer.selectedProperties as Property[]) {
549+
const selectedProperties = Core.getSelectedProperties(layer);
550+
for (const property of selectedProperties) {
548551
if (property === undefined) continue;
549552
for (const keyIndex of property.selectedKeys) {
550553
if (keyIndex === undefined) continue;
@@ -554,6 +557,23 @@ export default class Core {
554557
}
555558
}
556559

560+
applyGenerateSubtitles(comp: CompItem) {
561+
const { subtitle } = this.portal.toolsTab;
562+
const duration = parseFloat(subtitle.durationTxt.text);
563+
const subtitlesText = subtitle.subtitlesText.text;
564+
if (!isFinite(duration) || duration <= 0) throw new InvalidDurationError();
565+
if (!subtitlesText.trim().length) throw new EmptySubtitlesError();
566+
const subtitles = subtitlesText.replace(/\r\n|\n\r|\r|\n/g, "\n").split("\n");
567+
568+
app.beginUndoGroup("om midi - Apply Batch Subtitle Generation");
569+
const layer = comp.layers.addText();
570+
const startTime = layer.startTime = this.getStartTime(comp);
571+
subtitles.forEach((line, index) => {
572+
if (!line.trim().length) return;
573+
layer.sourceText.setValueAtTime(startTime + index * duration, new TextDocument(line));
574+
});
575+
}
576+
557577
//#region 辅助方法
558578
/**
559579
* 创建一个空对象图层。
@@ -604,6 +624,28 @@ export default class Core {
604624
return layer("Effects") as PropertyGroup;
605625
}
606626

627+
/**
628+
* 获取选中的参数,用以获取选中的关键帧,但是要避免选中参数组,如果是参数组则通过递归来获取真正的参数。
629+
* @param layer - 图层或参数类。
630+
* @returns 选中的参数。
631+
*/
632+
private static getSelectedProperties(layer: Layer | _PropertyClasses[]): Property[] {
633+
const properties: Property[] = [];
634+
const propertyClasses = layer instanceof Array ? layer : layer.selectedProperties;
635+
for (const property of propertyClasses) {
636+
if (property === undefined) continue;
637+
else if (property instanceof Property)
638+
properties.push(property);
639+
else {
640+
const subProperties: _PropertyClasses[] = [];
641+
for (let i = 1; i <= property.numProperties; i++)
642+
subProperties.push(property.property(i));
643+
properties.push(...this.getSelectedProperties(subProperties));
644+
}
645+
}
646+
return properties;
647+
}
648+
607649
/**
608650
* 为指定图层添加一个表达式控制 - 滑块控制的效果。
609651
* @param layer - 图层。
@@ -719,10 +761,20 @@ export default class Core {
719761
if (ease.length !== 0)
720762
property.setTemporalEaseAtKey(keyIndex, ease as [KeyframeEase]);
721763
const anotherSide = isHold ? KeyframeInterpolationType.HOLD : KeyframeInterpolationType.LINEAR;
764+
const original: [KeyframeInterpolationType, KeyframeInterpolationType] =
765+
[property.keyInInterpolationType(keyIndex), property.keyOutInterpolationType(keyIndex)];
722766
if (easeType === EaseType.EASE_IN)
723767
property.setInterpolationTypeAtKey(keyIndex, KeyframeInterpolationType.BEZIER, anotherSide);
724768
else if (easeType === EaseType.EASE_OUT)
725769
property.setInterpolationTypeAtKey(keyIndex, anotherSide, KeyframeInterpolationType.BEZIER);
770+
else if (easeType === EaseType.LINEAR)
771+
property.setInterpolationTypeAtKey(keyIndex, KeyframeInterpolationType.LINEAR);
772+
else if (easeType === EaseType.HOLD)
773+
property.setInterpolationTypeAtKey(keyIndex, KeyframeInterpolationType.HOLD);
774+
else if (easeType === EaseType.HOLD_IN)
775+
property.setInterpolationTypeAtKey(keyIndex, KeyframeInterpolationType.HOLD, original[1]);
776+
else if (easeType === EaseType.HOLD_OUT)
777+
property.setInterpolationTypeAtKey(keyIndex, original[0], KeyframeInterpolationType.HOLD);
726778
}
727779
//#endregion
728780

src/dialogs/SettingsDialog.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default class SettingsDialog {
7171
group: this.languageGroup,
7272
label: this.languageLbl,
7373
control: this.languageCombo,
74-
} = addGroup(this.generalPanel, localize(uiStr.language), "dropdownlist"));
74+
} = addGroup(this.generalPanel, localize(uiStr.language), "dropdownlist", undefined, undefined, true));
7575
addItems(this.languageCombo, localize(uiStr.app_default) + ` (${this.getDefaultLocale()})`, "简体中文", "English", "日本語", "Tiếng Việt", "한국어");
7676
const selectedLanguageIndex = Setting.getLanguage();
7777
if (selectedLanguageIndex > 0 && selectedLanguageIndex < this.languageCombo.items.length)

src/errors.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,15 @@ export class InvalidMappingVelocityValuesError extends MyError {
139139
super(localize(uiStr.invalid_mapping_velocity_values_error));
140140
}
141141
}
142+
143+
export class InvalidDurationError extends MyError {
144+
constructor() {
145+
super(localize(uiStr.invalid_duration_error));
146+
}
147+
}
148+
149+
export class EmptySubtitlesError extends MyError {
150+
constructor() {
151+
super(localize(uiStr.empty_subtitles_error));
152+
}
153+
}

src/languages/English.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ const English: typeof SChinese = {
8888
paren_truncated: " (Truncated)",
8989
cannot_find_window_error: "Error: Unable to find or create window.",
9090
unsupported_setting_type_error: "Error: Unsupported setting data type.",
91-
file_unreadable_error: "Error: Could not read the MIDI file. The file may already be occupied or not exist.",
91+
file_unreadable_error: "Error: Could not read the file. The file may already be occupied or not exist.",
9292
midi_header_validation_error: "Error: MIDI file header chunks validation failed (not a standard MIDI file or this file is corrupt).",
9393
midi_track_header_validation_error: "Error: MIDI track header chunks validation failed.",
9494
midi_custom_events_error: "Error: Custom MIDI events could not be read.",
@@ -103,7 +103,7 @@ const English: typeof SChinese = {
103103
end_of_track_position_error: "Error: Track ends in wrong position. Expected %1, actually %2.",
104104
cannot_set_time_remap_error: "Error: Time remapping cannot be set for the selected layer.",
105105
cannot_tuning_error: "Error: The selected layer does not contain audio so that cannot be tuned.",
106-
about: "It reads a Standard MIDI sequence file and creates layers and keyframes corresponding to the notes and controllers in that MIDI sequence file.\n\nVersion: %4\nApp: %2\nSpecifier: %3\n\nOriginal Authors: David Van Brink (omino), Dora (NGDXW), Z4HD\nAuthor: Ranne\nRepository Link: %1",
106+
about: "It reads a Standard MIDI sequence file and creates layers and keyframes corresponding to the notes and controllers in that MIDI sequence file.\n\nVersion: %4\nApp: %2\nSpecifier: %3\n\nAuthor: Ranne\nOriginal Authors: David Van Brink (omino), Dora (NGDXW), Z4HD\nRepository Link: %1",
107107
horizontal_mirror: "Horizontal Mirror",
108108
advanced_scale: "Advanced Scale",
109109
loading_midi: "Loading %1 ...",
@@ -125,6 +125,19 @@ const English: typeof SChinese = {
125125
motion_float_up: "Float Up",
126126
motion_float_down: "Float Down",
127127
script_translator: "Translator: ",
128+
invalid_duration_error: "Error: The value of the \"Duration of each subtitles\" parameter is invalid.",
129+
empty_subtitles_error: "Error: Please enter the subtitle content.",
130+
batch_subtitle_generation: "Batch Subtitle Generation",
131+
linear: "Linear",
132+
hold_both: "Hold both",
133+
hold_in: "Hold in",
134+
hold_out: "Hold out",
135+
second_unit: "Seconds",
136+
open: "Open",
137+
text_document: "Text Document",
138+
browse: "Browse",
139+
file_too_large_info: "The file is too large. Do you want to open it anyway?",
140+
will_clear_existing_text_info: "Existing text content will be cleared and your changes may not be retained.",
128141
};
129142

130143
export default English;

0 commit comments

Comments
 (0)