Skip to content

New Script Submission: UTILIDAD Crear ollados #46

Description

@kiniBTK

Script Name: UTILIDAD Crear ollados
Author: kiniBTK
Description: Genera ollados vectoriales nativos en esquinas o lados seleccionados con control de diámetro, margen y distribución. Incluye modo de fusión Multiplicar automático para la capa técnica. Category: Imprenta / Utilidad Version: 1.6.0

Code:
"use strict";

/**

  • name: UTILIDAD Crear ollados
  • description: Marca agujeros (ollados) en esquinas y lados con diámetro, margen y distribución automática. Capa "Agujeros/Ollados", Tinta "Corte" y modo "Multiplicar".
  • version: 1.6.0
    */

const { Document } = require("/document");
const {
DocumentCommand,
AddChildNodesCommandBuilder,
InsertionMode
} = require("/commands");
const { ShapeNodeDefinition, ContainerNodeDefinition } = require("/nodes");
const { ShapeEllipse } = require("/shapes");
const { CMYKf } = require("/colours");
const { FillDescriptor } = require("/fills");
const { Rectangle } = require("/geometry");
const { Dialog, DialogResult } = require("/dialog");
const { UnitType } = require("/units");
const { BlendMode } = require("affinity:common");

function main() {
const doc = Document.current;
if (!doc) return;

const spread = doc.currentSpread;
const dpi = doc.dpi;
const mmToPx = dpi / 25.4;

// =================================================================
// INTERFAZ DE USUARIO
// =================================================================
const dlg = Dialog.create("Crear Ollados (Affinity)");
dlg.initialWidth = 360;
const col = dlg.addColumn();

const pnlConfig = col.addGroup("Configuración (mm)");
const diamCtrl = pnlConfig.addUnitValueEditor("Diámetro", UnitType.Millimetre, UnitType.Millimetre, 25, 1, 1000);
const margCtrl = pnlConfig.addUnitValueEditor("Margen", UnitType.Millimetre, UnitType.Millimetre, 20, 0, 1000);

const pnlMode = col.addGroup("Opciones de colocación");
const chkCornersOnly = pnlMode.addCheckBox("Colocar solo las 4 esquinas", false);

const pnlLados = col.addGroup("Lados a rellenar (incluye sus esquinas)");
const chkTop = pnlLados.addCheckBox("Lado Superior", true);
const chkBot = pnlLados.addCheckBox("Lado Inferior", true);
const chkLeft = pnlLados.addCheckBox("Lado Izquierdo", true);
const chkRight = pnlLados.addCheckBox("Lado Derecho", true);

const pnlDist = col.addGroup("Parámetros de distribución");
const distCtrl = pnlDist.addUnitValueEditor("Distancia mín. entre centros (mm)", UnitType.Millimetre, UnitType.Millimetre, 500, 10, 10000);

const result = dlg.runModal();
if (result.value !== DialogResult.Ok.value) return;

// =================================================================
// LÓGICA DE CREACIÓN
// =================================================================
const diam = diamCtrl.value * mmToPx;
const marg = margCtrl.value * mmToPx;
const minDist = distCtrl.value * mmToPx;
const radio = diam / 2;

const box = spread.getSpreadBaseBox(false);
const L = box.x, T = box.y;
const R = box.x + box.width, B = box.y + box.height;

// Posiciones teóricas de las 4 esquinas
const cTL = { x: L + marg + radio, y: T + marg + radio };
const cTR = { x: R - (marg + radio), y: T + marg + radio };
const cBL = { x: L + marg + radio, y: B - (marg + radio) };
const cBR = { x: R - (marg + radio), y: B - (marg + radio) };

// 1. Crear Grupo
const groupDef = ContainerNodeDefinition.create("Agujeros/Ollados");
groupDef.userDescription = "Agujeros/Ollados";
const groupBuilder = AddChildNodesCommandBuilder.create();
groupBuilder.setInsertionTarget(spread);
groupBuilder.setInsertionMode(InsertionMode.InsertAtEnd);
groupBuilder.addContainerNode(groupDef);
const groupCmd = groupBuilder.createCommand(false);
doc.executeCommand(groupCmd);
const groupNode = groupCmd.newNodes[0];

if (!groupNode) return;

// Configurar el modo de fusión del GRUPO a MULTIPLICAR
try {
    groupNode.blendMode = BlendMode.Multiply;
} catch (e) {
    try {
        doc.executeCommand(DocumentCommand.createSetBlendMode(groupNode.selfSelection, BlendMode.Multiply));
    } catch (err) {}
}

// 2. Estilo
const corteColor = CMYKf(0, 1, 0, 0); 
const stroke = FillDescriptor.createSolid(corteColor, BlendMode.Multiply);
const none = FillDescriptor.createNone();

// Set para evitar duplicados en las esquinas
const pointsToDraw = [];

function addPoint(x, y) {
    // Evitar duplicados exactos (margen de 0.1px por redondeos)
    const exists = pointsToDraw.some(p => Math.abs(p.x - x) < 0.1 && Math.abs(p.y - y) < 0.1);
    if (!exists) pointsToDraw.push({ x, y });
}

function drawCircle(cx, cy) {
    const shape = ShapeEllipse.create();
    const rect = new Rectangle(cx - radio, cy - radio, diam, diam);
    const def = ShapeNodeDefinition.create(shape, rect, none);
    const b = AddChildNodesCommandBuilder.create();
    b.setInsertionTarget(groupNode);
    b.addShapeNode(def);
    const cmd = b.createCommand(false);
    doc.executeCommand(cmd);

    const node = cmd.newNodes[0];
    if (node) {
        const sel = node.selfSelection;
        doc.executeCommand(DocumentCommand.createSetPenFill(sel, stroke));
        doc.executeCommand(DocumentCommand.createSetBrushFill(sel, none));
        node.lineWeightPts = 0.5;
        try { node.blendMode = BlendMode.Multiply; } catch(e) {}
    }
}

function calculateDistribution(startPos, endPos, isHorizontal) {
    const totalLen = isHorizontal ? Math.abs(endPos.x - startPos.x) : Math.abs(endPos.y - startPos.y);
    if (totalLen <= minDist) return;
    const numIntervals = Math.floor(totalLen / minDist);
    const actualDist = totalLen / numIntervals;
    for (let j = 1; j < numIntervals; j++) {
        if (isHorizontal) addPoint(startPos.x + (actualDist * j), startPos.y);
        else addPoint(startPos.x, startPos.y + (actualDist * j));
    }
}

// Lógica de selección selectiva
if (chkCornersOnly.value) {
    addPoint(cTL.x, cTL.y);
    addPoint(cTR.x, cTR.y);
    addPoint(cBL.x, cBL.y);
    addPoint(cBR.x, cBR.y);
} else {
    if (chkTop.value) {
        addPoint(cTL.x, cTL.y);
        addPoint(cTR.x, cTR.y);
        calculateDistribution(cTL, cTR, true);
    }
    if (chkBot.value) {
        addPoint(cBL.x, cBL.y);
        addPoint(cBR.x, cBR.y);
        calculateDistribution(cBL, cBR, true);
    }
    if (chkLeft.value) {
        addPoint(cTL.x, cTL.y);
        addPoint(cBL.x, cBL.y);
        calculateDistribution(cTL, cBL, false);
    }
    if (chkRight.value) {
        addPoint(cTR.x, cTR.y);
        addPoint(cBR.x, cBR.y);
        calculateDistribution(cTR, cBR, false);
    }
}

// Dibujar todos los puntos calculados
pointsToDraw.forEach(p => drawCircle(p.x, p.y));

}

module.exports.main = main;
main();

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions