Reset Blockscalefactor to Zero but stay at new size

Hi,
i have scaled my roof by 17.592 because of new Data, i would like to reset the Scale Factor to Zero (0,0) but stay at the current size is there a Pythonscript ore similiar to change this :slight_smile:

Usually the Scalefactor is not that important but in this case we need it to be 0,0,0

shouldn’t it be “reset to 1.0” ?
1.0,1.0,1.0
???

by guess - the block base point does not have a nice position / relation to the geometry.

please post a simple file, that shows what you are after.
Maybe just post one or two instances of “Dach Joch Rand”
Best:
current set up on one layer
desired transformation result on the next layer

kind regards - tom

As Tom alludes to if you can post a more complete example we can get a clearer picture of the additional variables that need to be considered.

The logic in python would be somewhat similar.


R8-makenewblock-from-scaledBlock.gh (9.0 KB)
R8-makenewblock-from-scaledBlock.3dm (51.2 KB)

So here is the detached Test File Test Block scale.3dm (1.4 MB) i would like to have all the Scaled Blockes to be not Scaled so that when i use the Command
_BlockResetScale
They should stay the same size.

If it would be so complex i could do it by hand but that would take ages in that case :frowning:
PS: i did now how to do it right so the green Objects should stay individual Blocks, in this file they are combined in one Block with scalefactor 1

A script where the scalefactor can be overwritten would be perfect

@Japhy @Tom_P

