diff --git a/src/main/python/plotlyst/core/domain.py b/src/main/python/plotlyst/core/domain.py index b69d7607d..efb255236 100644 --- a/src/main/python/plotlyst/core/domain.py +++ b/src/main/python/plotlyst/core/domain.py @@ -2482,6 +2482,14 @@ def update_acts(self): icon_color='#6a0136', act=2, ends_act=True, percentage=80) +second_plot_point_aha = StoryBeat(text='A-ha moment', + icon='fa5.lightbulb', + icon_color='#6a0136', + description="It propels the story into the climax through the character's epiphany. They often have a realization about themselves or the plot.", + placeholder="It propels the story into the climax through the character's epiphany.", + id=uuid.UUID('00ccb15d-9331-4f45-8ed7-ffc7b2e7bf90'), + act=2, ends_act=True, percentage=80) + midpoint = StoryBeat(text='Midpoint', icon='mdi.middleware-outline', icon_color='#2e86ab', @@ -2559,6 +2567,7 @@ def update_acts(self): act=3, percentage=99) first_plot_points = (first_plot_point, first_plot_point_ponr) +second_plot_points = (second_plot_point, second_plot_point_aha) midpoints = ( midpoint, midpoint_ponr, midpoint_mirror, midpoint_proactive, midpoint_false_victory, midpoint_re_dedication) diff --git a/src/main/python/plotlyst/view/widget/structure/template.py b/src/main/python/plotlyst/view/widget/structure/template.py index 6a1fb3976..cdd2ae14a 100644 --- a/src/main/python/plotlyst/view/widget/structure/template.py +++ b/src/main/python/plotlyst/view/widget/structure/template.py @@ -36,7 +36,7 @@ disturbance_beat, normal_world_beat, characteristic_moment_beat, midpoint, midpoint_ponr, midpoint_mirror, \ midpoint_proactive, crisis, first_plot_point, first_plot_point_ponr, first_plot_points, midpoints, story_spine, \ twists_and_turns, twist_beat, turn_beat, danger_beat, copy_beat, five_act_structure, midpoint_false_victory, \ - midpoint_re_dedication + midpoint_re_dedication, second_plot_points, second_plot_point_aha, second_plot_point from plotlyst.view.common import ExclusiveOptionalButtonGroup, push_btn, label from plotlyst.view.generated.story_structure_selector_dialog_ui import Ui_StoryStructureSelectorDialog from plotlyst.view.icons import IconRegistry @@ -108,6 +108,11 @@ class _ThreeActFirstPlotPoint(BeatCustomization): Point_of_no_return = auto() +class _ThreeActSecondPlotPoint(BeatCustomization): + Second_plot_point = auto() + Aha_moment = auto() + + class _ThreeActMidpoint(BeatCustomization): Turning_point = auto() Point_of_no_return = auto() @@ -144,6 +149,7 @@ def beat_option_description(option: BeatCustomization) -> str: elif option == _ThreeActFirstPlotPoint.Point_of_no_return: return first_plot_point_ponr.description + elif option == _ThreeActMidpoint.Turning_point: return midpoint.description elif option == _ThreeActMidpoint.Point_of_no_return: @@ -157,6 +163,11 @@ def beat_option_description(option: BeatCustomization) -> str: elif option == _ThreeActMidpoint.Re_dedication: return midpoint_re_dedication.description + elif option == _ThreeActSecondPlotPoint.Second_plot_point: + return second_plot_point.description + elif option == _ThreeActSecondPlotPoint.Aha_moment: + return second_plot_point_aha.description + elif option == _ThreeActEnding.Crisis: return crisis.description @@ -191,6 +202,11 @@ def beat_option_icon(option: BeatCustomization) -> Tuple[str, str]: elif option == _ThreeActMidpoint.Re_dedication: return midpoint_re_dedication.icon, midpoint_re_dedication.icon_color + elif option == _ThreeActSecondPlotPoint.Second_plot_point: + return second_plot_point.icon, second_plot_point.icon_color + elif option == _ThreeActSecondPlotPoint.Aha_moment: + return second_plot_point_aha.icon, second_plot_point_aha.icon_color + elif option == _ThreeActEnding.Crisis: return crisis.icon, crisis.icon_color @@ -225,6 +241,11 @@ def option_from_beat(beat: StoryBeat) -> Optional[BeatCustomization]: elif beat == midpoint_re_dedication: return _ThreeActMidpoint.Re_dedication + elif beat == second_plot_point: + return _ThreeActSecondPlotPoint.Second_plot_point + elif beat == second_plot_point_aha: + return _ThreeActSecondPlotPoint.Aha_moment + elif beat == crisis: return _ThreeActEnding.Crisis @@ -235,6 +256,10 @@ def find_first_plot_point(structure: StoryStructure) -> Optional[StoryBeat]: return next((x for x in structure.beats if x in first_plot_points), None) +def find_second_plot_point(structure: StoryStructure) -> Optional[StoryBeat]: + return next((x for x in structure.beats if x in second_plot_points), None) + + def find_midpoint(structure: StoryStructure) -> Optional[StoryBeat]: return next((x for x in structure.beats if x in midpoints), None) @@ -359,6 +384,15 @@ def __init__(self, novel: Novel, structure: StoryStructure, parent=None): menu.options.optionSelected.connect(self._midpointChanged) menu.options.optionsReset.connect(self._midpointReset) + self.btnSecondPlotPoint = ActOptionsButton('Second Plot Point', 2) + self.btnSecondPlotPoint.setIcon(IconRegistry.from_name('mdi6.chevron-triple-right')) + spp_beat = find_second_plot_point(self._structure) + checked = _ThreeActSecondPlotPoint.Aha_moment if spp_beat == second_plot_point_aha else None + menu = StructureOptionsMenu(self.btnSecondPlotPoint, 'Customize', + [_ThreeActSecondPlotPoint.Aha_moment], checked=checked) + menu.options.optionSelected.connect(self._secondPlotPointChanged) + menu.options.optionsReset.connect(self._secondPlotPointReset) + crisis_beat = find_crisis(self._structure) checked = option_from_beat(crisis_beat) if crisis_beat else None self.btnEnding = ActOptionsButton('Ending', 3) @@ -371,9 +405,9 @@ def __init__(self, novel: Novel, structure: StoryStructure, parent=None): self.toggle4act = Toggle() self.toggle4act.setChecked(midpoint_beat.ends_act) - wdg = group(spacer(), self.btnBeginning, self.btnFirstPlotPoint, self.btnMidpoint, + wdg = group(spacer(), self.btnBeginning, self.btnFirstPlotPoint, self.btnMidpoint, self.btnSecondPlotPoint, self.btnEnding, spacer(), spacing=15) - wdg.layout().insertWidget(1, self.lblCustomization, alignment=Qt.AlignmentFlag.AlignTop) + wdg.layout().insertWidget(1, self.lblCustomization, alignment=Qt.AlignmentFlag.AlignBottom) lbl = push_btn(text='Split 2nd act into two parts', transparent_=True) lbl.clicked.connect(self.toggle4act.animateClick) wdg.layout().addWidget(group(lbl, self.toggle4act, spacing=0, margin=0)) @@ -413,6 +447,21 @@ def _firstPlotPointReset(self): if current_pp: self.beatsPreview.replaceBeat(current_pp, copy.deepcopy(first_plot_point)) + def _secondPlotPointChanged(self, option: _ThreeActSecondPlotPoint): + if option == _ThreeActSecondPlotPoint.Aha_moment: + beat = second_plot_point_aha + else: + beat = second_plot_point + + current_pp = find_second_plot_point(self._structure) + if current_pp: + self.beatsPreview.replaceBeat(current_pp, copy.deepcopy(beat)) + + def _secondPlotPointReset(self): + current_pp = find_second_plot_point(self._structure) + if current_pp: + self.beatsPreview.replaceBeat(current_pp, copy.deepcopy(second_plot_point)) + def _midpointChanged(self, midpoint_option: _ThreeActMidpoint): if midpoint_option == _ThreeActMidpoint.Turning_point: beat = midpoint