<commit_before>package Slic3r::GUI::PreviewCanvas;
use strict;
use warnings;

use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS);
# must load OpenGL *before* Wx::GLCanvas
use OpenGL qw(:glconstants :glfunctions :glufunctions);
use base qw(Wx::GLCanvas Class::Accessor);
use Math::Trig qw(asin);
use List::Util qw(reduce min max first);
use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan);
use Wx::GLCanvas qw(:all);
 
__PACKAGE__->mk_accessors( qw(quat dirty init mview_init
                              object_bounding_box object_shift
                              volumes initpos
                              sphi stheta
                              cutting_plane_z
                              ) );

use constant TRACKBALLSIZE => 0.8;
use constant TURNTABLE_MODE => 1;
use constant SELECTED_COLOR => [0,1,0,1];
use constant COLORS => [ [1,1,1], [1,0.5,0.5], [0.5,1,0.5], [0.5,0.5,1] ];

# make OpenGL::Array thread-safe
*OpenGL::Array::CLONE_SKIP = sub { 1 };

sub new {
    my ($class, $parent, $object) = @_;
    my $self = $class->SUPER::new($parent);
   
    $self->quat((0, 0, 0, 1));
    $self->sphi(45);
    $self->stheta(-45);

    $self->load_object($object);
    
    EVT_PAINT($self, sub {
        my $dc = Wx::PaintDC->new($self);
        $self->Render($dc);
    });
    EVT_SIZE($self, sub { $self->dirty(1) });
    EVT_IDLE($self, sub {
        return unless $self->dirty;
        return if !$self->IsShownOnScreen;
        $self->Resize( $self->GetSizeWH );
        $self->Refresh;
    });
    EVT_MOUSEWHEEL($self, sub {
        my ($self, $e) = @_;
        
        my $zoom = ($e->GetWheelRotation() / $e->GetWheelDelta() / 10);
        $zoom = $zoom > 0 ?  (1.0 + $zoom) : 1 / (1.0 - $zoom);
        my @pos3d = $self->mouse_to_3d($e->GetX(), $e->GetY());
        $self->ZoomTo($zoom, $pos3d[0], $pos3d[1]);
        
        $self->Refresh;
    });
    EVT_MOUSE_EVENTS($self, sub {
        my ($self, $e) = @_;

        if ($e->Dragging() && $e->LeftIsDown()) {
            $self->handle_rotation($e);
        } elsif ($e->Dragging() && $e->RightIsDown()) {
            $self->handle_translation($e);
        } elsif ($e->LeftUp() || $e->RightUp()) {
            $self->initpos(undef);
        } else {
            $e->Skip();
        }
    });
    
    return $self;
}