Filtering by layer (to not get the text or example scaled factor 1 block.

In the past I needed the same functionality but was not able to get it to work.

But because I have a new faible to script and iterate with gemini, I tried again and voilĂ  30mins later it works. Let me know if it works on your end as well, if not feel free to iterate further via AI - I think right now we are going into a crazy new era to be able to create all those functionalities without the need of deep programming skills.

the scripts works on block and nested blocks, you can chose to change the block directly and affect all instances of it or to make a unique block.

best regards,

sebowim

# -*- coding: utf-8 -*-
"""
Script: Block Scale Resetter (Deep Fix)
Description: 
    Resets the scale factor of a Block Instance to (1,1,1) while keeping its 
    visual size and proportions exactly the same.
    
    Features:
    - Works on nested blocks (blocks inside blocks).
    - Prevents "double scaling" distortion in nested hierarchies.
    - Option A: Global Update (Changes the definition, affects all copies).
    - Option B: Deep Unique Fix (Creates a completely isolated copy of the 
      block hierarchy before fixing, preserving the original blocks).

Usage:
    Run the script, select a scaled block instance, and choose the mode.
"""

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc
import math

# ==============================================================================
# HELPER FUNCTIONS
# ==============================================================================

def GetScaleFromXform(xform):
    """ Extracts the scale vector (lengths of basis vectors) from a transformation matrix. """
    vx = Rhino.Geometry.Vector3d(xform.M00, xform.M10, xform.M20)
    vy = Rhino.Geometry.Vector3d(xform.M01, xform.M11, xform.M21)
    vz = Rhino.Geometry.Vector3d(xform.M02, xform.M12, xform.M22)
    return [vx.Length, vy.Length, vz.Length]

def FindDefById(guid):
    """ Finds an InstanceDefinition by ID safely across different Rhino versions. """
    if hasattr(sc.doc.InstanceDefinitions, "FindId"):
        return sc.doc.InstanceDefinitions.FindId(guid)
    # Fallback for older versions
    for idef in sc.doc.InstanceDefinitions:
        if idef.Id == guid: return idef
    return None

def GetUniqueName(base_name):
    """ Generates a unique name for the new block definition (e.g., Name_Fixed_01). """
    # Prevent stacking suffixes like Name_Fixed_Fixed
    if "_Fixed" in base_name:
        base_name = base_name.split("_Fixed")[0]
        
    suffix = "_Fixed"
    new_name = base_name + suffix
    
    # Check if name exists, if so, append number
    if not sc.doc.InstanceDefinitions.Find(new_name):
        return new_name
    
    i = 1
    while True:
        test_name = "{}_{:02d}".format(new_name, i)
        if not sc.doc.InstanceDefinitions.Find(test_name):
            return test_name
        i += 1

# ==============================================================================
# PHASE 1: DEEP COPY / MAKE UNIQUE HIERARCHY
# ==============================================================================

def DuplicateDefinitionRecursive(idef, created_map):
    """
    Recursively duplicates a block definition and ALL its nested block definitions.
    
    Args:
        idef: The InstanceDefinition to copy.
        created_map: A dictionary {Old_ID: New_Def_Object} to track already copied 
                     definitions (handles shared blocks correctly).
                     
    Returns: 
        The NEW InstanceDefinition object.
    """
    # 1. Check if we already duplicated this specific definition in this session
    if idef.Id in created_map:
        return created_map[idef.Id]

    # 2. Create a new unique name
    new_name = GetUniqueName(idef.Name)
    print("  > Duplicating Definition: {} -> {}".format(idef.Name, new_name))

    # 3. Process and duplicate all objects inside the block
    new_objs = []
    new_attrs = []
    
    existing_objects = idef.GetObjects()
    
    for obj in existing_objects:
        # Duplicate geometry and attributes
        dup_geo = obj.Geometry.Duplicate()
        dup_attr = obj.Attributes.Duplicate()
        
        # --- HANDLE NESTED BLOCKS ---
        if isinstance(dup_geo, Rhino.Geometry.InstanceReferenceGeometry):
            old_child_id = dup_geo.ParentIdefId
            old_child_def = FindDefById(old_child_id)
            
            if old_child_def:
                # RECURSION: Duplicate the child definition hierarchy too!
                new_child_def = DuplicateDefinitionRecursive(old_child_def, created_map)
                
                # Create a new instance geometry pointing to the NEW child definition
                # but preserving the original position/rotation/scale of the instance.
                new_iref = Rhino.Geometry.InstanceReferenceGeometry(new_child_def.Id, dup_geo.Xform)
                dup_geo = new_iref
        
        new_objs.append(dup_geo)
        new_attrs.append(dup_attr)

    # 4. Add the new definition to the Rhino document
    # Block definitions are always defined around World Origin (0,0,0)
    new_idef_index = sc.doc.InstanceDefinitions.Add(new_name, idef.Description, Rhino.Geometry.Point3d.Origin, new_objs, new_attrs)
    
    if new_idef_index < 0:
        print("Error creating definition: " + new_name)
        return None

    new_idef = sc.doc.InstanceDefinitions[new_idef_index]
    
    # 5. Store in map and return
    created_map[idef.Id] = new_idef
    return new_idef

def MakeBlockTreeUniqueAndSwap(instance_guid):
    """ 
    Entry point for Phase 1.
    Duplicates the entire nested hierarchy of the selected block and 
    swaps the selected instance to use the new "root" definition.
    """
    rhino_obj = sc.doc.Objects.Find(instance_guid)
    if not rhino_obj: return None, None
    
    # Try getting the definition (compatible with different RhinoCommon versions)
    try:
        old_idef = rhino_obj.InstanceDefinition
    except:
        old_idef = sc.doc.InstanceDefinitions.FindId(rhino_obj.InstanceDefinitionId)
        
    if not old_idef: return None, None

    # Map to track created definitions (Deep Copy Memory)
    created_map = {}
    
    # Start Recursion
    new_main_idef = DuplicateDefinitionRecursive(old_idef, created_map)
    
    if not new_main_idef: return None, None
    
    # --- SWAP INSTANCE IN DOCUMENT ---
    old_xform = rhino_obj.InstanceXform
    old_attrs = rhino_obj.Attributes.Duplicate()
    
    # Add new instance pointing to the new definition
    new_guid = sc.doc.Objects.AddInstanceObject(new_main_idef.Index, old_xform, old_attrs)
    
    # Delete the old instance
    sc.doc.Objects.Delete(instance_guid, True)
    
    # Select the new instance so the script continues smoothly
    rs.SelectObject(new_guid)
    
    return new_guid, new_main_idef.Name

# ==============================================================================
# PHASE 2: SCALE FIXING (The "Bake" Logic)
# ==============================================================================

def ResetInstanceScaleInPlace(geometry, current_scale):
    """ 
    Critical Helper:
    Takes a nested block instance (geometry) that has been scaled up by the parent process,
    and resets its local scale factor to 1.0 (inverse scaling).
    This prevents the "double scaling" effect where nested blocks explode in size.
    """
    sx, sy, sz = current_scale
    
    # Extract insertion point from matrix
    xform = geometry.Xform
    insert_pt = Rhino.Geometry.Point3d(xform.M03, xform.M13, xform.M23)
    
    # Create pivot plane for scaling
    plane = Rhino.Geometry.Plane.WorldXY
    plane.Origin = insert_pt
    
    # Apply inverse scale (shrinking the container to neutralize parent growth)
    inv_scale = Rhino.Geometry.Transform.Scale(plane, 1.0/sx, 1.0/sy, 1.0/sz)
    geometry.Transform(inv_scale)

def RecursiveBake(block_name, scale_vector, visited_ids):
    """ 
    Recursively bakes the scale factor into the geometry of the block definition.
    
    Logic:
    1. Scale all geometry inside the definition UP.
    2. If a nested block is found:
       - Reset its instance scale DOWN (to keep it visual size).
       - Recursively dive into its definition to fix its internal geometry.
    """
    psx, psy, psz = scale_vector
    
    idef = sc.doc.InstanceDefinitions.Find(block_name)
    if not idef: return False

    # Transformation matrix to scale everything UP
    global_scale = Rhino.Geometry.Transform.Scale(Rhino.Geometry.Plane.WorldXY, psx, psy, psz)

    new_objs = []
    new_attrs = []
    
    existing = idef.GetObjects()
    
    for obj in existing:
        dup_geo = obj.Geometry.Duplicate()
        dup_attr = obj.Attributes.Duplicate()
        
        # A. Transform geometry (Move to new position, scale up size)
        dup_geo.Transform(global_scale)
        
        # B. Handle Nested Blocks (Special Logic)
        if isinstance(dup_geo, Rhino.Geometry.InstanceReferenceGeometry):
            # 1. Neutralize the scale on the instance container
            ResetInstanceScaleInPlace(dup_geo, [psx, psy, psz])
            
            # 2. Recursively fix the definition of this nested block
            child_id = dup_geo.ParentIdefId
            if child_id not in visited_ids:
                visited_ids.add(child_id)
                child_def = FindDefById(child_id)
                if child_def:
                    print("  > Fixing Scale in Nested Definition: {}".format(child_def.Name))
                    RecursiveBake(child_def.Name, [psx, psy, psz], visited_ids)
        
        new_objs.append(dup_geo)
        new_attrs.append(dup_attr)
        
    # Update the definition with the modified geometry
    sc.doc.InstanceDefinitions.ModifyGeometry(idef.Index, new_objs, new_attrs)

def ResetMainInstance(guid, scale):
    """ 
    Resets the scale of the selected main instance in the Rhino document to (1,1,1).
    This completes the process: Definition is big, Instance is small = Visual match.
    """
    obj = sc.doc.Objects.Find(guid)
    if not obj: return
    
    sx, sy, sz = scale
    xform = obj.InstanceXform
    pt = Rhino.Geometry.Point3d(xform.M03, xform.M13, xform.M23)
    
    plane = Rhino.Geometry.Plane.WorldXY
    plane.Origin = pt
    
    # Scale down
    shrink = Rhino.Geometry.Transform.Scale(plane, 1.0/sx, 1.0/sy, 1.0/sz)
    sc.doc.Objects.Transform(guid, shrink, True)

# ==============================================================================
# MAIN Execution
# ==============================================================================

def Main():
    # 1. Select Block
    guid = rs.GetObject("Select the SCALED Block Instance", rs.filter.instance)
    if not guid: return
    
    # 2. Get current Scale
    obj = sc.doc.Objects.Find(guid)
    s = GetScaleFromXform(obj.InstanceXform)
    sx, sy, sz = s
    
    # Tolerance check: Is it already 1.0?
    if abs(sx-1)<1e-4 and abs(sy-1)<1e-4 and abs(sz-1)<1e-4:
        print("Block is already at scale 1. No changes needed.")
        return

    # 3. ASK USER FOR MODE
    items = ["Global Update (Affects ALL copies)", "Make Unique & Fix (Deep Copy / Safe Mode)"]
    result = rs.ListBox(items, "Choose how to apply the fix:", "Block Scale Resetter")
    
    if not result: return 

    rs.EnableRedraw(False)
    try:
        block_name = rs.BlockInstanceName(guid)
        
        # --- PHASE 1: PREPARATION (Deep Copy) ---
        if result == items[1]:
            print("--- PHASE 1: Creating Deep Unique Hierarchy ---")
            new_guid, new_name = MakeBlockTreeUniqueAndSwap(guid)
            if new_guid:
                guid = new_guid
                block_name = new_name
                # Re-fetch scale just in case (to ensure object validity)
                obj = sc.doc.Objects.Find(guid)
                s = GetScaleFromXform(obj.InstanceXform)
            else:
                print("Error creating unique hierarchy. Aborting.")
                return

        # --- PHASE 2: EXECUTION (Scale Fix) ---
        print("--- PHASE 2: Fixing Proportions ({}) ---".format(block_name))
        
        visited = set()
        RecursiveBake(block_name, s, visited)
        
        ResetMainInstance(guid, s)
        
        print("--- SUCCESS: Block scale reset to 1. ---")
        
    except Exception as e:
        print("ERROR occurred: {}".format(e))
        import traceback
        traceback.print_exc()
        
    finally:
        rs.EnableRedraw(True)

if __name__=="__main__":
    Main()

nearly at tthe goal, currently it just works for one Block

is it possible to do it for multiple?

@Sebastian_Wimmer

Mode 2 is working but if it would be possible to make mode one also working would be fantastic

sure thing - I really encourage you to try iterating or creating on your own (get gemini first) - this change took me 3 prompts, and I added preselection so you can select everything before the script starts. I think it would be so great, when the community now creates all sorts of great creative scripts that really ease the work and exchange those scripts and thus collaborate

# -*- coding: utf-8 -*-
"""
Script: Multi-Block Scale Resetter (Smart Selection)
Description: 
    Batch processes multiple Block Instances to reset their scale factors to (1,1,1) 
    while preserving visual size. Handles nested blocks and deep hierarchies.

    Features:
    - Smart Selection: Detects pre-selected blocks automatically.
    - Global Update: Fixes shared definitions (once per definition).
    - Unique Fix: Deep copies hierarchies to isolate specific blocks.

Usage:
    Select blocks (optional) -> Run Script -> Choose Mode.
"""

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc
import math

# ==============================================================================
# HELPER FUNCTIONS
# ==============================================================================

def GetScaleFromXform(xform):
    """ Extracts scale vector (lengths of basis vectors) from transformation matrix. """
    vx = Rhino.Geometry.Vector3d(xform.M00, xform.M10, xform.M20)
    vy = Rhino.Geometry.Vector3d(xform.M01, xform.M11, xform.M21)
    vz = Rhino.Geometry.Vector3d(xform.M02, xform.M12, xform.M22)
    return [vx.Length, vy.Length, vz.Length]

def FindDefById(guid):
    """ Finds InstanceDefinition by ID safely. """
    if hasattr(sc.doc.InstanceDefinitions, "FindId"):
        return sc.doc.InstanceDefinitions.FindId(guid)
    for idef in sc.doc.InstanceDefinitions:
        if idef.Id == guid: return idef
    return None

def GetUniqueName(base_name):
    """ Generates a unique name (e.g., Name_Fixed_01). """
    if "_Fixed" in base_name:
        base_name = base_name.split("_Fixed")[0]
        
    suffix = "_Fixed"
    new_name = base_name + suffix
    
    if not sc.doc.InstanceDefinitions.Find(new_name):
        return new_name
    
    i = 1
    while True:
        test_name = "{}_{:02d}".format(new_name, i)
        if not sc.doc.InstanceDefinitions.Find(test_name):
            return test_name
        i += 1

# ==============================================================================
# PHASE 1: DEEP COPY / MAKE UNIQUE HIERARCHY
# ==============================================================================

def DuplicateDefinitionRecursive(idef, created_map):
    """
    Recursively duplicates a block definition and its nested blocks.
    created_map tracks copies to handle shared nested blocks correctly.
    """
    if idef.Id in created_map:
        return created_map[idef.Id]

    new_name = GetUniqueName(idef.Name)

    new_objs = []
    new_attrs = []
    
    existing_objects = idef.GetObjects()
    
    for obj in existing_objects:
        dup_geo = obj.Geometry.Duplicate()
        dup_attr = obj.Attributes.Duplicate()
        
        if isinstance(dup_geo, Rhino.Geometry.InstanceReferenceGeometry):
            old_child_id = dup_geo.ParentIdefId
            old_child_def = FindDefById(old_child_id)
            
            if old_child_def:
                # Recursion
                new_child_def = DuplicateDefinitionRecursive(old_child_def, created_map)
                new_iref = Rhino.Geometry.InstanceReferenceGeometry(new_child_def.Id, dup_geo.Xform)
                dup_geo = new_iref
        
        new_objs.append(dup_geo)
        new_attrs.append(dup_attr)

    new_idef_index = sc.doc.InstanceDefinitions.Add(new_name, idef.Description, Rhino.Geometry.Point3d.Origin, new_objs, new_attrs)
    
    if new_idef_index < 0:
        print("Error creating definition: " + new_name)
        return None

    new_idef = sc.doc.InstanceDefinitions[new_idef_index]
    created_map[idef.Id] = new_idef
    return new_idef

def MakeBlockTreeUniqueAndSwap(instance_guid):
    """ 
    Deep copies the hierarchy for the specific instance and swaps it in the doc.
    """
    rhino_obj = sc.doc.Objects.Find(instance_guid)
    if not rhino_obj: return None, None
    
    try:
        old_idef = rhino_obj.InstanceDefinition
    except:
        old_idef = sc.doc.InstanceDefinitions.FindId(rhino_obj.InstanceDefinitionId)
        
    if not old_idef: return None, None

    created_map = {}
    new_main_idef = DuplicateDefinitionRecursive(old_idef, created_map)
    
    if not new_main_idef: return None, None
    
    # Swap Instance
    old_xform = rhino_obj.InstanceXform
    old_attrs = rhino_obj.Attributes.Duplicate()
    
    new_guid = sc.doc.Objects.AddInstanceObject(new_main_idef.Index, old_xform, old_attrs)
    sc.doc.Objects.Delete(instance_guid, True)
    
    return new_guid, new_main_idef.Name

# ==============================================================================
# PHASE 2: SCALE FIXING
# ==============================================================================

def ResetInstanceScaleInPlace(geometry, current_scale):
    """ Resets scale of a nested instance geometry locally to prevent double scaling. """
    sx, sy, sz = current_scale
    xform = geometry.Xform
    insert_pt = Rhino.Geometry.Point3d(xform.M03, xform.M13, xform.M23)
    plane = Rhino.Geometry.Plane.WorldXY
    plane.Origin = insert_pt
    inv_scale = Rhino.Geometry.Transform.Scale(plane, 1.0/sx, 1.0/sy, 1.0/sz)
    geometry.Transform(inv_scale)

def RecursiveBake(block_name, scale_vector, visited_ids):
    """ Bakes scale into definition geometry recursively. """
    psx, psy, psz = scale_vector
    
    idef = sc.doc.InstanceDefinitions.Find(block_name)
    if not idef: return False

    global_scale = Rhino.Geometry.Transform.Scale(Rhino.Geometry.Plane.WorldXY, psx, psy, psz)

    new_objs = []
    new_attrs = []
    existing = idef.GetObjects()
    
    for obj in existing:
        dup_geo = obj.Geometry.Duplicate()
        dup_attr = obj.Attributes.Duplicate()
        
        dup_geo.Transform(global_scale)
        
        if isinstance(dup_geo, Rhino.Geometry.InstanceReferenceGeometry):
            # Fix nested instance scale
            ResetInstanceScaleInPlace(dup_geo, [psx, psy, psz])
            
            child_id = dup_geo.ParentIdefId
            if child_id not in visited_ids:
                visited_ids.add(child_id)
                child_def = FindDefById(child_id)
                if child_def:
                    RecursiveBake(child_def.Name, [psx, psy, psz], visited_ids)
        
        new_objs.append(dup_geo)
        new_attrs.append(dup_attr)
        
    sc.doc.InstanceDefinitions.ModifyGeometry(idef.Index, new_objs, new_attrs)

def ResetMainInstance(guid, scale):
    """ Resets the selected instance scale to 1 in the document. """
    obj = sc.doc.Objects.Find(guid)
    if not obj: return
    
    sx, sy, sz = scale
    xform = obj.InstanceXform
    pt = Rhino.Geometry.Point3d(xform.M03, xform.M13, xform.M23)
    
    plane = Rhino.Geometry.Plane.WorldXY
    plane.Origin = pt
    
    shrink = Rhino.Geometry.Transform.Scale(plane, 1.0/sx, 1.0/sy, 1.0/sz)
    sc.doc.Objects.Transform(guid, shrink, True)

# ==============================================================================
# MAIN
# ==============================================================================

def Main():
    guids = []
    
    # 1. CHECK FOR PRE-SELECTION
    # Get all currently selected objects
    pre_selected = rs.SelectedObjects()
    valid_pre_selected = []
    
    if pre_selected:
        for obj in pre_selected:
            if rs.IsBlockInstance(obj):
                valid_pre_selected.append(obj)
    
    use_pre_selection = False
    
    # If valid blocks are selected, ask user
    if valid_pre_selected:
        msg = "Found {} selected Block Instance(s).\nDo you want to use these?".format(len(valid_pre_selected))
        # MessageBox buttons: 4 = Yes/No. Icon: 32 = Question.
        # Result: 6 = Yes, 7 = No.
        result = rs.MessageBox(msg, 4 | 32, "Pre-Selection Detected")
        
        if result == 6: # YES
            guids = valid_pre_selected
            use_pre_selection = True
        else: # NO
            rs.UnselectAllObjects()
    
    # 2. MANUAL SELECTION (If no pre-selection used)
    if not use_pre_selection:
        guids = rs.GetObjects("Select Block Instances to Reset", rs.filter.instance)
    
    if not guids: return
    
    # 3. ASK USER MODE
    items = ["Global Update (Affects shared definitions)", "Make Unique & Fix (Deep Copy each)"]
    result = rs.ListBox(items, "Choose fix mode for {} selected blocks:".format(len(guids)), "Multi-Block Reset")
    if not result: return 
    
    is_unique_mode = (result == items[1])
    
    rs.EnableRedraw(False)
    
    # Track modified definitions to avoid double-scaling in Global Mode
    global_modified_defs = set()
    
    try:
        print("--- Starting Batch Process ---")
        
        for i, guid in enumerate(guids):
            # Progress feedback
            rs.Prompt("Processing block {}/{}...".format(i+1, len(guids)))
            
            obj = sc.doc.Objects.Find(guid)
            if not obj: continue
            
            # Get current scale
            s = GetScaleFromXform(obj.InstanceXform)
            sx, sy, sz = s
            
            # Skip if already 1.0 (approx)
            if abs(sx-1)<1e-4 and abs(sy-1)<1e-4 and abs(sz-1)<1e-4:
                continue

            block_name = rs.BlockInstanceName(guid)
            
            # --- PATH A: UNIQUE MODE ---
            if is_unique_mode:
                # Deep copy hierarchy first
                new_guid, new_name = MakeBlockTreeUniqueAndSwap(guid)
                if new_guid:
                    visited = set()
                    RecursiveBake(new_name, s, visited)
                    ResetMainInstance(new_guid, s)
            
            # --- PATH B: GLOBAL UPDATE ---
            else:
                if block_name in global_modified_defs:
                    # Just reset this instance, definition already fixed
                    ResetMainInstance(guid, s)
                else:
                    visited = set()
                    RecursiveBake(block_name, s, visited)
                    ResetMainInstance(guid, s)
                    global_modified_defs.add(block_name)

        print("--- SUCCESS: Processed {} blocks. ---".format(len(guids)))
        
    except Exception as e:
        print("ERROR: {}".format(e))
        import traceback
        traceback.print_exc()
        
    finally:
        rs.EnableRedraw(True)

if __name__=="__main__":
    Main()

Yes i know but to have good prompts i would need much deeper understanding i am a beginner :slight_smile:
The New Prompt works but it scaled the Block ( in that case on about x17.59, now the Prompt needed to be adapet so that the object doesnt went so big :slight_smile:

Is there something like rescaling?

haha I am no prompt engineer as well - you just type what functionality you want - insert the script into the pythoneditor and backfeed all the errors or wrong functionalities, in addition I like to make screenshots of states of the model and describe what went wrong or what works - all with natural language.

ofc I was not able to test heavier more complex files, thats where the collab. and further iteration between rhino users should start (bc. the generation and iteration is such a straight forward process imho) - if you can post the model, I could have a look tomorrow (it’s 23:50 in austria and I need some bedtime) but I won’t be able to invest a lot of time. Again, you should really try iterating it on your own - If you have questions on the process, I am happy to explain those simple steps further.

best regards,

sebowim

well i am in Austria too :joy:

But yes maybe someone can help here

haha, funny coincident. would you be able to provide your rhino-file? (at best; not bloated, just the files for editing) if you do not want to post, you could also DM me. Without the file I can not iterate the script anyway - because the whole process works on descriptive feedback.

Here is the Testfile,

Test Block scale (1).3dm (2.9 MB)

the First stayes in corrcet size all Block “Copies” Scale themself about x17.59

hi, I can not seem to reproduce the problem?

Ah you go inside the block an reset, sorry that was my fault :slight_smile:

so is it possible to create a button from this script so that i dont havet make Runpythonscript each time (implement it in Rhino, so that when i change the device i can have it there too)

hmm no I don‘t go into the block and reset: I just showed you that in the beginning there is a block-scaling and after that there is not (it might look different ob your end bc. I use the plugin „blockeditnew“) → I just openend your file and ran the script.

you can assign that to a button - there should be enough ressources on this forum / youtube / internet to get you started - personally I like zo create an alias to invoke the script bc. I do not want the 1001 buttons that bloats my UI