71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
# Copyright (c) 2023, Manfred Moitzi
|
|
# License: MIT License
|
|
"""
|
|
This module provides helper tools to work with dynamic blocks.
|
|
|
|
The current state supports only reading information from dynamic blocks, it does not
|
|
support the creation of new dynamic blocks nor the modification of them.
|
|
|
|
"""
|
|
from __future__ import annotations
|
|
from typing import TYPE_CHECKING, Optional
|
|
from ezdxf.entities import Insert
|
|
from ezdxf.lldxf import const
|
|
|
|
if TYPE_CHECKING:
|
|
from ezdxf.document import Drawing
|
|
from ezdxf.layouts import BlockLayout
|
|
from ezdxf.entities import BlockRecord
|
|
|
|
AcDbDynamicBlockGUID = "AcDbDynamicBlockGUID"
|
|
AcDbBlockRepBTag = "AcDbBlockRepBTag"
|
|
|
|
|
|
def get_dynamic_block_definition(
|
|
insert: Insert, doc: Optional[Drawing] = None
|
|
) -> Optional[BlockLayout]:
|
|
"""Returns the dynamic block definition if the given block reference is
|
|
referencing a dynamic block direct or indirect via an anonymous block.
|
|
Returns ``None`` otherwise.
|
|
"""
|
|
if doc is None:
|
|
doc = insert.doc
|
|
if doc is None:
|
|
return None
|
|
|
|
block = doc.blocks.get(insert.dxf.name)
|
|
if block is None:
|
|
return None
|
|
|
|
block_record = block.block_record
|
|
if is_dynamic_block_definition(block_record):
|
|
return block # direct dynamic block reference
|
|
|
|
# is indirect dynamic block reference?
|
|
handle = get_dynamic_block_record_handle(block_record)
|
|
if not handle:
|
|
return None # lost reference to dynamic block definition
|
|
dyn_block_record = doc.entitydb.get(handle)
|
|
if dyn_block_record:
|
|
return doc.blocks.get(dyn_block_record.dxf.name)
|
|
return None
|
|
|
|
|
|
def is_dynamic_block_definition(block_record: BlockRecord) -> bool:
|
|
"""Return ``True`` if the given block record is a dynamic block definition."""
|
|
return block_record.has_xdata(AcDbDynamicBlockGUID)
|
|
|
|
|
|
def get_dynamic_block_record_handle(block_record: BlockRecord) -> str:
|
|
"""Returns handle of the dynamic block record for an indirect dynamic block
|
|
reference. Returns an empty string if the block record do not reference a dynamic
|
|
block or the handle was not found.
|
|
|
|
"""
|
|
try: # check for indirect dynamic block reference
|
|
xdata = block_record.get_xdata(AcDbBlockRepBTag)
|
|
except const.DXFValueError:
|
|
return "" # not a dynamic block reference
|
|
# get handle of dynamic block definition
|
|
return xdata.get_first_value(1005, "")
|