2018-05-22 12:51:04 -07:00
/ *
Copyright ( c ) 2018 , Lars Brubaker , John Lewin
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
2018-06-07 17:03:07 -07:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2018-06-14 15:20:39 -07:00
using System.Threading.Tasks ;
2018-05-22 22:06:20 -07:00
using MatterHackers.Agg.UI ;
2018-05-22 12:51:04 -07:00
using MatterHackers.DataConverters3D ;
2018-06-05 11:17:02 -07:00
using MatterHackers.Localizations ;
2018-05-22 12:51:04 -07:00
using MatterHackers.MatterControl.CustomWidgets ;
2018-06-07 17:03:07 -07:00
using MatterHackers.MatterControl.DesignTools.Operations ;
2018-05-22 12:51:04 -07:00
using MatterHackers.MatterControl.Library ;
2018-05-31 20:21:57 -07:00
using MatterHackers.MatterControl.PartPreviewWindow.View3D ;
2018-05-22 12:51:04 -07:00
namespace MatterHackers.MatterControl.PartPreviewWindow
{
public static class Object3DTreeBuilder
{
2018-06-01 08:49:02 -07:00
public static TreeNode BuildTree ( IObject3D rootItem , ThemeConfig theme )
2018-05-22 12:51:04 -07:00
{
2018-06-07 17:03:07 -07:00
return AddTree ( BuildItemView ( rootItem ) , null , theme ) ;
2018-05-22 12:51:04 -07:00
}
2018-06-07 17:03:07 -07:00
private static TreeNode AddTree ( ObjectView item , TreeNode parent , ThemeConfig theme )
2018-05-22 12:51:04 -07:00
{
2018-06-07 17:03:07 -07:00
// Suppress MeshWrapper and OperationSource nodes in tree
bool shouldCollapseToParent = item . Source is MeshWrapper | | item . Source is OperationSource ;
2018-06-19 17:04:04 -07:00
var contextNode = ( shouldCollapseToParent & & parent ! = null ) ? parent : AddItem ( item , parent , theme ) ;
2018-05-22 12:51:04 -07:00
2018-06-07 17:03:07 -07:00
contextNode . SuspendLayout ( ) ;
if ( ! ( item . Source is IVisualLeafNode ) )
2018-05-22 12:51:04 -07:00
{
2018-06-01 08:57:00 -07:00
foreach ( var child in item . Children )
{
2018-06-07 17:03:07 -07:00
AddTree ( BuildItemView ( child ) , contextNode , theme ) ;
2018-06-01 08:57:00 -07:00
}
2018-05-22 12:51:04 -07:00
}
2018-06-01 08:49:02 -07:00
2018-06-07 17:03:07 -07:00
contextNode . ResumeLayout ( ) ;
2018-06-01 08:49:02 -07:00
return contextNode ;
2018-05-22 12:51:04 -07:00
}
2018-06-07 17:03:07 -07:00
private static TreeNode AddItem ( ObjectView item , TreeNode parentNode , ThemeConfig theme )
2018-05-22 12:51:04 -07:00
{
2018-06-07 17:03:07 -07:00
if ( item . Source is InsertionGroup insertionGroup )
2018-06-05 11:17:02 -07:00
{
return new TreeNode ( )
{
Text = "Loading" . Localize ( ) ,
2018-06-07 17:03:07 -07:00
Tag = item . Source ,
2018-06-05 11:17:02 -07:00
TextColor = theme . Colors . PrimaryTextColor ,
PointSize = theme . DefaultFontSize ,
} ;
}
2018-05-22 12:51:04 -07:00
var node = new TreeNode ( )
{
2018-06-07 16:26:58 -07:00
Text = GetName ( item ) ,
2018-06-07 17:03:07 -07:00
Tag = item . Source ,
2018-05-22 12:51:04 -07:00
TextColor = theme . Colors . PrimaryTextColor ,
PointSize = theme . DefaultFontSize ,
} ;
2018-05-22 22:06:20 -07:00
// Check for operation resulting in the given type
2018-06-07 17:03:07 -07:00
if ( ApplicationController . Instance . OperationsByType . TryGetValue ( item . Source . GetType ( ) , out SceneSelectionOperation operation ) )
2018-05-22 22:06:20 -07:00
{
// If exists, use the operation icon
node . Image = operation . Icon ;
}
else
2018-05-22 12:51:04 -07:00
{
2018-05-22 22:06:20 -07:00
node . Load + = ( s , e ) = >
2018-05-22 12:51:04 -07:00
{
2018-06-14 15:20:39 -07:00
ApplicationController . Instance . QueueForGeneration ( ( ) = >
2018-05-22 22:06:20 -07:00
{
2018-06-14 15:20:39 -07:00
// When this widget is dequeued for generation, validate before processing. Off-screen widgets should be skipped and will requeue next time they become visible
if ( node . ActuallyVisibleOnScreen ( )
& & ApplicationController . Instance . Library . ContentProviders . TryGetValue ( "mcx" , out IContentProvider contentProvider )
& & contentProvider is MeshContentProvider meshContentProvider )
{
node . Image = meshContentProvider . GetThumbnail (
item . Source ,
2018-06-19 17:04:04 -07:00
item . Source . MeshRenderId ( ) . ToString ( ) ,
2018-06-14 15:20:39 -07:00
16 ,
16 ,
2018-06-19 17:04:04 -07:00
true ) ;
2018-06-14 15:20:39 -07:00
}
return Task . CompletedTask ;
} ) ;
2018-05-22 12:51:04 -07:00
} ;
2018-05-22 22:06:20 -07:00
}
2018-05-22 12:51:04 -07:00
2018-06-01 08:49:02 -07:00
if ( parentNode ! = null )
{
parentNode . Nodes . Add ( node ) ;
parentNode . Expanded = true ;
}
2018-05-22 12:51:04 -07:00
return node ;
}
2018-06-07 17:03:07 -07:00
private static string GetName ( ObjectView item )
2018-05-22 12:51:04 -07:00
{
2018-06-07 16:26:58 -07:00
return ! string . IsNullOrEmpty ( item . Name ) ? $"{item.Name}" : $"{item.GetType().Name}" ;
2018-05-22 12:51:04 -07:00
}
2018-06-07 17:03:07 -07:00
private static ObjectView BuildItemView ( IObject3D item )
{
switch ( item )
{
case ArrayLinear3D arrayLinear3D :
return new ObjectView ( )
{
Children = item . Children . OfType < OperationSource > ( ) . ToList ( ) ,
Name = $"{arrayLinear3D.Name} ({arrayLinear3D.Count})" ,
Source = item
} ;
2018-06-08 12:15:30 -07:00
// TODO: array operations should only expose OperationSource
2018-06-07 17:03:07 -07:00
case ArrayAdvanced3D arrayAdvanced3D :
return new ObjectView ( )
{
Children = item . Children . Take ( 1 ) ,
Name = $"{arrayAdvanced3D.Name} ({arrayAdvanced3D.Count})" ,
Source = item
} ;
2018-06-08 12:15:30 -07:00
// TODO: array operations should only expose OperationSource
case ArrayRadial3D arrayRadial3D :
return new ObjectView ( )
{
Children = item . Children . Take ( 1 ) ,
Name = $"{arrayRadial3D.Name} ({arrayRadial3D.Count})" ,
Source = item
} ;
2018-06-07 17:03:07 -07:00
default :
return new ObjectView ( item ) ;
}
}
private class ObjectView
{
public ObjectView ( )
{
}
public ObjectView ( IObject3D source )
{
this . Source = source ;
this . Children = this . Source . Children ;
this . Name = this . Source . Name ;
}
public IEnumerable < IObject3D > Children { get ; set ; }
public string Name { get ; set ; }
public IObject3D Source { get ; set ; }
}
2018-05-22 12:51:04 -07:00
}
}