Created
July 20, 2012 02:54
-
-
Save russdill/3148380 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright 2012, Russ.Dill@asu.edu | |
* Released under LGPLv2 or later */ | |
#include <math.h> | |
#include "config.h" | |
#include "data.h" | |
#include "rtree.h" | |
#include "mirror.h" | |
#include "remove.h" | |
#include "select.h" | |
#include "draw.h" | |
#include "undo.h" | |
#include "move.h" | |
#include "change.h" | |
#include "copy.h" | |
#include "rotate.h" | |
#include "global.h" | |
static char *new_footprint; | |
static int | |
direction (Coord x1, Coord y1, Coord x2, Coord y2) | |
{ | |
if (x1 != x2 || y1 != y2) | |
{ | |
double theta = atan2(y2 - y1, x2 - x1); | |
theta *= 2.0 / M_PI; | |
theta += 4.5; | |
return (int) theta % 4; | |
} | |
return -1; | |
} | |
static BYTE | |
_ElementOrientation (ElementType *e) | |
{ | |
BYTE ret; | |
PIN_LOOP (e) | |
{ | |
ret = direction(e->MarkX, e->MarkY, pin->X, pin->Y); | |
if (ret != -1) | |
return ret; | |
} | |
END_LOOP; | |
PAD_LOOP (e) | |
{ | |
ret = direction(e->MarkX, e->MarkY, pad->Point1.X, pad->Point1.Y); | |
if (ret != -1) | |
return ret; | |
ret = direction(e->MarkX, e->MarkY, pad->Point2.X, pad->Point2.Y); | |
if (ret != -1) | |
return ret; | |
} | |
END_LOOP; | |
return 0; | |
} | |
static void * | |
ReplaceElement (ElementType *Element) | |
{ | |
int i; | |
FlagType flags; | |
Coord element_x, element_y; | |
Coord text_x, text_y; | |
TextType *name; | |
BYTE element_rotation; | |
BYTE text_rotation; | |
BYTE paste_rotation; | |
BYTE new_rotation; | |
int scale; | |
char *refdes; | |
char *value; | |
char *old; | |
ElementType *paste_element = NULL; | |
ELEMENT_LOOP (PASTEBUFFER->Data) | |
{ | |
if (paste_element) | |
{ | |
/* More than one element */ | |
return NULL; | |
} | |
paste_element = element; | |
} | |
END_LOOP; | |
if (!paste_element) | |
{ | |
/* No element to paste */ | |
return NULL; | |
} | |
flags = Element->Flags; | |
element_x = Element->MarkX; | |
element_y = Element->MarkY; | |
element_rotation = _ElementOrientation (Element); | |
name = &Element->Name[NAMEONPCB_INDEX]; | |
text_x = name->X; | |
text_y = name->Y; | |
text_rotation = name->Direction; | |
scale = name->Scale; | |
refdes = strdup (name->TextString); | |
name = &Element->Name[VALUE_INDEX]; | |
value = strdup (name->TextString); | |
paste_element = CopyElementLowLevel(PCB->Data, NULL, paste_element, | |
TEST_FLAG (UNIQUENAMEFLAG, PCB), | |
element_x - paste_element->MarkX, | |
element_y - paste_element->MarkY); | |
if (!FRONT (Element)) | |
MirrorElementCoordinates (PCB->Data, paste_element, | |
paste_element->MarkY*2 - PCB->MaxHeight); | |
// Thermals and polygon zero clearance | |
PIN_LOOP (Element) | |
{ | |
PinType *old = pin; | |
if (pin->Number) | |
{ | |
PIN_LOOP (paste_element) | |
{ | |
if (pin->Number && !strcmp (pin->Number, old->Number)) | |
{ | |
if (!old->Clearance) | |
pin->Clearance = 0; | |
for (i = 0; i < MAX_LAYER; i++) | |
ASSIGN_THERM (i, GET_THERM (i, old), pin); | |
} | |
} | |
END_LOOP; | |
} | |
} | |
END_LOOP; | |
PAD_LOOP (Element) | |
{ | |
PadType *old = pad; | |
if (old->Number) | |
{ | |
PAD_LOOP (paste_element) | |
{ | |
if (pad->Number && !strcmp (pad->Number, old->Number)) | |
{ | |
if (!old->Clearance) | |
pad->Clearance = 0; | |
for (i = 0; i < MAX_LAYER; i++) | |
ASSIGN_THERM (i, GET_THERM (i, old), pad); | |
} | |
} | |
END_LOOP; | |
} | |
} | |
END_LOOP; | |
RemoveElement(Element); | |
paste_element->Flags = flags; | |
old = ChangeElementText(PCB, PCB->Data, paste_element, NAMEONPCB_INDEX, | |
refdes); | |
if (old) | |
free(old); | |
old = ChangeElementText(PCB, PCB->Data, paste_element, VALUE_INDEX, | |
value); | |
if (old) | |
free(old); | |
if (new_footprint) | |
{ | |
old = ChangeElementText(PCB, PCB->Data, paste_element, DESCRIPTION_INDEX, | |
strdup (new_footprint)); | |
if (old) | |
free(old); | |
} | |
SaveUndoSerialNumber (); | |
paste_rotation = _ElementOrientation (paste_element); | |
new_rotation = (paste_rotation - element_rotation) & 3; | |
RotateElementLowLevel (PCB->Data, paste_element, paste_element->MarkX, | |
paste_element->MarkY, new_rotation); | |
ELEMENTTEXT_LOOP (paste_element); | |
{ | |
BYTE rot; | |
if (PCB->Data->name_tree[n]) | |
r_delete_entry (PCB->Data->name_tree[n], (BoxType *)text); | |
MOVE_TEXT_LOWLEVEL (text, text_x - text->X, text_y - text->Y); | |
text->Scale = scale; | |
rot = text_rotation - text->Direction + 4; | |
RotateTextLowLevel (text, text->X, text->Y, rot & 3); | |
if (PCB->Data->name_tree[n]) | |
r_insert_entry (PCB->Data->name_tree[n], (BoxType *)text, 0); | |
} | |
END_LOOP; | |
RestoreUndoSerialNumber (); | |
AddObjectToCreateUndoList (ELEMENT_TYPE, paste_element, paste_element, | |
paste_element); | |
if (PCB->ElementOn && (FRONT (paste_element) || PCB->InvisibleObjectsOn)) | |
{ | |
DrawElementName (paste_element); | |
DrawElementPackage (paste_element); | |
} | |
if (PCB->PinOn) | |
{ | |
DrawElementPinsAndPads (paste_element); | |
} | |
return NULL; | |
} | |
static ObjectFunctionType ReplaceFunctions = { | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
ReplaceElement, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
}; | |
static int | |
replace (int argc, char **argv, Coord x, Coord y) | |
{ | |
new_footprint = NULL; | |
if (argc > 0) | |
{ | |
new_footprint = argv[0]; | |
} | |
if (SelectedOperation (&ReplaceFunctions, true, ELEMENT_TYPE)) | |
{ | |
IncrementUndoSerialNumber (); | |
Draw (); | |
} | |
else | |
{ | |
} | |
return 0; | |
} | |
static HID_Action replace_action_list[] = { | |
{"ReplaceSelected", NULL, replace, | |
NULL, NULL} | |
}; | |
REGISTER_ACTIONS (replace_action_list) | |
void | |
pcb_plugin_init() | |
{ | |
register_replace_action_list(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment