Skip to content

Commit

Permalink
Merge pull request #236 from tscircuit/schematic-box-improvements
Browse files Browse the repository at this point in the history
Schematic box improvements, render PinHeader properly
  • Loading branch information
seveibar authored Nov 5, 2024
2 parents 0244ab7 + 00d5b4c commit bd370d4
Show file tree
Hide file tree
Showing 19 changed files with 215 additions and 211 deletions.
Binary file modified bun.lockb
Binary file not shown.
117 changes: 107 additions & 10 deletions lib/components/base-components/NormalComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CadModelObj,
CadModelProp,
CadModelStl,
SchematicPortArrangement,
} from "@tscircuit/props"
import { point3, rotation } from "circuit-json"
import Debug from "debug"
Expand All @@ -25,6 +26,12 @@ import { ZodType, z } from "zod"
import { Footprint } from "../primitive-components/Footprint"
import { Port } from "../primitive-components/Port"
import { PrimitiveComponent } from "./PrimitiveComponent"
import {
getAllDimensionsForSchematicBox,
type SchematicBoxDimensions,
} from "lib/utils/schematic/getAllDimensionsForSchematicBox"
import { underscorifyPortArrangement } from "lib/soup/underscorifyPortArrangement"
import { underscorifyPinStyles } from "lib/soup/underscorifyPinStyles"

const debug = Debug("tscircuit:core")

Expand Down Expand Up @@ -253,14 +260,29 @@ export class NormalComponent<

/**
* Render the schematic component for this NormalComponent using the
* config.schematicSymbolName if it exists.
* config.schematicSymbolName if it exists, or create a generic box if
* no symbol is defined.
*
* You can override this method to do more complicated things.
*/
doInitialSchematicComponentRender() {
const { db } = this.root!
const { schematicSymbolName } = this.config
if (!schematicSymbolName) return
if (schematicSymbolName) {
return this._doInitialSchematicComponentRenderWithSymbol()
}

const dimensions = this._getSchematicBoxDimensions()
if (dimensions) {
return this._doInitialSchematicComponentRenderWithSchematicBoxDimensions()
}

// No schematic symbol or dimensions defined, this could be a board, group
// or other NormalComponent that doesn't have a schematic representation
}

_doInitialSchematicComponentRenderWithSymbol() {
const { db } = this.root!

// TODO switch between horizontal and vertical based on schRotation
const base_symbol_name = this.config.schematicSymbolName
const symbol_name_horz = `${base_symbol_name}_horz`
Expand All @@ -281,18 +303,48 @@ export class NormalComponent<

const symbol: SchSymbol | undefined = symbols[symbol_name]

if (!symbol) {
throw new Error(`Could not find schematic-symbol "${symbol_name}"`)
if (symbol) {
const schematic_component = db.schematic_component.insert({
center: { x: this.props.schX ?? 0, y: this.props.schY ?? 0 },
rotation: this.props.schRotation ?? 0,
size: symbol.size,
source_component_id: this.source_component_id!,

symbol_name,
})
this.schematic_component_id = schematic_component.schematic_component_id
}
}

_doInitialSchematicComponentRenderWithSchematicBoxDimensions() {
const { db } = this.root!
const { _parsedProps: props } = this
const dimensions = this._getSchematicBoxDimensions()!

const primaryPortLabels: Record<string, string> = {}
for (const [port, label] of Object.entries(props.pinLabels ?? {})) {
primaryPortLabels[port] = Array.isArray(label) ? label[0] : label
}

const schematic_component = db.schematic_component.insert({
center: { x: this.props.schX ?? 0, y: this.props.schY ?? 0 },
rotation: this.props.schRotation ?? 0,
size: symbol.size,
source_component_id: this.source_component_id!,
center: { x: props.schX ?? 0, y: props.schY ?? 0 },
rotation: props.schRotation ?? 0,
size: dimensions.getSize(),

port_arrangement: underscorifyPortArrangement(
props.schPortArrangement as any,
),

pin_spacing: props.schPinSpacing ?? 0.2,

// @ts-ignore soup needs to support distance for pin_styles
pin_styles: underscorifyPinStyles(props.schPinStyle),

symbol_name,
port_labels: primaryPortLabels,

source_component_id: this.source_component_id!,
})

this.schematic_component_id = schematic_component.schematic_component_id
}

Expand Down Expand Up @@ -545,6 +597,51 @@ export class NormalComponent<
}
}

