diff --git a/scripts/constants.jsx b/scripts/constants.jsx index ac29327..b8a2ae9 100644 --- a/scripts/constants.jsx +++ b/scripts/constants.jsx @@ -93,6 +93,7 @@ var LayerNames = { RULES_TEXT_CREATURE_FLIP: "Rules Text - Creature Flip", RULES_TEXT_ADVENTURE: "Rules Text - Adventure", MUTATE: "Mutate", + DIVIDER: "Divider", // planar text and icons STATIC_ABILITY: "Static Ability", @@ -176,7 +177,7 @@ var font_name_ndpmtg = "NDPMTG"; // Font spacing var modal_indent = 5.7; var line_break_lead = 2.4; -var flavour_text_lead = 4.4; +var flavour_text_lead = 7; // 4.4 without flavour text divider, 7 with // Symbol colours var rgb_c = new SolidColor(); diff --git a/scripts/templates.jsx b/scripts/templates.jsx index 0082afa..045ac37 100644 --- a/scripts/templates.jsx +++ b/scripts/templates.jsx @@ -283,6 +283,7 @@ var NormalTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = is_centred, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), pt_reference_layer = text_and_icons.layers.getByName(LayerNames.PT_REFERENCE), pt_top_reference_layer = text_and_icons.layers.getByName(LayerNames.PT_TOP_REFERENCE), ), @@ -301,6 +302,7 @@ var NormalTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = is_centred, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ), ); @@ -411,6 +413,7 @@ var NormalClassicTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = is_centred, reference_layer = reference_layer, + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ), ); @@ -613,6 +616,7 @@ var ExpeditionTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = false, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ), ); }, @@ -673,6 +677,7 @@ var MiracleTemplate = new Class({ flavour_text = this.layout.flavour_text, is_centred = false, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ), ); }, @@ -778,6 +783,7 @@ var TransformFrontTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = is_centred, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), pt_reference_layer = text_and_icons.layers.getByName(LayerNames.PT_REFERENCE), pt_top_reference_layer = text_and_icons.layers.getByName(LayerNames.PT_TOP_REFERENCE), ), @@ -799,6 +805,7 @@ var TransformFrontTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = is_centred, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ), ); @@ -850,6 +857,7 @@ var IxalanTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = false, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ), ); }, @@ -942,6 +950,7 @@ var MutateTemplate = Class({ flavour_text = this.layout.flavour_text, is_centred = false, reference_layer = text_and_icons.layers.getByName(LayerNames.MUTATE_REFERENCE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ) ); } @@ -987,6 +996,7 @@ var AdventureTemplate = Class({ flavour_text = "", is_centred = false, reference_layer = text_and_icons.layers.getByName(LayerNames.TEXTBOX_REFERENCE_ADVENTURE), + divider_layer = text_and_icons.layers.getByName(LayerNames.DIVIDER), ), new TextField( layer = type_line, diff --git a/scripts/text_layers.jsx b/scripts/text_layers.jsx index 3f39be7..0b5f8ef 100644 --- a/scripts/text_layers.jsx +++ b/scripts/text_layers.jsx @@ -78,6 +78,7 @@ function vertically_align_text(layer, reference_layer) { function vertically_nudge_creature_text(layer, reference_layer, top_reference_layer) { /** * Vertically nudge a creature's text layer if it overlaps with the power/toughness box, determined by the given reference layers. + * Returns the amount by which the text layer was nudged. */ // if the layer needs to be nudged @@ -118,6 +119,8 @@ function vertically_nudge_creature_text(layer, reference_layer, top_reference_la } clear_selection(); + + return delta; } } @@ -229,12 +232,15 @@ var FormattedTextField = Class({ } this.is_centred = is_centred; }, - execute: function () { - this.super(); + determine_italics_text_and_flavour_index: function() { + /** + * Returns an array of italic text for the instance's text contents and the index at which flavour text begins. + * Within flavour text, any text between asterisks should not be italicised, and the asterisks should not be included + * in the rendered flavour text. + */ - // generate italic text arrays from things in (parentheses), ability words, and the given flavour text - var italic_text = generate_italics(this.text_contents); - var flavour_index = -1; + var italic_text = generate_italics(this.text_contents); + var flavour_index = -1; if (this.flavour_text.length > 1) { // remove things between asterisks from flavour text if necessary @@ -253,6 +259,18 @@ var FormattedTextField = Class({ } flavour_index = this.text_contents.length; } + return { + flavour_index: flavour_index, + italic_text: italic_text, + } + }, + execute: function () { + this.super(); + + // generate italic text arrays from things in (parentheses), ability words, and the given flavour text + var ret = this.determine_italics_text_and_flavour_index(); + var flavour_index = ret.flavour_index; + var italic_text = ret.italic_text; app.activeDocument.activeLayer = this.layer; format_text(this.text_contents + "\r" + this.flavour_text, italic_text, flavour_index, this.is_centred); @@ -267,12 +285,60 @@ var FormattedTextArea = Class({ * A FormattedTextField where the text is required to fit within a given area. An instance of this class will step down the font size * until the text fits within the reference layer's bounds (in 0.25 pt increments), then rasterise the text layer, and centre it vertically * with respect to the reference layer's pixels. + * Positions the flavour text divider after sizing the text to the given area. */ extends_: FormattedTextField, - constructor: function (layer, text_contents, text_colour, flavour_text, is_centred, reference_layer) { + constructor: function (layer, text_contents, text_colour, flavour_text, is_centred, reference_layer, divider_layer) { this.super(layer, text_contents, text_colour, flavour_text, is_centred); this.reference_layer = reference_layer; + this.divider_layer = divider_layer; + }, + insert_divider: function() { + /** + * Inserts the flavour text divider between rules text and flavour text. + * The position of the divider is calculated by creating two copies of `this.layer`, rendering `this.text_contents` in the first copy + * and `this.flavour_text` in the second copy, then finding the midpoint between the bottom of the first copy and the top of the second copy. + * This method is slighty imperfect because of how the shape of the text layer can affect how flavour text is positioned, but should be close enough. + */ + + if (this.flavour_text.length !== "") { + var ret = this.determine_italics_text_and_flavour_index(); + var flavour_index = ret.flavour_index; + var italic_text = ret.italic_text; + + var layer_bounds = compute_text_layer_bounds(this.layer); + + var layer_text_contents = this.layer.duplicate(); + app.activeDocument.activeLayer = layer_text_contents; + format_text(this.text_contents, italic_text, flavour_index, this.is_centred); + layer_text_contents.rasterize(RasterizeType.ENTIRELAYER); + text_contents_bottom = layer_text_contents.bounds[3].as("px"); + + var layer_flavour_text = this.layer.duplicate(); + app.activeDocument.activeLayer = layer_flavour_text; + format_text(this.flavour_text, italic_text, flavour_index, this.is_centred); + layer_flavour_text.rasterize(RasterizeType.ENTIRELAYER); + layer_flavour_text.translate(0, layer_bounds[3].as("px") - layer_flavour_text.bounds[3].as("px")); + var flavour_text_top = layer_flavour_text.bounds[1].as("px"); + + var divider_y_midpoint = (text_contents_bottom + flavour_text_top) / 2; + + layer_text_contents.remove(); + layer_flavour_text.remove(); + + app.activeDocument.activeLayer = this.divider_layer; + this.divider_layer.visible = true; + + app.activeDocument.selection.select([ + [0, divider_y_midpoint - 1], + [1, divider_y_midpoint - 1], + [1, divider_y_midpoint + 1], + [0, divider_y_midpoint + 1] + ]); + align_vertical(); + clear_selection(); + } }, execute: function () { this.super(); @@ -283,6 +349,8 @@ var FormattedTextArea = Class({ // centre vertically vertically_align_text(this.layer, this.reference_layer); + + this.insert_divider(); } } }); @@ -295,8 +363,8 @@ var CreatureFormattedTextArea = Class({ */ extends_: FormattedTextArea, - constructor: function (layer, text_contents, text_colour, flavour_text, is_centred, reference_layer, pt_reference_layer, pt_top_reference_layer) { - this.super(layer, text_contents, text_colour, flavour_text, is_centred, reference_layer); + constructor: function (layer, text_contents, text_colour, flavour_text, is_centred, reference_layer, divider_layer, pt_reference_layer, pt_top_reference_layer) { + this.super(layer, text_contents, text_colour, flavour_text, is_centred, reference_layer, divider_layer); this.pt_reference_layer = pt_reference_layer; this.pt_top_reference_layer = pt_top_reference_layer; }, @@ -304,6 +372,9 @@ var CreatureFormattedTextArea = Class({ this.super(); // shift vertically if the text overlaps the PT box - vertically_nudge_creature_text(this.layer, this.pt_reference_layer, this.pt_top_reference_layer); + var delta = vertically_nudge_creature_text(this.layer, this.pt_reference_layer, this.pt_top_reference_layer); + if (delta < 0) { + this.divider_layer.applyOffset(0, new UnitValue(delta, "px"), OffsetUndefinedAreas.SETTOBACKGROUND); + } } })