sub load_object {
    my ($self, $object) = @_;
    
    my $bb = $object->raw_mesh->bounding_box;
    my $center = $bb->center;
    $self->object_shift(Slic3r::Pointf3->new(-$center->x, -$center->y, -$bb->z_min));  #,,
    $bb->translate(@{ $self->object_shift });
    $self->object_bounding_box($bb);
    
    # group mesh(es) by material
    my @materials = ();
    $self->volumes([]);
    
    # sort volumes: non-modifiers first
    my @volumes = sort { ($a->modifier // 0) <=> ($b->modifier // 0) } @{$object->volumes};
    foreach my $volume (@volumes) {
        my $mesh = $volume->mesh->clone;
        $mesh->translate(@{ $self->object_shift });  
        
        my $material_id = $volume->material_id // '_';
        my $color_idx = first { $materials[$_] eq $material_id } 0..$#materials;
        if (!defined $color_idx) {
            push @materials, $material_id;
            $color_idx = $#materials;
        }
        
        my $color = [ @{COLORS->[ $color_idx % scalar(@{&COLORS}) ]} ];
        push @$color, $volume->modifier ? 0.5 : 1;
        push @{$self->volumes}, my $v = {<commit_msg>Apply transform to meshes before displaying the 3D preview canvas<commit_after>package Slic3r::GUI::PreviewCanvas;
use strict;
use warnings;

use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS);
# must load OpenGL *before* Wx::GLCanvas
use OpenGL qw(:glconstants :glfunctions :glufunctions);
use base qw(Wx::GLCanvas Class::Accessor);
use Math::Trig qw(asin);
use List::Util qw(reduce min max first);
use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan);
use Wx::GLCanvas qw(:all);
 
__PACKAGE__->mk_accessors( qw(quat dirty init mview_init
                              object_bounding_box object_shift
                              volumes initpos
                              sphi stheta
                              cutting_plane_z
                              ) );

use constant TRACKBALLSIZE => 0.8;
use constant TURNTABLE_MODE => 1;
use constant SELECTED_COLOR => [0,1,0,1];
use constant COLORS => [ [1,1,1], [1,0.5,0.5], [0.5,1,0.5], [0.5,0.5,1] ];

# make OpenGL::Array thread-safe
*OpenGL::Array::CLONE_SKIP = sub { 1 };

sub new {
    my ($class, $parent, $object) = @_;
    my $self = $class->SUPER::new($parent);
   
    $self->quat((0, 0, 0, 1));
    $self->sphi(45);
    $self->stheta(-45);

    $self->load_object($object);
    
    EVT_PAINT($self, sub {
        my $dc = Wx::PaintDC->new($self);
        $self->Render($dc);
    });
    EVT_SIZE($self, sub { $self->dirty(1) });
    EVT_IDLE($self, sub {
        return unless $self->dirty;
        return if !$self->IsShownOnScreen;
        $self->Resize( $self->GetSizeWH );
        $self->Refresh;
    });
    EVT_MOUSEWHEEL($self, sub {
        my ($self, $e) = @_;
        
        my $zoom = ($e->GetWheelRotation() / $e->GetWheelDelta() / 10);
        $zoom = $zoom > 0 ?  (1.0 + $zoom) : 1 / (1.0 - $zoom);
        my @pos3d = $self->mouse_to_3d($e->GetX(), $e->GetY());
        $self->ZoomTo($zoom, $pos3d[0], $pos3d[1]);
        
        $self->Refresh;
    });
    EVT_MOUSE_EVENTS($self, sub {
        my ($self, $e) = @_;

        if ($e->Dragging() && $e->LeftIsDown()) {
            $self->handle_rotation($e);
        } elsif ($e->Dragging() && $e->RightIsDown()) {
            $self->handle_translation($e);
        } elsif ($e->LeftUp() || $e->RightUp()) {
            $self->initpos(undef);
        } else {
            $e->Skip();
        }
    });
    
    return $self;
}

sub load_object {
    my ($self, $object) = @_;
    
    my $bb = $object->instance_bounding_box;
    my $center = $bb->center;
    $self->object_shift(Slic3r::Pointf3->new(-$center->x, -$center->y, -$bb->z_min));  #,,
    $bb->translate(@{ $self->object_shift });
    $self->object_bounding_box($bb);
    
    # group mesh(es) by material
    my @materials = ();
    $self->volumes([]);
    
    # sort volumes: non-modifiers first
    my @volumes = sort { ($a->modifier // 0) <=> ($b->modifier // 0) } @{$object->volumes};
    foreach my $volume (@volumes) {
        my $mesh = $volume->mesh->clone;
        $object->instances->[0]->transform_mesh($mesh);
        $mesh->translate(@{ $self->object_shift });  
        
        my $material_id = $volume->material_id // '_';
        my $color_idx = first { $materials[$_] eq $material_id } 0..$#materials;
        if (!defined $color_idx) {
            push @materials, $material_id;
            $color_idx = $#materials;
        }
        
        my $color = [ @{COLORS->[ $color_idx % scalar(@{&COLORS}) ]} ];
        push @$color, $volume->modifier ? 0.5 : 1;
        push @{$self->volumes}, my $v = {
{'fraction_non_alphanumeric': 0.18270453582026283, 'fraction_numerical': 0.017238943054966795, 'mean_word_length': 2.3339613754121524, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 125, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3844186', 'n_tokens_mistral': 2583, 'n_tokens_neox': 2536, 'n_words': 506}