_getPinCount(): number {
const schPortArrangement = this._getSchematicPortArrangement()
const pinCountFromSchArrangement =
(schPortArrangement?.leftSize ?? 0) +
(schPortArrangement?.rightSize ?? 0) +
(schPortArrangement?.topSize ?? 0) +
(schPortArrangement?.bottomSize ?? 0)
const pinCount =
pinCountFromSchArrangement || this.getPortsFromFootprint().length
return pinCount
}

/**
* Override the schematic port arrangement if you want to customize where pins
* appear on a schematic box, e.g. for a pin header
*/
_getSchematicPortArrangement(): SchematicPortArrangement | null {
return this._parsedProps.schPortArrangement
}

_getSchematicBoxDimensions(): SchematicBoxDimensions | null {
// Only valid if we don't have a schematic symbol
if (this.getSchematicSymbol()) return null
if (!this.config.shouldRenderAsSchematicBox) return null

const { _parsedProps: props } = this

const pinCount = this._getPinCount()

const pinSpacing = props.schPinSpacing ?? 0.2

const dimensions = getAllDimensionsForSchematicBox({
schWidth: props.schWidth,
schHeight: props.schHeight,
schPinSpacing: pinSpacing,
schPinStyle: props.schPinStyle,

pinCount,

schPortArrangement: this._getSchematicPortArrangement()!,
})

return dimensions
}

doInitialCadModelRender(): void {
const { db } = this.root!
const { boardThickness = 0 } = this.root?._getBoard() ?? {}
Expand Down
18 changes: 18 additions & 0 deletions lib/components/base-components/PrimitiveComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ import { z } from "zod"
import type { Circuit } from "../../Circuit"
import type { ISubcircuit } from "../primitive-components/Group/ISubcircuit"
import { Renderable } from "./Renderable"
import type { SchematicBoxDimensions } from "lib/utils/schematic/getAllDimensionsForSchematicBox"

export interface BaseComponentConfig {
componentName: string
schematicSymbolName?: BaseSymbolName | null
zodProps: ZodType
sourceFtype?: AnySourceComponent["ftype"] | null
shouldRenderAsSchematicBox?: boolean
}

/**
Expand Down Expand Up @@ -509,6 +511,22 @@ export abstract class PrimitiveComponent<
return descendants
}

/**
* Return the number of pins in this component, this is important for
* NormalComponents
*/
_getPinCount(): number {
return 0
}

/**
* If this component represents a SchematicBox (like a Chip), return the
* dimensions of the box, which allows computing the position of ports etc.
*/
_getSchematicBoxDimensions(): SchematicBoxDimensions | null {
return null
}

// TODO we shouldn't need to override this, errors can be rendered and handled
// by the Renderable class, however, the Renderable class currently doesn't
// have access to the database or cleanup
Expand Down
58 changes: 2 additions & 56 deletions lib/components/normal-components/Chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
typeof chipProps,
PinLabels
> {
schematicDimensions: SchematicBoxDimensions | null = null
schematicBoxDimensions: SchematicBoxDimensions | null = null

get config() {
return {
componentName: "Chip",
zodProps: chipProps,
shouldRenderAsSchematicBox: true,
}
}

Expand All @@ -34,61 +35,6 @@ export class Chip<PinLabels extends string = never> extends NormalComponent<
this.source_component_id = source_component.source_component_id!
}

doInitialSchematicComponentRender() {
const { db } = this.root!
const { _parsedProps: props } = this

const pinCountFromSchArrangement =
(props.schPortArrangement?.leftSize ?? 0) +
(props.schPortArrangement?.rightSize ?? 0) +
(props.schPortArrangement?.topSize ?? 0) +
(props.schPortArrangement?.bottomSize ?? 0)
const pinCount = pinCountFromSchArrangement || this.getPortsFromFootprint().length

const pinSpacing = props.schPinSpacing ?? 0.2

const dimensions = getAllDimensionsForSchematicBox({
schWidth: props.schWidth,
schHeight: props.schHeight,
schPinSpacing: pinSpacing,
schPinStyle: props.schPinStyle,

pinCount,

// @ts-ignore there's a subtley in the definition difference with
// leftSide/rightSide/topSide/bottomSide in how the direction is defined
// that doesn't really matter
schPortArrangement: props.schPortArrangement,
})
this.schematicDimensions = dimensions

const primaryPortLabels: Record<string, string> = {}
for (const [port, label] of Object.entries(props.pinLabels ?? {})) {
primaryPortLabels[port] = Array.isArray(label) ? label[0] : label
}

const schematic_component = db.schematic_component.insert({
center: { x: props.schX ?? 0, y: props.schY ?? 0 },
rotation: props.schRotation ?? 0,
size: dimensions.getSize(),

port_arrangement: underscorifyPortArrangement(
props.schPortArrangement as any,
),

pin_spacing: pinSpacing,

// @ts-ignore soup needs to support distance for pin_styles
pin_styles: underscorifyPinStyles(props.schPinStyle),

port_labels: primaryPortLabels,

source_component_id: this.source_component_id!,
})

this.schematic_component_id = schematic_component.schematic_component_id
}

doInitialPcbComponentRender() {
const { db } = this.root!
const { _parsedProps: props } = this
Expand Down
49 changes: 1 addition & 48 deletions lib/components/normal-components/Jumper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
return {
componentName: "Jumper",
zodProps: jumperProps,
shouldRenderAsSchematicBox: true,
}
}

Expand All @@ -36,54 +37,6 @@ export class Jumper<PinLabels extends string = never> extends NormalComponent<
this.source_component_id = source_component.source_component_id!
}

doInitialSchematicComponentRender() {
const { db } = this.root!
const { _parsedProps: props } = this

const ports = this.children.filter((child) => child instanceof Port)

const pinSpacing = props.schPinSpacing ?? 0.2

const dimensions = getAllDimensionsForSchematicBox({
schWidth: props.schWidth,
schHeight: props.schHeight,
schPinSpacing: pinSpacing,
schPinStyle: props.schPinStyle,

pinCount: ports.length,

// @ts-ignore there's a subtley in the definition difference with
// leftSide/rightSide/topSide/bottomSide in how the direction is defined
// that doesn't really matter
schPortArrangement: {
// TODO use schematic direction or schPortArrangement
rightSize: ports.length,
},
})
this.schematicDimensions = dimensions

const schematic_component = db.schematic_component.insert({
center: { x: props.schX ?? 0, y: props.schY ?? 0 },
rotation: props.schRotation ?? 0,
size: dimensions.getSize(),

port_arrangement: underscorifyPortArrangement(
props.schPortArrangement as any,
),

pin_spacing: pinSpacing,

// @ts-ignore soup needs to support distance for pin_styles
pin_styles: underscorifyPinStyles(props.schPinStyle),

port_labels: props.pinLabels,

source_component_id: this.source_component_id!,
})

this.schematic_component_id = schematic_component.schematic_component_id
}

doInitialPcbComponentRender() {
const { db } = this.root!
const { _parsedProps: props } = this
Expand Down
29 changes: 9 additions & 20 deletions lib/components/normal-components/PinHeader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { pinHeaderProps } from "@tscircuit/props"
import { pinHeaderProps, type SchematicPortArrangement } from "@tscircuit/props"
import { NormalComponent } from "../base-components/NormalComponent"
import { Port } from "../primitive-components/Port"
import type { BaseSymbolName } from "lib/utils/constants"
Expand All @@ -8,7 +8,7 @@ export class PinHeader extends NormalComponent<typeof pinHeaderProps> {
return {
componentName: "PinHeader",
zodProps: pinHeaderProps,
schematicSymbolName: "pinrow_horz" as BaseSymbolName,
shouldRenderAsSchematicBox: true,
}
}

Expand Down Expand Up @@ -41,6 +41,13 @@ export class PinHeader extends NormalComponent<typeof pinHeaderProps> {
}
}

_getSchematicPortArrangement(): SchematicPortArrangement | null {
return {
leftSize: 0,
rightSize: this._parsedProps.pinCount ?? 1,
}
}

doInitialSourceRender() {
const { db } = this.root!
const { _parsedProps: props } = this
Expand All @@ -56,22 +63,4 @@ export class PinHeader extends NormalComponent<typeof pinHeaderProps> {

this.source_component_id = source_component.source_component_id
}

doInitialSchematicComponentRender() {
const { db } = this.root!
const { _parsedProps: props } = this

const schematic_component = db.schematic_component.insert({
center: { x: props.schX ?? 0, y: props.schY ?? 0 },
rotation: props.schRotation ?? 0,
size: { width: 2, height: props.pinCount ?? 1 },
source_component_id: this.source_component_id!,
port_arrangement: {
left_size: 0,
right_size: props.pinCount ?? 1,
},
})

this.schematic_component_id = schematic_component.schematic_component_id
}
}
Loading

0 comments on commit bd370d4

Please sign in to comment.