diff options
43 files changed, 3272 insertions, 14238 deletions
diff --git a/projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj b/projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj index 3664ed4fe4c..bf534d94fd9 100644 --- a/projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj +++ b/projectfiles_vc9/BL_bmesh/BL_bmesh.vcproj @@ -1,336 +1,344 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="9.00" - Name="BL_bmesh" - ProjectGUID="{6A51010A-9393-4D77-84B4-5BBCDA6E7C25}" - RootNamespace="BL_bmesh" - TargetFrameworkVersion="196613" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory="$(SolutionDir)$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="2" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\editors\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\source\blender\blenkernel;..\..\source\blender\makesdna;..\..\source\blender\blenlib;..\..\source\blender\bmesh;..\..\source\blender\editors\include;..\..\source\blender\bmesh\operators;..\..\source\blender\bmesh\intern;..\..\source\blender\editors\mesh" - MinimalRebuild="true" - BasicRuntimeChecks="3" - RuntimeLibrary="1" - WarningLevel="3" - DebugInformationFormat="4" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - OutputFile="..\..\..\build\msvc_9\libs\debug\BL_bmesh.lib" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory="$(SolutionDir)$(ConfigurationName)" - IntermediateDirectory="$(ConfigurationName)" - ConfigurationType="4" - CharacterSet="2" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\editors\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\source\blender\blenkernel;..\..\source\blender\makesdna;..\..\source\blender\blenlib;..\..\source\blender\bmesh;..\..\source\blender\editors\include;..\..\source\blender\bmesh\operators;..\..\source\blender\bmesh\intern;..\..\source\blender\editors\mesh" - RuntimeLibrary="0" - EnableFunctionLevelLinking="true" - WarningLevel="3" - DebugInformationFormat="3" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - OutputFile="..\..\..\build\msvc_9\libs\BL_bmesh.lib" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - <ProjectReference - ReferencedProjectIdentifier="{31628053-825D-4C06-8A21-D13883489718}" - RelativePathToProject=".\blenlib\BLI_blenlib.vcproj" - /> - <ProjectReference - ReferencedProjectIdentifier="{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}" - RelativePathToProject=".\blenkernel\BKE_blenkernel.vcproj" - /> - <ProjectReference - ReferencedProjectIdentifier="{E013786A-9575-4F34-81B2-33290357EE87}" - RelativePathToProject=".\makesdna\DNA_makesdna.vcproj" - /> - <ProjectReference - ReferencedProjectIdentifier="{1CC733F1-6AB5-4904-8F63-C08C46B79DD9}" - RelativePathToProject="..\..\intern\guardedalloc\make\msvc_9_0\guardedalloc.vcproj" - /> - </References> - <Files> - <Filter - Name="Source Files" - Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" - UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" - > - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_construct.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\bmesh_dupeops.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_eulers.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_filters.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_interp.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_iterators.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_marking.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_mesh.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_mods.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_opdefines.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_operators.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_operators_private.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_polygon.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_private.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_queries.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_structure.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_structure.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_to_editmesh.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\bmesh_walkers.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\connectops.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\createops.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\dissolveops.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\edgesplitop.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\intern\editmesh_to_bmesh.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\extrudeops.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\mesh_conv.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\mirror.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\removedoubles.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\subdivideop.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\triangulateop.c" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\operators\utils.c" - > - </File> - </Filter> - <Filter - Name="Header Files" - Filter="h;hpp;hxx;hm;inl;inc;xsd" - UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" - > - <File - RelativePath="..\..\source\blender\bmesh\bmesh.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_error.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_filters.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_iterators.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_marking.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_operator_api.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_operators.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_queries.h" - > - </File> - <File - RelativePath="..\..\source\blender\bmesh\bmesh_walkers.h" - > - </File> - </Filter> - </Files> - <Globals> - </Globals> -</VisualStudioProject> +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="BL_bmesh"
+ ProjectGUID="{6A51010A-9393-4D77-84B4-5BBCDA6E7C25}"
+ RootNamespace="BL_bmesh"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\editors\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\source\blender\blenkernel;..\..\source\blender\makesdna;..\..\source\blender\blenlib;..\..\source\blender\bmesh;..\..\source\blender\editors\include;..\..\source\blender\bmesh\operators;..\..\source\blender\bmesh\intern;..\..\source\blender\editors\mesh"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\build\msvc_9\libs\debug\BL_bmesh.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories="..\..\..\..\lib\windows\pthreads\include;..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_9\intern\bmfont\include;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\editors\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\makesrna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_9\extern\verse\include;..\..\..\..\build\msvc_9\intern\opennl\include;..\..\..\..\build\msvc_9\extern\bullet\include;..\..\..\..\build\msvc_9\extern\glew\include;..\..\..\source\blender\gpu;..\..\source\blender\blenkernel;..\..\source\blender\makesdna;..\..\source\blender\blenlib;..\..\source\blender\bmesh;..\..\source\blender\editors\include;..\..\source\blender\bmesh\operators;..\..\source\blender\bmesh\intern;..\..\source\blender\editors\mesh"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="..\..\..\build\msvc_9\libs\BL_bmesh.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ <ProjectReference
+ ReferencedProjectIdentifier="{31628053-825D-4C06-8A21-D13883489718}"
+ RelativePathToProject=".\blenlib\BLI_blenlib.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{CAE37E91-6570-43AC-A4B4-7A37A4B0FC94}"
+ RelativePathToProject=".\blenkernel\BKE_blenkernel.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{E013786A-9575-4F34-81B2-33290357EE87}"
+ RelativePathToProject=".\makesdna\DNA_makesdna.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{1CC733F1-6AB5-4904-8F63-C08C46B79DD9}"
+ RelativePathToProject="..\..\intern\guardedalloc\make\msvc_9_0\guardedalloc.vcproj"
+ />
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_construct.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\bmesh_dupeops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_eulers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_filters.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_interp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_iterators.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_marking.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_mesh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_mods.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_opdefines.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_operators.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_operators_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_polygon.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_private.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_queries.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_structure.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_structure.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_to_editmesh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\bmesh_walkers.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\connectops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\createops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\dissolveops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\edgesplitop.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\intern\editmesh_to_bmesh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\extrudeops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\join_triangles.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\mesh_conv.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\mirror.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\primitiveops.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\removedoubles.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\subdivideop.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\triangulateop.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\operators\utils.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_error.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_filters.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_iterators.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_marking.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_operator_api.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_operators.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_queries.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\source\blender\bmesh\bmesh_walkers.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/projectfiles_vc9/blender/editors/ED_editors.vcproj b/projectfiles_vc9/blender/editors/ED_editors.vcproj index 9a78c04b450..9cafa103dda 100644 --- a/projectfiles_vc9/blender/editors/ED_editors.vcproj +++ b/projectfiles_vc9/blender/editors/ED_editors.vcproj @@ -1200,39 +1200,19 @@ >
</File>
<File
- RelativePath="..\..\..\source\blender\editors\mesh\editbmesh_bvh.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\mesh\editbmesh_bvh.h"
+ RelativePath="..\..\..\source\blender\editors\mesh\editbmesh_add.c"
>
</File>
<File
- RelativePath="..\..\..\source\blender\editors\mesh\editface.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\mesh\editmesh.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\mesh\editmesh_add.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\mesh\editmesh_lib.c"
- >
- </File>
- <File
- RelativePath="..\..\..\source\blender\editors\mesh\editmesh_loop.c"
+ RelativePath="..\..\..\source\blender\editors\mesh\editbmesh_bvh.c"
>
</File>
<File
- RelativePath="..\..\..\source\blender\editors\mesh\editmesh_mods.c"
+ RelativePath="..\..\..\source\blender\editors\mesh\editbmesh_bvh.h"
>
</File>
<File
- RelativePath="..\..\..\source\blender\editors\mesh\editmesh_tools.c"
+ RelativePath="..\..\..\source\blender\editors\mesh\editface.c"
>
</File>
<File
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index f1d04358d9c..c0b11791c1e 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -151,6 +151,9 @@ typedef struct DMFaceIter { int index; int len; + + /*you can set mat_nr and flags, and the backends + must detect and update the internal faces*/ int mat_nr; int flags; diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index f1ab1d61fdf..0801bb27a6a 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -66,6 +66,9 @@ struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob); use_face_origindex sets the tesselation faces' origindex layer to point to the tesselation faces themselves, not the polys. + + if both of the above are 0, it'll use the indices of the mpolys of the MPoly + data in pdata, and ignore the origindex layer altogether. */ int mesh_recalcTesselation(struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MVert *mvert, int totface, diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index ad705395354..91e33eef08a 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1841,6 +1841,10 @@ void cddm_stepiter(void *self) CDDM_FaceIter *iter = self; MPoly *mp; + mp = iter->cddm->mpoly + iter->head.index; + mp->flag = iter->head.flags; + mp->mat_nr = iter->head.mat_nr; + iter->head.index++; if (iter->head.index >= iter->cddm->dm.numPolyData) { iter->head.done = 1; @@ -1937,8 +1941,13 @@ DMFaceIter *cdDM_newFaceIter(DerivedMesh *source) iter->liter.cddm = cddm; iter->cddm = cddm; - iter->head.index = -1; - iter->head.step(iter); + + if (source->numFaceData) { + iter->head.index = -1; + iter->head.step(iter); + } else { + iter->head.done = 1; + } return (DMFaceIter*) iter; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 896d29fd0f8..04f04ca6a8c 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -70,6 +70,7 @@ #include "BKE_mesh.h" #include "BKE_shrinkwrap.h" #include "BKE_mesh.h" +#include "BKE_tessmesh.h" #ifndef DISABLE_PYTHON #include "BPY_extern.h" @@ -406,7 +407,7 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, f { DerivedMesh *dm; Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; float vec[3] = {0.0f, 0.0f, 0.0f}, tvec[3]; float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3]; float imat[3][3], tmat[3][3]; @@ -423,7 +424,7 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, f /* get DerivedMesh */ if (em) { /* target is in editmode, so get a special derived mesh */ - dm = CDDM_from_editmesh(em, ob->data); + dm = CDDM_from_BMEditMesh(em, ob->data); freeDM= 1; } else { @@ -503,8 +504,6 @@ static void contarget_get_mesh_mat (Scene *scene, Object *ob, char *substring, f /* free temporary DerivedMesh created (in EditMode case) */ if (dm && freeDM) dm->release(dm); - if (em) - BKE_mesh_end_editmesh(me, em); } /* function that sets the given matrix based on given vertex group in lattice */ diff --git a/source/blender/blenkernel/intern/editderivedbmesh.c b/source/blender/blenkernel/intern/editderivedbmesh.c index 4f10edf242e..d1a503b36dd 100644 --- a/source/blender/blenkernel/intern/editderivedbmesh.c +++ b/source/blender/blenkernel/intern/editderivedbmesh.c @@ -1387,6 +1387,11 @@ void bmDM_faceIterStep(void *self) { bmDM_faceIter *iter = self; + if (iter->f) { + iter->f->mat_nr = iter->head.mat_nr; + iter->f->head.flag = MEFlags_To_BMFlags(iter->head.flags, BM_FACE); + } + iter->f = iter->nextf; iter->head.mat_nr = iter->f->mat_nr; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 63533ef1adb..a7df7a44475 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -80,21 +80,6 @@ #include "bmesh.h" -EditMesh *BKE_mesh_get_editmesh(Mesh *me) -{ - return bmesh_to_editmesh(me->edit_btmesh->bm); -} - -void free_editMesh(EditMesh *em); -void BKE_mesh_end_editmesh(Mesh *me, EditMesh *em) -{ - BM_Free_Mesh(me->edit_btmesh->bm); - me->edit_btmesh->bm = editmesh_to_bmesh(em); - BMEdit_RecalcTesselation(me->edit_btmesh); - free_editMesh(em); - MEM_freeN(em); -} - static void mesh_ensure_tesselation_customdata(Mesh *me) { int tottex, totcol; @@ -1605,9 +1590,19 @@ static void mesh_loops_to_corners(CustomData *fdata, CustomData *ldata, } } -/*this function recreates a tesselation. +/* + this function recreates a tesselation. + returns number of tesselation faces. + + use_poly_origindex sets whether or not the tesselation faces' origindex + layer should point to original poly indices or real poly indices. - returns number of tesselation faces.*/ + use_face_origindex sets the tesselation faces' origindex layer + to point to the tesselation faces themselves, not the polys. + + if both of the above are 0, it'll use the indices of the mpolys of the MPoly + data in pdata, and ignore the origindex layer altogether. + */ int mesh_recalcTesselation(CustomData *fdata, CustomData *ldata, CustomData *pdata, MVert *mvert, int totface, int totloop, diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9ef10eda6c4..c0446375acd 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7501,7 +7501,6 @@ static void meshdeformModifier_do( { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; Mesh *me= (mmd->object)? mmd->object->data: NULL; - EditMesh *em = (me)? BKE_mesh_get_editmesh(me): NULL; BMEditMesh *bem = me->edit_btmesh; DerivedMesh *tmpdm, *cagedm; MDeformVert *dvert = NULL; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d7738fc3f54..687c9b8c7bf 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1816,25 +1816,27 @@ static void ob_parbone(Object *ob, Object *par, float mat[][4]) static void give_parvert(Object *par, int nr, float *vec) { - EditMesh *em; + BMEditMesh *em; int a, count; vec[0]=vec[1]=vec[2]= 0.0f; if(par->type==OB_MESH) { Mesh *me= par->data; - em = BKE_mesh_get_editmesh(me); + em = me->edit_btmesh; if(em) { - EditVert *eve; - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->keyindex==nr) { + BMVert *eve; + BMIter iter; + + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + int *keyindex = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX); + + if(keyindex && *keyindex==nr) { memcpy(vec, eve->co, sizeof(float)*3); break; } } - BKE_mesh_end_editmesh(me, em); } else { DerivedMesh *dm = par->derivedFinal; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 8a5e1b24c01..991d9f548b0 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1433,13 +1433,13 @@ void cgdm_faceIterStep(void *self) return; } - fiter->head.index++; - - if (fiter->head.index >= ccgSubSurf_getNumFinalFaces(fiter->cgdm->ss)) { + if (fiter->head.index+1 >= ccgSubSurf_getNumFinalFaces(fiter->cgdm->ss)) { fiter->head.done = 1; return; }; + fiter->head.index++; + fiter->mf++; fiter->head.flags = fiter->mface->flag; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index eb8d48896c7..0576031c703 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -578,15 +578,6 @@ BMOpDefine def_extrudefaceregion = { 0 }; -BMOpDefine def_makefgonsop = { - "makefgon", - {{BMOP_OPSLOT_INT, "trifan"}, /*use triangle fans instead of - real interpolation*/ - {0} /*null-terminating sentinel*/}, - bmesh_make_fgons_exec, - 0 -}; - BMOpDefine def_dissolvevertsop = { "dissolveverts", {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, @@ -644,9 +635,10 @@ BMOpDefine def_subdop = { {BMOP_OPSLOT_MAPPING, "custompatterns"}, {BMOP_OPSLOT_MAPPING, "edgepercents"}, - /*these next two can have multiple types of elements in them.*/ + /*these next three can have multiple types of elements in them.*/ {BMOP_OPSLOT_ELEMENT_BUF, "outinner"}, {BMOP_OPSLOT_ELEMENT_BUF, "outsplit"}, + {BMOP_OPSLOT_ELEMENT_BUF, "geomout"}, /*contains all output geometry*/ {BMOP_OPSLOT_INT, "quadcornertype"}, //quad corner type, see bmesh_operators.h {BMOP_OPSLOT_INT, "gridfill"}, //fill in fully-selected faces with a grid @@ -658,22 +650,6 @@ BMOpDefine def_subdop = { 0 }; -BMOpDefine def_edit2bmesh = { - "editmesh_to_bmesh", - {{BMOP_OPSLOT_PNT, "em"}, {BMOP_OPSLOT_MAPPING, "map"}, - {0} /*null-terminating sentinel*/}, - edit2bmesh_exec, - 0 -}; - -BMOpDefine def_bmesh2edit = { - "bmesh_to_editmesh", - {{BMOP_OPSLOT_PNT, "emout"}, - {0} /*null-terminating sentinel*/}, - bmesh2edit_exec, - 0 -}; - BMOpDefine def_delop = { "del", {{BMOP_OPSLOT_ELEMENT_BUF, "geom"}, {BMOP_OPSLOT_INT, "context"}, @@ -837,19 +813,114 @@ BMOpDefine def_edgesplit = { 0 }; +/* + Create Grid + + Creates a grid with a variable number of subdivisions +*/ +BMOpDefine def_create_grid = { + "create_grid", + {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts + {BMOP_OPSLOT_INT, "xsegments"}, //number of x segments + {BMOP_OPSLOT_INT, "ysegments"}, //number of y segments + {BMOP_OPSLOT_FLT, "size"}, //size of the grid + {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with + {0, /*null-terminating sentinel*/}}, + bmesh_create_grid_exec, + 0, +}; + +/* + Create UV Sphere + + Creates a grid with a variable number of subdivisions +*/ +BMOpDefine def_create_uvsphere = { + "create_uvsphere", + {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts + {BMOP_OPSLOT_INT, "segments"}, //number of u segments + {BMOP_OPSLOT_INT, "revolutions"}, //number of v segment + {BMOP_OPSLOT_FLT, "diameter"}, //diameter + {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with-- + {0, /*null-terminating sentinel*/}}, + bmesh_create_uvsphere_exec, + 0, +}; + +/* + Create Ico Sphere + + Creates a grid with a variable number of subdivisions +*/ +BMOpDefine def_create_icosphere = { + "create_icosphere", + {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts + {BMOP_OPSLOT_INT, "subdivisions"}, //how many times to recursively subdivide the sphere + {BMOP_OPSLOT_FLT, "diameter"}, //diameter + {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with + {0, /*null-terminating sentinel*/}}, + bmesh_create_icosphere_exec, + 0, +}; + +/* + Create Suzanne + + Creates a monkey. Be wary. +*/ +BMOpDefine def_create_monkey = { + "create_monkey", + {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts + {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with-- + {0, /*null-terminating sentinel*/}}, + bmesh_create_monkey_exec, + 0, +}; + +/* + Create Cone + + Creates a cone with variable depth at both ends +*/ +BMOpDefine def_create_cone = { + "create_cone", + {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts + {BMOP_OPSLOT_INT, "cap_ends"}, //wheter or not to fill in the ends with faces + {BMOP_OPSLOT_INT, "segments"}, + {BMOP_OPSLOT_FLT, "diameter1"}, //diameter of one end + {BMOP_OPSLOT_FLT, "diameter2"}, //diameter of the opposite + {BMOP_OPSLOT_FLT, "depth"}, //distance between ends + {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with-- + {0, /*null-terminating sentinel*/}}, + bmesh_create_monkey_exec, + 0, +}; + +/* + Create Cone + + Creates a cone with variable depth at both ends +*/ +BMOpDefine def_create_cube = { + "create_cube", + {{BMOP_OPSLOT_ELEMENT_BUF, "vertout"}, //output verts + {BMOP_OPSLOT_FLT, "size"}, //size of the cube + {BMOP_OPSLOT_MAT, "mat"}, //matrix to multiply the new geometry with-- + {0, /*null-terminating sentinel*/}}, + bmesh_create_cube_exec, + 0, +}; + BMOpDefine *opdefines[] = { &def_splitop, &def_dupeop, &def_delop, - &def_edit2bmesh, - &def_bmesh2edit, &def_subdop, &def_triangop, &def_dissolvefacesop, &def_dissolveedgessop, &def_dissolveedgeloopsop, &def_dissolvevertsop, - &def_makefgonsop, &def_extrudefaceregion, &def_connectverts, //&def_makeprim, @@ -892,6 +963,12 @@ BMOpDefine *opdefines[] = { &def_scale, &def_edgesplit, &def_automerge, + &def_create_uvsphere, + &def_create_grid, + &def_create_icosphere, + &def_create_monkey, + &def_create_cone, + &def_create_cube, }; int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*)); diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index e5e05921195..eb0f402b5ff 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -61,5 +61,11 @@ void bmesh_vertexshortestpath_exec(BMesh *bm, BMOperator *op); void bmesh_scale_exec(BMesh *bm, BMOperator *op); void bmesh_edgesplitop_exec(BMesh *bm, BMOperator *op); void bmesh_automerge_exec(BMesh *bm, BMOperator *op); +void bmesh_create_cone_exec(BMesh *bm, BMOperator *op); +void bmesh_create_monkey_exec(BMesh *bm, BMOperator *op); +void bmesh_create_icosphere_exec(BMesh *bm, BMOperator *op); +void bmesh_create_uvsphere_exec(BMesh *bm, BMOperator *op); +void bmesh_create_grid_exec(BMesh *bm, BMOperator *op); +void bmesh_create_cube_exec(BMesh *bm, BMOperator *op); #endif diff --git a/source/blender/bmesh/intern/bmesh_to_editmesh.c b/source/blender/bmesh/intern/bmesh_to_editmesh.c index 1bad95ab0b1..6f43df4d75b 100644 --- a/source/blender/bmesh/intern/bmesh_to_editmesh.c +++ b/source/blender/bmesh/intern/bmesh_to_editmesh.c @@ -1,3 +1,4 @@ +#if 0 #include "MEM_guardedalloc.h" #include "BKE_customdata.h" #include "DNA_listBase.h" @@ -313,4 +314,5 @@ EditMesh *bmesh_to_editmesh(BMesh *bmesh) BMO_Finish_Op(bmesh, &conv); return em; -}
\ No newline at end of file +} +#endif
\ No newline at end of file diff --git a/source/blender/bmesh/intern/editmesh_to_bmesh.c b/source/blender/bmesh/intern/editmesh_to_bmesh.c index cf30f4ae5aa..a2a37639670 100644 --- a/source/blender/bmesh/intern/editmesh_to_bmesh.c +++ b/source/blender/bmesh/intern/editmesh_to_bmesh.c @@ -1,3 +1,4 @@ +#if 0 #include "MEM_guardedalloc.h" #include "BKE_customdata.h" @@ -471,4 +472,5 @@ BMesh *init_editmesh_to_bmesh(EditMesh *em, BMOperator *op) BMO_Set_Pnt(op, "em", em); return bm; -}
\ No newline at end of file +} +#endif diff --git a/source/blender/bmesh/operators/connectops.c b/source/blender/bmesh/operators/connectops.c index 3337a91e2c4..673b34415ae 100644 --- a/source/blender/bmesh/operators/connectops.c +++ b/source/blender/bmesh/operators/connectops.c @@ -101,27 +101,3 @@ void connectverts_exec(BMesh *bm, BMOperator *op) BLI_array_free(loops); BLI_array_free(verts); } - -int BM_ConnectVerts(EditMesh *em, int flag) -{ - EditMesh *em2; - BMesh *bm = editmesh_to_bmesh(em); - BMOperator op; - - BMO_Init_Op(&op, "connectverts"); - BMO_HeaderFlag_To_Slot(bm, &op, "verts", flag, BM_VERT); - BMO_Exec_Op(bm, &op); - BMO_Finish_Op(bm, &op); - - if (BMO_GetSlot(&op, "edgeout")->len > 0 && - BMO_GetError(bm, NULL, NULL)==0) - { - em2 = bmesh_to_editmesh(bm); - set_editMesh(em, em2); - MEM_freeN(em2); - - return 1; - } - - return 0; -}
\ No newline at end of file diff --git a/source/blender/bmesh/operators/join_triangles.c b/source/blender/bmesh/operators/join_triangles.c new file mode 100644 index 00000000000..2c8567273a3 --- /dev/null +++ b/source/blender/bmesh/operators/join_triangles.c @@ -0,0 +1,119 @@ +#if 0 +#include "MEM_guardedalloc.h" +#include "BKE_customdata.h" +#include "DNA_listBase.h" +#include "DNA_customdata_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include <string.h> +#include "BKE_utildefines.h" +#include "BKE_mesh.h" +#include "BKE_global.h" +#include "BKE_DerivedMesh.h" +#include "BKE_cdderivedmesh.h" + +#include "BLI_editVert.h" +#include "mesh_intern.h" +#include "ED_mesh.h" + +#include "BLI_math.h" +#include "BLI_array.h" +#include "BLI_blenlib.h" +#include "BLI_edgehash.h" + +#include "BLI_heap.h" + +#include "bmesh.h" + +/* + * JOIN_TRIANGLES.C + * + * utility bmesh operators, e.g. transform, + * translate, rotate, scale, etc. + * +*/ + +/*assumes edges are validated before reaching this point*/ +static float measure_facepair(BMesh *bm, BMVert *v1, BMVert *v2, + BMVert *v3, BMVert *v4, float limit) +{ + /*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/ + /*Note: this is more complicated than it needs to be and should be cleaned up...*/ + float no1[3], no2[3], measure = 0.0f, angle1, angle2, diff; + float edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3]; + float minarea, maxarea, areaA, areaB; + + /*First Test: Normal difference*/ + normal_tri_v3(n1, v1->co, v2->co, v3->co); + normal_tri_v3(n2, v1->co, v3->co, v4->co); + + if(no1[0] == no2[0] && no1[1] == no2[1] && no1[2] == no2[2]) angle1 = 0.0f; + else angle1 = angle_v2v2(no1, no2); + + normal_tri_v3(n1, v2->co, v3->co, v4->co); + normal_tri_v3(n2, v4->co, v1->co, v2->co); + + if(no1[0] == no2[0] && no1[1] == no2[1] && no1[2] == no2[2]) angle2 = 0.0f; + else angle2 = angle_v2v2(no1, no2); + + measure += (angle1/360.0f) + (angle2/360.0f); + if(measure > limit) return measure; + + /*Second test: Colinearity*/ + sub_v3_v3v3(edgeVec1, v1->co, v2->co); + sub_v3_v3v3(edgeVec2, v2->co, v3->co); + sub_v3_v3v3(edgeVec3, v3->co, v4->co); + sub_v3_v3v3(edgeVec4, v4->co, v1->co); + + diff = 0.0; + + diff = ( + fabs(angle_v2v2(edgeVec1, edgeVec2) - 90) + + fabs(angle_v2v2(edgeVec2, edgeVec3) - 90) + + fabs(angle_v2v2(edgeVec3, edgeVec4) - 90) + + fabs(angle_v2v2(edgeVec4, edgeVec1) - 90)) / 360.0f; + if(!diff) return 0.0; + + measure += diff; + if(measure > limit) return measure; + + /*Third test: Concavity*/ + areaA = area_tri_v3(v1->co, v2->co, v3->co) + area_tri_v3(v1->co, v3->co, v4->co); + areaB = area_tri_v3(v2->co, v3->co, v4->co) + area_tri_v3(v4->co, v1->co, v2->co); + + if(areaA <= areaB) minarea = areaA; + else minarea = areaB; + + if(areaA >= areaB) maxarea = areaA; + else maxarea = areaB; + + if(!maxarea) measure += 1; + else measure += (1 - (minarea / maxarea)); + + return measure; +} + +#define T2QUV_LIMIT 0.005 +#define T2QCOL_LIMIT 3 + +static int compareFaceAttribs(BMesh *bm, BMEdge *e) +{ + MTexPoly *tp1, *tp2; + MLoopCol *lcol1, *lcol2, *lcol3, *lcol4; + MLoopUV *luv1, *luv2, *luv3, *luv4; + BMLoop *l1, *l2; + + l1 = e->loop + l2 = (BMLoop*)e->loop->radial.next->data; + + +} + +void bmesh_jointriangles_exec(BMesh *bm, BMOperator *op) +{ + +} + +#endif diff --git a/source/blender/bmesh/operators/primitiveops.c b/source/blender/bmesh/operators/primitiveops.c new file mode 100644 index 00000000000..ba32d09abb6 --- /dev/null +++ b/source/blender/bmesh/operators/primitiveops.c @@ -0,0 +1,581 @@ +#include "MEM_guardedalloc.h" + +#include "DNA_meshdata_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_utildefines.h" + +#include "BLI_math.h" +#include "BLI_ghash.h" +#include "BLI_blenlib.h" +#include "BLI_array.h" + +#include "bmesh.h" +#include "mesh_intern.h" +#include "bmesh_private.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + + +/* ************************ primitives ******************* */ + +static float icovert[12][3] = { + {0.0f,0.0f,-200.0f}, + {144.72f, -105.144f,-89.443f}, + {-55.277f, -170.128,-89.443f}, + {-178.885f,0.0f,-89.443f}, + {-55.277f,170.128f,-89.443f}, + {144.72f,105.144f,-89.443f}, + {55.277f,-170.128f,89.443f}, + {-144.72f,-105.144f,89.443f}, + {-144.72f,105.144f,89.443f}, + {55.277f,170.128f,89.443f}, + {178.885f,0.0f,89.443f}, + {0.0f,0.0f,200.0f} +}; + +static short icoface[20][3] = { + {1,0,2}, + {1,0,5}, + {2,0,3}, + {3,0,4}, + {4,0,5}, + {1,5,10}, + {2,1,6}, + {3,2,7}, + {4,3,8}, + {5,4,9}, + {10,1,6}, + {6,2,7}, + {7,3,8}, + {8,4,9}, + {9,5,10}, + {6,10,11}, + {7,6,11}, + {8,7,11}, + {9,8,11}, + {10,9,11} +}; + +// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker +// this hack is only used so that scons+mingw + split-sources hack works + // ------------------------------- start copied code +/* these are not the monkeys you are looking for */ +int monkeyo= 4; +int monkeynv= 271; +int monkeynf= 250; +signed char monkeyv[271][3]= { +{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92}, +{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83}, +{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102}, +{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92}, +{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74}, +{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99}, +{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105}, +{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100}, +{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100}, +{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73}, +{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45}, +{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68}, +{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68}, +{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80}, +{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96}, +{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90}, +{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85}, +{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94}, +{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96}, +{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95}, +{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84}, +{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109}, +{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88}, +{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82}, +{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96}, +{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96}, +{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100}, +{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104}, +{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71}, +{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88}, +{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84}, +{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81}, +{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99}, +{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87}, +{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100}, +{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97}, +{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86}, +{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96}, +{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79}, +{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59}, +{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37}, +{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59}, +{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7}, +{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9}, +{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52}, +{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51}, +{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55}, +{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34}, +{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30}, +{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7}, +{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57}, +{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26}, +{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16}, +{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54}, +{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52}, +{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28}, +{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57}, +{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27}, +{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35}, +{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24}, +{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41}, +{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41}, +{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62}, +{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42}, +{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48}, +{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62}, +{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63}, +{-26,-16,-42},{-17,49,-49}, +}; + +signed char monkeyf[250][4]= { +{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, +{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, +{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, +{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, +{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, +{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, +{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, +{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, +{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, +{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, +{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, +{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, +{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, +{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, +{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, +{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, +{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, +{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, +{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, +{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, +{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, +{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, +{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, +{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, +{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, +{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, +{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, +{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, +{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, +{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, +{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, +{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, +{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, +{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, +{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, +{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, +{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, +{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, +{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, +{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, +{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, +{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, +{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, +{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, +{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, +{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, +{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, +{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, +{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, +{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, +{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, +{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, +{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, +{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, +{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, +{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, +{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, +{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, +{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, +{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, +{-68,-67,24,-33}, +}; + +#define VERT_MARK 1 + +#define EDGE_ORIG 1 +#define EDGE_MARK 2 + +#define FACE_MARK 1 + +void bmesh_create_grid_exec(BMesh *bm, BMOperator *op) +{ + BMOperator bmop, prevop; + BMVert *eve, *preveve; + BMEdge *e; + float vec[3], mat[4][4], phi, phid, dia=BMO_Get_Float(op, "size"); + int a, tot=BMO_Get_Int(op, "xsegments"), seg=BMO_Get_Int(op, "ysegments"); + + if (tot < 2) tot = 2; + if (seg < 2) seg = 2; + + BMO_Get_Mat4(op, "mat", mat); + + /* one segment first: the X axis */ + phi= 1.0; + phid= 2.0/((float)tot-1); + for(a=0;a<tot;a++) { + vec[0]= dia*phi; + vec[1]= - dia; + vec[2]= 0.0f; + mul_m4_v3(mat,vec); + + eve= BM_Make_Vert(bm, vec, NULL); + BM_Select(bm, eve, 1); + + if (a) { + e = BM_Make_Edge(bm, preveve, eve, NULL, 1); + BMO_SetFlag(bm, e, EDGE_ORIG); + } + + preveve = eve; + phi-=phid; + } + + /* extrude and translate */ + vec[0]= vec[2]= 0.0; + vec[1]= dia*phid; + mul_mat3_m4_v3(mat, vec); + + for(a=0;a<seg-1;a++) { + if (a) { + BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_Exec_Op(bm, &bmop); + BMO_Finish_Op(bm, &prevop); + + BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT); + } else { + BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%fe", EDGE_ORIG); + BMO_Exec_Op(bm, &bmop); + BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT); + } + + BMO_CallOpf(bm, "translate vec=%v verts=%s", vec, &bmop, "geomout"); + prevop = bmop; + } + + if (a) + BMO_Finish_Op(bm, &bmop); + + BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT); +} + +void bmesh_create_uvsphere_exec(BMesh *bm, BMOperator *op) +{ + BMOperator bmop, prevop; + BMVert *eve, *preveve, *v1; + BMEdge *e; + BMIter iter; + float vec[3], mat[4][4], cmat[3][3], phi, q[4]; + float phid, dia=BMO_Get_Float(op, "diameter"); + int a, seg=BMO_Get_Int(op, "segments"), tot=BMO_Get_Int(op, "revolutions"); + + BMO_Get_Mat4(op, "mat", mat); + + phid= 2.0f*(float)M_PI/tot; + phi= .25f*(float)M_PI; + + /* one segment first */ + phi= 0; + phid/=2; + for(a=0; a<=tot; a++) { + vec[0]= dia*sin(phi); + vec[1]= 0.0; + vec[2]= dia*cos(phi); + eve= BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, eve, VERT_MARK); + + if(a==0) v1= eve; + else { + e = BM_Make_Edge(bm, preveve, eve, NULL, 0); + BMO_SetFlag(bm, e, EDGE_ORIG); + } + + phi+= phid; + preveve = eve; + } + + /* extrude and rotate */ + phi= M_PI/seg; + q[0]= cos(phi); + q[3]= sin(phi); + q[1]=q[2]= 0; + quat_to_mat3(cmat, q); + + for(a=0; a<seg; a++) { + if (a) { + BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_Exec_Op(bm, &bmop); + BMO_Finish_Op(bm, &prevop); + } else { + BMO_InitOpf(bm, &bmop, "extrude_edge_only edges=%fe", EDGE_ORIG); + BMO_Exec_Op(bm, &bmop); + } + + BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT); + BMO_CallOpf(bm, "rotate cent=%v mat=%m3 verts=%s", vec, cmat, &bmop, "geomout"); + + prevop = bmop; + } + + if (a) + BMO_Finish_Op(bm, &bmop); + + BMO_CallOpf(bm, "removedoubles verts=%fv dist=%f", VERT_MARK, 0.001f); + + /* and now do imat */ + BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) { + if(BMO_TestFlag(bm, eve, VERT_MARK)) { + mul_m4_v3(mat, eve->co); + } + } + + BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT); +} + +void bmesh_create_icosphere_exec(BMesh *bm, BMOperator *op) +{ + BMVert *eva[12]; + float vec[3], mat[4][4], phi, phid; + float dia = BMO_Get_Float(op, "diameter"); + int a, subdiv = BMO_Get_Int(op, "subdivisions"); + + BMO_Get_Mat4(op, "mat", mat); + + phid= 2.0f*(float)M_PI/subdiv; + phi= .25f*(float)M_PI; + + dia/=200; + for(a=0;a<12;a++) { + vec[0]= dia*icovert[a][0]; + vec[1]= dia*icovert[a][1]; + vec[2]= dia*icovert[a][2]; + eva[a]= BM_Make_Vert(bm, vec, NULL); + + mul_m4_v3(mat, eva[a]->co); + BM_Select(bm, eva[a], 1); + } + + for(a=0;a<20;a++) { + BMFace *evtemp; + BMVert *v1, *v2, *v3; + + v1= eva[ icoface[a][0] ]; + v2= eva[ icoface[a][1] ]; + v3= eva[ icoface[a][2] ]; + + evtemp = BM_Make_QuadTri(bm, v1, v2, v3, NULL, NULL, 0); + BMO_SetFlag(bm, evtemp, FACE_MARK); + } + + dia*=200; + + for(a=1; a<subdiv; a++) { + BMOperator bmop; + + BMO_InitOpf(bm, &bmop, "esubd edges=%he smooth=%f numcuts=%i gridfill=%i", EDGE_MARK, dia, 1, 1); + BMO_Exec_Op(bm, &bmop); + BMO_Flag_Buffer(bm, &bmop, "geomout", VERT_MARK, BM_VERT); + BMO_Finish_Op(bm, &bmop); + } + + BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT); +} + +void bmesh_create_monkey_exec(BMesh *bm, BMOperator *op) +{ + BMVert *eve; + BMVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv"); + float mat[4][4]; + int i; + + BMO_Get_Mat4(op, "mat", mat); + + for (i=0; i<monkeynv; i++) { + float v[3]; + + v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0; + + tv[i]= BM_Make_Vert(bm, v, NULL); + BMO_SetFlag(bm, tv[i], VERT_MARK); + + tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]: (eve=BM_Make_Vert(bm, v, NULL), mul_m4_v3(mat, eve->co), eve); + BMO_SetFlag(bm, tv[monkeynv+i], VERT_MARK); + + mul_m4_v3(mat, tv[i]->co); + } + + for (i=0; i<monkeynf; i++) { + BM_Make_QuadTri(bm, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, 0); + BM_Make_QuadTri(bm, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, 0); + } + + MEM_freeN(tv); + + BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT); +} + +void bmesh_create_cone_exec(BMesh *bm, BMOperator *op) +{ + BMVert *v1, *v2, *lastv1=NULL, *lastv2=NULL, *cent1, *cent2, *firstv1, *firstv2; + float vec[3], mat[4][4], phi, phid; + float dia1 = BMO_Get_Float(op, "diameter1"); + float dia2 = BMO_Get_Float(op, "diameter2"); + float depth = BMO_Get_Float(op, "depth"); + int cap_ends = BMO_Get_Int(op, "cap_ends"), segs=BMO_Get_Int(op, "segments"); + int a; + + BMO_Get_Mat4(op, "mat", mat); + + phid= 2.0f*(float)M_PI/segs; + phi= .25f*(float)M_PI; + + depth *= 0.5f; + if (cap_ends) { + vec[0] = vec[1] = 0.0f; + vec[2] = -depth; + + cent1 = BM_Make_Vert(bm, vec, NULL); + + vec[0] = vec[1] = 0.0f; + vec[2] = depth; + cent2 = BM_Make_Vert(bm, vec, NULL); + + BMO_SetFlag(bm, cent1, VERT_MARK); + BMO_SetFlag(bm, cent2, VERT_MARK); + } + + for (a=0; a<segs; a++) { + vec[0]= dia1*sin(phi); + vec[1]= dia1*cos(phi); + vec[2]= -depth; + mul_m4_v3(mat, vec); + v1 = BM_Make_Vert(bm, vec, NULL); + + vec[0]= dia2*sin(phi); + vec[1]= dia2*cos(phi); + vec[2]= depth; + mul_m4_v3(mat, vec); + v2 = BM_Make_Vert(bm, vec, NULL); + + BMO_SetFlag(bm, v1, VERT_MARK); + BMO_SetFlag(bm, v2, VERT_MARK); + + if (a) { + if (cap_ends) { + BM_Make_QuadTri(bm, cent1, lastv1, v1, NULL, NULL, 0); + } + BM_Make_QuadTri(bm, lastv1, lastv2, v2, v1, NULL, 0); + } else { + firstv1 = v1; + firstv2 = v2; + } + + lastv1 = v1; + lastv2 = v2; + } + + if (!a) + return; + + if (cap_ends) { + BM_Make_QuadTri(bm, cent1, firstv1, v1, NULL, NULL, 0); + } + + BM_Make_QuadTri(bm, firstv1, firstv2, v2, v1, NULL, 0); + + BMO_CallOpf(bm, "removedoubles verts=%fv dist=%f", VERT_MARK, 0.000001); + BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT); +} + +void bmesh_create_cube_exec(BMesh *bm, BMOperator *op) +{ + BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8; + float vec[3], mat[4][4], off = BMO_Get_Float(op, "size") / 2.0f; + + BMO_Get_Mat4(op, "mat", mat); + + if (!off) off = 0.5f; + + vec[0] = -off; + vec[1] = -off; + vec[2] = -off; + mul_m4_v3(mat, vec); + v1 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v1, VERT_MARK); + + vec[0] = -off; + vec[1] = off; + vec[2] = -off; + mul_m4_v3(mat, vec); + v2 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v2, VERT_MARK); + + vec[0] = off; + vec[1] = off; + vec[2] = -off; + mul_m4_v3(mat, vec); + v3 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v3, VERT_MARK); + + vec[0] = off; + vec[1] = -off; + vec[2] = -off; + mul_m4_v3(mat, vec); + v4 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v4, VERT_MARK); + + vec[0] = -off; + vec[1] = -off; + vec[2] = off; + mul_m4_v3(mat, vec); + v5 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v5, VERT_MARK); + + vec[0] = -off; + vec[1] = off; + vec[2] = off; + mul_m4_v3(mat, vec); + v6 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v6, VERT_MARK); + + vec[0] = off; + vec[1] = off; + vec[2] = off; + mul_m4_v3(mat, vec); + v7 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v7, VERT_MARK); + + vec[0] = off; + vec[1] = -off; + vec[2] = off; + mul_m4_v3(mat, vec); + v8 = BM_Make_Vert(bm, vec, NULL); + BMO_SetFlag(bm, v8, VERT_MARK); + + /*the four sides*/ + BM_Make_QuadTri(bm, v5, v6, v2, v1, NULL, 0); + BM_Make_QuadTri(bm, v6, v7, v3, v2, NULL, 0); + BM_Make_QuadTri(bm, v7, v8, v4, v3, NULL, 0); + BM_Make_QuadTri(bm, v8, v5, v1, v4, NULL, 0); + + /*top/bottom*/ + BM_Make_QuadTri(bm, v1, v2, v3, v4, NULL, 0); + BM_Make_QuadTri(bm, v8, v7, v6, v5, NULL, 0); + + BMO_Flag_To_Slot(bm, op, "vertout", VERT_MARK, BM_VERT); +} diff --git a/source/blender/bmesh/operators/removedoubles.c b/source/blender/bmesh/operators/removedoubles.c index c7ab4af3ada..f8c0086d7fa 100644 --- a/source/blender/bmesh/operators/removedoubles.c +++ b/source/blender/bmesh/operators/removedoubles.c @@ -475,8 +475,10 @@ void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op) float vec[3]; v2 = verts[j]; - if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2]) - > distsqr) break; + //if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2]) + // > distsqr) break; + if ((v2->co[0]-v->co[0]) + (v2->co[1]-v->co[1]) + (v2->co[2]-v->co[2]) > distsqr*4.0f) + break; vec[0] = v->co[0] - v2->co[0]; vec[1] = v->co[1] - v2->co[1]; diff --git a/source/blender/bmesh/operators/subdivideop.c b/source/blender/bmesh/operators/subdivideop.c index f8e1723b009..701bce4ca88 100644 --- a/source/blender/bmesh/operators/subdivideop.c +++ b/source/blender/bmesh/operators/subdivideop.c @@ -964,6 +964,9 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op) ELE_INNER, BM_ALL); BMO_Flag_To_Slot(bmesh, op, "outsplit", ELE_SPLIT, BM_ALL); + + BMO_Flag_To_Slot(bmesh, op, "geomout", + ELE_INNER|ELE_SPLIT, BM_ALL); } /*editmesh-emulating function*/ diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index e205c19e797..69a29475434 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -3386,6 +3386,8 @@ static int iteratorStopped(void *arg) ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C) { + return NULL; +#if 0 Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); EditMesh *em =BKE_mesh_get_editmesh(((Mesh*)obedit->data)); @@ -3491,6 +3493,7 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C) MEM_freeN(em); return rg; +#endif } #if 0 diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 273dc50317b..8f7a71ca460 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -91,13 +91,16 @@ void EDBM_MakeEditBMesh(struct ToolSettings *ts, struct Scene *scene, struct Obj void EDBM_FreeEditBMesh(struct BMEditMesh *tm); void EDBM_LoadEditBMesh(struct Scene *scene, struct Object *ob); -void EDBM_init_index_arrays(struct BMEditMesh *tm, int forvert, int foredge, int forface); -void EDBM_free_index_arrays(struct BMEditMesh *tm); -struct BMVert *EDBM_get_vert_for_index(struct BMEditMesh *tm, int index); -struct BMEdge *EDBM_get_edge_for_index(struct BMEditMesh *tm, int index); -struct BMFace *EDBM_get_face_for_index(struct BMEditMesh *tm, int index); +void EDBM_init_index_arrays(struct BMEditMesh *em, int forvert, int foredge, int forface); +void EDBM_free_index_arrays(struct BMEditMesh *em); +struct BMVert *EDBM_get_vert_for_index(struct BMEditMesh *em, int index); +struct BMEdge *EDBM_get_edge_for_index(struct BMEditMesh *em, int index); +struct BMFace *EDBM_get_face_for_index(struct BMEditMesh *em, int index); struct BMFace *EDBM_get_actFace(struct BMEditMesh *em, int sloppy); +int EDBM_CallAndSelectOpf(struct BMEditMesh *em, struct wmOperator *op, + char *selectslot, char *fmt, ...); + /*flushes based on the current select mode. if in vertex select mode, verts select/deselect edges and faces, if in edge select mode, edges select/deselect faces and vertices, and in face select mode faces select/deselect diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c index 960d7ca45b7..aa6a700eb6f 100644 --- a/source/blender/editors/mesh/bmesh_select.c +++ b/source/blender/editors/mesh/bmesh_select.c @@ -1786,15 +1786,17 @@ void MESH_OT_select_less(wmOperatorType *ot) static int mesh_select_nth_exec(bContext *C, wmOperator *op) { Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; int nth = RNA_int_get(op->ptr, "nth"); +#if 0 //BMESH_TODO if(EM_deselect_nth(em, nth) == 0) { BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face."); return OPERATOR_CANCELLED; } - - BKE_mesh_end_editmesh(obedit->data, em); +#else + BKE_report(op->reports, RPT_ERROR, "Unimplemented"); +#endif DAG_id_flush_update(obedit->data, OB_RECALC_DATA); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); @@ -2053,3 +2055,21 @@ int EM_deselect_nth(EditMesh *em, int nth) #endif return 1; } + +void em_setup_viewcontext(bContext *C, ViewContext *vc) +{ + view3d_set_viewcontext(C, vc); + + if(vc->obedit) { + Mesh *me= vc->obedit->data; + vc->em= me->edit_btmesh; + } +} + +/* poll call for mesh operators requiring a view3d context */ +int EM_view3d_poll(bContext *C) +{ + if(ED_operator_editmesh(C) && ED_operator_view3d_active(C)) + return 1; + return 0; +} diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c index e92eab07c1b..c1e659de106 100644 --- a/source/blender/editors/mesh/bmesh_tools.c +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -3653,3 +3653,1137 @@ void MESH_OT_solidify(wmOperatorType *ot) prop= RNA_def_float(ot->srna, "thickness", 0.01f, -FLT_MAX, FLT_MAX, "thickness", "", -10.0f, 10.0f); RNA_def_property_ui_range(prop, -10, 10, 0.1, 4); } + +#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */ +#define TRAIL_FREEHAND 2 +#define TRAIL_MIXED 3 /* (1|2) */ +#define TRAIL_AUTO 4 +#define TRAIL_MIDPOINTS 8 + +typedef struct CutCurve { + float x; + float y; +} CutCurve; + +/* ******************************************************************** */ +/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail + drawn by user. + + Currently mapped to KKey when in MeshEdit mode. + Usage: + Hit Shift K, Select Centers or Exact + Hold LMB down to draw path, hit RETKEY. + ESC cancels as expected. + + Contributed by Robert Wenzlaff (Det. Thorn). + + 2.5 revamp: + - non modal (no menu before cutting) + - exit on mouse release + - polygon/segment drawing can become handled by WM cb later + + bmesh port version +*/ + +#define KNIFE_EXACT 1 +#define KNIFE_MIDPOINT 2 +#define KNIFE_MULTICUT 3 + +static EnumPropertyItem knife_items[]= { + {KNIFE_EXACT, "EXACT", 0, "Exact", ""}, + {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""}, + {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""}, + {0, NULL, 0, NULL, NULL} +}; + +/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */ + +static float bm_seg_intersect(BMEdge *e, CutCurve *c, int len, char mode, + struct GHash *gh, int *isected) +{ +#define MAXSLOPE 100000 + float x11, y11, x12=0, y12=0, x2max, x2min, y2max; + float y2min, dist, lastdist=0, xdiff2, xdiff1; + float m1, b1, m2, b2, x21, x22, y21, y22, xi; + float yi, x1min, x1max, y1max, y1min, perc=0; + float *scr; + float threshold = 0.0; + int i; + + //threshold = 0.000001; /*tolerance for vertex intersection*/ + // XXX threshold = scene->toolsettings->select_thresh / 100; + + /* Get screen coords of verts */ + scr = BLI_ghash_lookup(gh, e->v1); + x21=scr[0]; + y21=scr[1]; + + scr = BLI_ghash_lookup(gh, e->v2); + x22=scr[0]; + y22=scr[1]; + + xdiff2=(x22-x21); + if (xdiff2) { + m2=(y22-y21)/xdiff2; + b2= ((x22*y21)-(x21*y22))/xdiff2; + } + else { + m2=MAXSLOPE; /* Verticle slope */ + b2=x22; + } + + *isected = 0; + + /*check for *exact* vertex intersection first*/ + if(mode!=KNIFE_MULTICUT){ + for (i=0; i<len; i++){ + if (i>0){ + x11=x12; + y11=y12; + } + else { + x11=c[i].x; + y11=c[i].y; + } + x12=c[i].x; + y12=c[i].y; + + /*test e->v1*/ + if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){ + perc = 0; + *isected = 1; + return(perc); + } + /*test e->v2*/ + else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){ + perc = 0; + *isected = 2; + return(perc); + } + } + } + + /*now check for edge interesect (may produce vertex intersection as well)*/ + for (i=0; i<len; i++){ + if (i>0){ + x11=x12; + y11=y12; + } + else { + x11=c[i].x; + y11=c[i].y; + } + x12=c[i].x; + y12=c[i].y; + + /* Perp. Distance from point to line */ + if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */ + /* change in sign. Skip extra math */ + else dist=x22-x12; + + if (i==0) lastdist=dist; + + /* if dist changes sign, and intersect point in edge's Bound Box*/ + if ((lastdist*dist)<=0){ + xdiff1=(x12-x11); /* Equation of line between last 2 points */ + if (xdiff1){ + m1=(y12-y11)/xdiff1; + b1= ((x12*y11)-(x11*y12))/xdiff1; + } + else{ + m1=MAXSLOPE; + b1=x12; + } + x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */ + x2min=MIN2(x21,x22)-0.001; /* due to round off error */ + y2max=MAX2(y21,y22)+0.001; + y2min=MIN2(y21,y22)-0.001; + + /* Found an intersect, calc intersect point */ + if (m1==m2){ /* co-incident lines */ + /* cut at 50% of overlap area*/ + x1max=MAX2(x11, x12); + x1min=MIN2(x11, x12); + xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0; + + y1max=MAX2(y11, y12); + y1min=MIN2(y11, y12); + yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0; + } + else if (m2==MAXSLOPE){ + xi=x22; + yi=m1*x22+b1; + } + else if (m1==MAXSLOPE){ + xi=x12; + yi=m2*x12+b2; + } + else { + xi=(b1-b2)/(m2-m1); + yi=(b1*m2-m1*b2)/(m2-m1); + } + + /* Intersect inside bounding box of edge?*/ + if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){ + /*test for vertex intersect that may be 'close enough'*/ + if(mode!=KNIFE_MULTICUT){ + if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){ + if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){ + *isected = 1; + perc = 0; + break; + } + } + if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){ + if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){ + *isected = 2; + perc = 0; + break; + } + } + } + if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21); + else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/ + //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */ + + break; + } + } + lastdist=dist; + } + return(perc); +} + +#define MAX_CUTS 256 + +static int knife_cut_exec(bContext *C, wmOperator *op) +{ + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; + BMesh *bm = em->bm; + ARegion *ar= CTX_wm_region(C); + BMVert *bv; + BMIter iter; + BMEdge *be; + BMOperator bmop; + CutCurve curve[MAX_CUTS]; + struct GHash *gh; + float isect=0.0; + float *scr, co[4]; + int len=0, isected, flag, i; + short numcuts=1, mode= RNA_int_get(op->ptr, "type"); + + /* edit-object needed for matrix, and ar->regiondata for projections to work */ + if (ELEM3(NULL, obedit, ar, ar->regiondata)) + return OPERATOR_CANCELLED; + + if (bm->totvertsel < 2) { + error("No edges are selected to operate on"); + return OPERATOR_CANCELLED;; + } + + /* get the cut curve */ + RNA_BEGIN(op->ptr, itemptr, "path") { + + RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]); + len++; + if(len>= MAX_CUTS) break; + } + RNA_END; + + if(len<2) { + return OPERATOR_CANCELLED; + } + + /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/ + gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + for(bv=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);bv;bv=BMIter_Step(&iter)){ + scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates"); + VECCOPY(co, bv->co); + co[3]= 1.0; + mul_m4_v4(obedit->obmat, co); + project_float(ar, co, scr); + BLI_ghash_insert(gh, bv, scr); + } + + BMO_Init_Op(&bmop, "esubd"); + + i = 0; + /*store percentage of edge cut for KNIFE_EXACT here.*/ + for (be=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be=BMIter_Step(&iter)) { + if( BM_Selected(bm, be) ) { + isect= bm_seg_intersect(be, curve, len, mode, gh, &isected); + + if (isect != 0.0f) { + if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { + BMO_Insert_MapFloat(bm, &bmop, + "edgepercents", + be, isect); + + } + BMO_SetFlag(bm, be, 1); + } else BMO_ClearFlag(bm, be, 1); + } else BMO_ClearFlag(bm, be, 1); + } + + BMO_Flag_To_Slot(bm, &bmop, "edges", 1, BM_EDGE); + + BMO_Set_Int(&bmop, "numcuts", numcuts); + flag = B_KNIFE; + if (mode == KNIFE_MIDPOINT) numcuts = 1; + BMO_Set_Int(&bmop, "flag", flag); + BMO_Set_Float(&bmop, "radius", 0); + + BMO_Exec_Op(bm, &bmop); + BMO_Finish_Op(bm, &bmop); + + BLI_ghash_free(gh, NULL, (GHashValFreeFP)WMEM_freeN); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_knife_cut(wmOperatorType *ot) +{ + PropertyRNA *prop; + + ot->name= "Knife Cut"; + ot->description= "Cut selected edges and faces into parts."; + ot->idname= "MESH_OT_knife_cut"; + + ot->invoke= WM_gesture_lines_invoke; + ot->modal= WM_gesture_lines_modal; + ot->exec= knife_cut_exec; + + ot->poll= EM_view3d_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", ""); + prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); + + /* internal */ + RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX); +} + +static int mesh_separate_exec(bContext *C, wmOperator *op) +{ +#if 0 + Scene *scene= CTX_data_scene(C); + Base *base= CTX_data_active_base(C); + int retval= 0, type= RNA_enum_get(op->ptr, "type"); + + if(type == 0) + retval= mesh_separate_selected(scene, base); + else if(type == 1) + retval= mesh_separate_material (scene, base); + else if(type == 2) + retval= mesh_separate_loose(scene, base); + + if(retval) { + WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data); + return OPERATOR_FINISHED; + } + +#endif + return OPERATOR_CANCELLED; +} + +/* *************** Operator: separate parts *************/ + +static EnumPropertyItem prop_separate_types[] = { + {0, "SELECTED", 0, "Selection", ""}, + {1, "MATERIAL", 0, "By Material", ""}, + {2, "LOOSE", 0, "By loose parts", ""}, + {0, NULL, 0, NULL, NULL} +}; + +void MESH_OT_separate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Separate"; + ot->description= "Separate selected geometry into a new mesh."; + ot->idname= "MESH_OT_separate"; + + /* api callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= mesh_separate_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", ""); +} + + +static int fill_mesh_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + fill_mesh(em); + + BKE_mesh_end_editmesh(obedit->data, em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); +#endif + return OPERATOR_FINISHED; + +} + +void MESH_OT_fill(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Fill"; + ot->idname= "MESH_OT_fill"; + + /* api callbacks */ + ot->exec= fill_mesh_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int beauty_fill_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + beauty_fill(em); + + BKE_mesh_end_editmesh(obedit->data, em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_beauty_fill(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Beauty Fill"; + ot->idname= "MESH_OT_beauty_fill"; + + /* api callbacks */ + ot->exec= beauty_fill_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/********************** Quad/Tri Operators *************************/ + +static int quads_convert_to_tris_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; + + //convert_to_triface(em,0); + if (!EDBM_CallOpf(em, op, "triangulate faces=%hf", BM_SELECT)) + return OPERATOR_CANCELLED; + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Quads to Tris"; + ot->idname= "MESH_OT_quads_convert_to_tris"; + + /* api callbacks */ + ot->exec= quads_convert_to_tris_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int tris_convert_to_quads_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + join_triangles(em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_tris_convert_to_quads(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Tris to Quads"; + ot->idname= "MESH_OT_tris_convert_to_quads"; + + /* api callbacks */ + ot->exec= tris_convert_to_quads_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int edge_flip_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + edge_flip(em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_edge_flip(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Edge Flip"; + ot->idname= "MESH_OT_edge_flip"; + + /* api callbacks */ + ot->exec= edge_flip_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int split_mesh(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + WM_cursor_wait(1); + + /* make duplicate first */ + adduplicateflag(em, SELECT); + /* old faces have flag 128 set, delete them */ + delfaceflag(em, 128); + recalc_editnormals(em); + + WM_cursor_wait(0); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_FINISHED; +#endif +} + +void MESH_OT_split(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Split"; + ot->idname= "MESH_OT_split"; + + /* api callbacks */ + ot->exec= split_mesh; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + + +static int spin_mesh(bContext *C, wmOperator *op, float *dvec, int steps, float degr, int dupli ) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + ToolSettings *ts= CTX_data_tool_settings(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + EditVert *eve,*nextve; + float nor[3]= {0.0f, 0.0f, 0.0f}; + float si, n[3], q[4], cmat[3][3], imat[3][3], tmat[3][3]; + float cent[3], bmat[3][3]; + float phi; + short a, ok= 1; + + RNA_float_get_array(op->ptr, "center", cent); + + /* imat and center and size */ + copy_m3_m4(bmat, obedit->obmat); + invert_m3_m3(imat,bmat); + + cent[0]-= obedit->obmat[3][0]; + cent[1]-= obedit->obmat[3][1]; + cent[2]-= obedit->obmat[3][2]; + mul_m3_v3(imat, cent); + + phi= degr*M_PI/360.0; + phi/= steps; + if(ts->editbutflag & B_CLOCKWISE) phi= -phi; + + RNA_float_get_array(op->ptr, "axis", n); + normalize_v3(n); + + q[0]= (float)cos(phi); + si= (float)sin(phi); + q[1]= n[0]*si; + q[2]= n[1]*si; + q[3]= n[2]*si; + quat_to_mat3( cmat,q); + + mul_m3_m3m3(tmat,cmat,bmat); + mul_m3_m3m3(bmat,imat,tmat); + + if(dupli==0) + if(ts->editbutflag & B_KEEPORIG) + adduplicateflag(em, 1); + + for(a=0; a<steps; a++) { + if(dupli==0) ok= extrudeflag(obedit, em, SELECT, nor, 0); + else adduplicateflag(em, SELECT); + + if(ok==0) + break; + + rotateflag(em, SELECT, cent, bmat); + if(dvec) { + mul_m3_v3(bmat,dvec); + translateflag(em, SELECT, dvec); + } + } + + if(ok==0) { + /* no vertices or only loose ones selected, remove duplicates */ + eve= em->verts.first; + while(eve) { + nextve= eve->next; + if(eve->f & SELECT) { + BLI_remlink(&em->verts,eve); + free_editvert(em, eve); + } + eve= nextve; + } + } + else { + recalc_editnormals(em); + + EM_fgon_flags(em); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + } + + BKE_mesh_end_editmesh(obedit->data, em); + return ok; +#endif +} + +static int spin_mesh_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + int ok; + + ok= spin_mesh(C, op, NULL, RNA_int_get(op->ptr,"steps"), RNA_float_get(op->ptr,"degrees"), RNA_boolean_get(op->ptr,"dupli")); + if(ok==0) { + BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected"); + return OPERATOR_CANCELLED; + } + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); +#endif + return OPERATOR_FINISHED; +} + +/* get center and axis, in global coords */ +static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ +#if 0 + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d= ED_view3d_context_rv3d(C); + + RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d)); + RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]); + + return spin_mesh_exec(C, op); +#endif +} + +void MESH_OT_spin(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Spin"; + ot->idname= "MESH_OT_spin"; + + /* api callbacks */ + ot->invoke= spin_mesh_invoke; + ot->exec= spin_mesh_exec; + ot->poll= EM_view3d_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX); + RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates"); + RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f); + + RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); + RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); + +} + +static int screw_mesh_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + EditVert *eve,*v1=0,*v2=0; + EditEdge *eed; + float dvec[3], nor[3]; + int steps, turns; + + turns= RNA_int_get(op->ptr, "turns"); + steps= RNA_int_get(op->ptr, "steps"); + + /* clear flags */ + for(eve= em->verts.first; eve; eve= eve->next) + eve->f1= 0; + + /* edges set flags in verts */ + for(eed= em->edges.first; eed; eed= eed->next) { + if(eed->v1->f & SELECT) { + if(eed->v2->f & SELECT) { + /* watch: f1 is a byte */ + if(eed->v1->f1<2) eed->v1->f1++; + if(eed->v2->f1<2) eed->v2->f1++; + } + } + } + /* find two vertices with eve->f1==1, more or less is wrong */ + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f1==1) { + if(v1==NULL) v1= eve; + else if(v2==NULL) v2= eve; + else { + v1= NULL; + break; + } + } + } + if(v1==NULL || v2==NULL) { + BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too"); + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_CANCELLED; + } + + /* calculate dvec */ + dvec[0]= ( v1->co[0]- v2->co[0] )/steps; + dvec[1]= ( v1->co[1]- v2->co[1] )/steps; + dvec[2]= ( v1->co[2]- v2->co[2] )/steps; + + VECCOPY(nor, obedit->obmat[2]); + + if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) { + dvec[0]= -dvec[0]; + dvec[1]= -dvec[1]; + dvec[2]= -dvec[2]; + } + + if(spin_mesh(C, op, dvec, turns*steps, 360.0f*turns, 0)) { + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected"); + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_CANCELLED; + } +#endif +} + +/* get center and axis, in global coords */ +static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ +#if 0 + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d= ED_view3d_context_rv3d(C); + + RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d)); + RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]); +#endif + return screw_mesh_exec(C, op); +} + +void MESH_OT_screw(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Screw"; + ot->idname= "MESH_OT_screw"; + + /* api callbacks */ + ot->invoke= screw_mesh_invoke; + ot->exec= screw_mesh_exec; + ot->poll= EM_view3d_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /*props */ + RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256); + RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256); + + RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); + RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); +} + +static int region_to_loop(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + EditEdge *eed; + EditFace *efa; + int selected= 0; + + for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0; + + for(efa=em->faces.first; efa; efa=efa->next){ + if(efa->f&SELECT){ + efa->e1->f1++; + efa->e2->f1++; + efa->e3->f1++; + if(efa->e4) + efa->e4->f1++; + + selected= 1; + } + } + + if(!selected) + return OPERATOR_CANCELLED; + + EM_clear_flag_all(em, SELECT); + + for(eed=em->edges.first; eed; eed=eed->next){ + if(eed->f1 == 1) EM_select_edge(eed, 1); + } + + em->selectmode = SCE_SELECT_EDGE; + EM_selectmode_set(em); + + BKE_mesh_end_editmesh(obedit->data, em); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_region_to_loop(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Region to Loop"; + ot->idname= "MESH_OT_region_to_loop"; + + /* api callbacks */ + ot->exec= region_to_loop; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} +static int loop_to_region(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); + + + EditFace *efa; + ListBase allcollections={NULL,NULL}; + Collection *edgecollection; + int testflag; + + build_edgecollection(em, &allcollections); + + for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){ + if(validate_loop(em, edgecollection)){ + testflag = loop_bisect(em, edgecollection); + for(efa=em->faces.first; efa; efa=efa->next){ + if(efa->f1 == testflag){ + if(efa->f&SELECT) EM_select_face(efa, 0); + else EM_select_face(efa,1); + } + } + } + } + + for(efa=em->faces.first; efa; efa=efa->next){ /*fix this*/ + if(efa->f&SELECT) EM_select_face(efa,1); + } + + freecollections(&allcollections); + BKE_mesh_end_editmesh(obedit->data, em); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_loop_to_region(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Loop to Region"; + ot->idname= "MESH_OT_loop_to_region"; + + /* api callbacks */ + ot->exec= loop_to_region; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +int select_by_number_vertices_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + EditFace *efa; + int numverts= RNA_enum_get(op->ptr, "type"); + + /* Selects trias/qiads or isolated verts, and edges that do not have 2 neighboring + * faces + */ + + /* for loose vertices/edges, we first select all, loop below will deselect */ + if(numverts==5) { + EM_set_flag_all(em, SELECT); + } + else if(em->selectmode!=SCE_SELECT_FACE) { + BKE_report(op->reports, RPT_ERROR, "Only works in face selection mode"); + return OPERATOR_CANCELLED; + } + + for(efa= em->faces.first; efa; efa= efa->next) { + if (efa->e4) { + EM_select_face(efa, (numverts==4) ); + } + else { + EM_select_face(efa, (numverts==3) ); + } + } + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_select_by_number_vertices(wmOperatorType *ot) +{ + static const EnumPropertyItem type_items[]= { + {3, "TRIANGLES", 0, "Triangles", NULL}, + {4, "QUADS", 0, "Triangles", NULL}, + {5, "OTHER", 0, "Other", NULL}, + {0, NULL, 0, NULL, NULL}}; + + /* identifiers */ + ot->name= "Select by Number of Vertices"; + ot->description= "Select vertices or faces by vertex count."; + ot->idname= "MESH_OT_select_by_number_vertices"; + + /* api callbacks */ + ot->exec= select_by_number_vertices_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_enum(ot->srna, "type", type_items, 3, "Type", "Type of elements to select."); +} + + +int select_mirror_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + + int extend= RNA_boolean_get(op->ptr, "extend"); + + EM_select_mirrored(obedit, em, extend); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_select_mirror(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Mirror"; + ot->description= "Select mesh items at mirrored locations."; + ot->idname= "MESH_OT_select_mirror"; + + /* api callbacks */ + ot->exec= select_mirror_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection"); +} + +static int select_sharp_edges_exec(bContext *C, wmOperator *op) +{ + /* Find edges that have exactly two neighboring faces, + * check the angle between those faces, and if angle is + * small enough, select the edge + */ +} + +void MESH_OT_edges_select_sharp(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Sharp Edges"; + ot->description= "Marked selected edges as sharp."; + ot->idname= "MESH_OT_edges_select_sharp"; + + /* api callbacks */ + ot->exec= select_sharp_edges_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_float(ot->srna, "sharpness", 0.01f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f); +} + +static int select_linked_flat_faces_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + + select_linked_flat_faces(em, op, RNA_float_get(op->ptr, "sharpness")); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_FINISHED; +#endif +} + +void MESH_OT_faces_select_linked_flat(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Linked Flat Faces"; + ot->description= "Select linked faces by angle."; + ot->idname= "MESH_OT_faces_select_linked_flat"; + + /* api callbacks */ + ot->exec= select_linked_flat_faces_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_float(ot->srna, "sharpness", 0.0f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f); +} + +static int select_non_manifold_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + + select_non_manifold(em, op); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); + return OPERATOR_FINISHED; +#endif +} + +void MESH_OT_select_non_manifold(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Non Manifold"; + ot->description= "Select all non-manifold vertices or edges."; + ot->idname= "MESH_OT_select_non_manifold"; + + /* api callbacks */ + ot->exec= select_non_manifold_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + +static int mesh_select_random_exec(bContext *C, wmOperator *op) +{ +#if 0 + Object *obedit= CTX_data_edit_object(C); + EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); + + if(!RNA_boolean_get(op->ptr, "extend")) + EM_deselect_all(em); + + selectrandom_mesh(em, RNA_float_get(op->ptr, "percent")/100.0f); + + WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); + + BKE_mesh_end_editmesh(obedit->data, em); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_select_random(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Select Random"; + ot->description= "Randomly select vertices."; + ot->idname= "MESH_OT_select_random"; + + /* api callbacks */ + ot->exec= mesh_select_random_exec; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly.", 0.f, 100.0f); + RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first."); +} diff --git a/source/blender/editors/mesh/bmeshutils.c b/source/blender/editors/mesh/bmeshutils.c index fc740b699d4..d0f89eda313 100644 --- a/source/blender/editors/mesh/bmeshutils.c +++ b/source/blender/editors/mesh/bmeshutils.c @@ -118,33 +118,6 @@ void EDBM_stats_update(BMEditMesh *em) } } -/*this function is defunct, dead*/ -void EDBM_Tesselate(EditMesh *em) -{ - EditMesh *em2; - EditFace *efa; - BMesh *bm; - int found=0; - - for (efa=em->faces.first; efa; efa=efa->next) { - if ((efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) || - (efa->e3->h & EM_FGON) || (efa->e4&&(efa->e4->h&EM_FGON))) - { - found = 1; - break; - } - } - - if (found) { - bm = editmesh_to_bmesh(em); - em2 = bmesh_to_editmesh(bm); - set_editMesh(em, em2); - - MEM_freeN(em2); - BM_Free_Mesh(bm); - } -} - int EDBM_InitOpf(BMEditMesh *em, BMOperator *bmop, wmOperator *op, char *fmt, ...) { BMesh *bm = em->bm; @@ -228,6 +201,32 @@ int EDBM_CallOpf(BMEditMesh *em, wmOperator *op, char *fmt, ...) return EDBM_FinishOp(em, &bmop, op, 1); } +int EDBM_CallAndSelectOpf(BMEditMesh *em, wmOperator *op, char *selectslot, char *fmt, ...) +{ + BMesh *bm = em->bm; + BMOperator bmop; + va_list list; + + va_start(list, fmt); + + if (!BMO_VInitOpf(bm, &bmop, fmt, list)) { + BKE_report(op->reports, RPT_ERROR, + "Parse error in EDBM_CallOpf"); + va_end(list); + return 0; + } + + if (!em->emcopy) + em->emcopy = BMEdit_Copy(em); + em->emcopyusers++; + + BMO_Exec_Op(bm, &bmop); + BMO_HeaderFlag_Buffer(em->bm, &bmop, selectslot, BM_SELECT, BM_ALL); + + va_end(list); + return EDBM_FinishOp(em, &bmop, op, 1); +} + int EDBM_CallOpfSilent(BMEditMesh *em, char *fmt, ...) { BMesh *bm = em->bm; @@ -258,12 +257,10 @@ void EDBM_MakeEditBMesh(ToolSettings *ts, Scene *scene, Object *ob) BMesh *bm; if (!me->mpoly && me->totface) { - printf("yeek!! bmesh conversion issue! may lose shapekeys!\n"); - - em = make_editMesh(scene, ob); - bm = editmesh_to_bmesh(em); - - free_editMesh(em); + printf("yeek!! bmesh conversion issue! may lose lots of geometry!\n"); + + /*BMESH_TODO need to write smarter code here*/ + bm = BKE_mesh_to_bmesh(me, ob); } else { bm = BKE_mesh_to_bmesh(me, ob); } @@ -788,7 +785,8 @@ MTexPoly *EDBM_get_active_mtexpoly(BMEditMesh *em, BMFace **act_efa, int sloppy) int EDBM_texFaceCheck(BMEditMesh *em) { /* some of these checks could be a touch overkill */ - return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY); + return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) && + CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL); } int EDBM_vertColorCheck(BMEditMesh *em) diff --git a/source/blender/editors/mesh/editbmesh_add.c b/source/blender/editors/mesh/editbmesh_add.c new file mode 100644 index 00000000000..b2631800dd8 --- /dev/null +++ b/source/blender/editors/mesh/editbmesh_add.c @@ -0,0 +1,529 @@ + /* $Id: bmesh_tools.c + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2004 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joseph Eagar + * + * ***** END GPL LICENSE BLOCK ***** + */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <math.h> +#include <float.h> + +#include "MEM_guardedalloc.h" +#include "PIL_time.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_view3d_types.h" +#include "DNA_key_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_types.h" +#include "RNA_define.h" +#include "RNA_access.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_editVert.h" +#include "BLI_rand.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_heap.h" +#include "BLI_array.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" +#include "BKE_bmesh.h" +#include "BKE_report.h" +#include "BKE_tessmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_view3d.h" +#include "ED_util.h" +#include "ED_screen.h" +#include "ED_transform.h" +#include "ED_object.h" + +#include "UI_interface.h" + +#include "mesh_intern.h" +#include "bmesh.h" + +#include "editbmesh_bvh.h" + + +/* uses context to figure out transform for primitive */ +/* returns standard diameter */ +static float new_primitive_matrix(bContext *C, float *loc, float *rot, float primmat[][4]) +{ + Object *obedit= CTX_data_edit_object(C); + View3D *v3d =CTX_wm_view3d(C); + float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3]; + + unit_m4(primmat); + + eul_to_mat3(rmat, rot); + invert_m3(rmat); + + /* inverse transform for initial rotation and object */ + copy_m3_m4(mat, obedit->obmat); + mul_m3_m3m3(cmat, rmat, mat); + invert_m3_m3(imat, cmat); + copy_m4_m3(primmat, imat); + + /* center */ + VECCOPY(primmat[3], loc); + VECSUB(primmat[3], primmat[3], obedit->obmat[3]); + invert_m3_m3(imat, mat); + mul_m3_v3(imat, primmat[3]); + + if(v3d) return v3d->grid; + return 1.0f; +} + +/* ********* add primitive operators ************* */ + +static void make_prim_init(bContext *C, float *dia, float mat[][4], + int *state, float *loc, float *rot) +{ + Object *obedit= CTX_data_edit_object(C); + + *state = 0; + if(obedit==NULL || obedit->type!=OB_MESH) { + obedit= ED_object_add_type(C, OB_MESH, loc, rot, FALSE); + + /* create editmode */ + ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); /* rare cases the active layer is messed up */ + *state = 1; + } + else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA); + + *dia *= new_primitive_matrix(C, loc, rot, mat); +} + +static void make_prim_finish(bContext *C, int *state, int enter_editmode) +{ + Object *obedit = CTX_data_edit_object(C); + + DAG_id_flush_update(obedit->data, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); + + /* userdef */ + if (*state && !enter_editmode) { + ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */ + } + WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); + +} +static int add_primitive_plane_exec(bContext *C, wmOperator *op) +{ + Object *obedit; + Mesh *me; + BMEditMesh *em; + float loc[3], rot[3], mat[4][4], dia; + int enter_editmode; + int state; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + make_prim_init(C, &dia, mat, &state, loc, rot); + + obedit = CTX_data_edit_object(C); + me = obedit->data; + em = me->edit_btmesh; + + if (!EDBM_CallAndSelectOpf(em, op, "vertout", + "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", 1, 1, sqrt(2.0), mat)) + return OPERATOR_CANCELLED; + + /* BMESH_TODO make plane side this: sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */ + make_prim_finish(C, &state, enter_editmode); + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_plane_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Plane"; + ot->description= "Construct a filled planar mesh with 4 vertices."; + ot->idname= "MESH_OT_primitive_plane_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_plane_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + ED_object_add_generic_props(ot, TRUE); +} + +static int add_primitive_cube_exec(bContext *C, wmOperator *op) +{ + Object *obedit; + Mesh *me; + BMEditMesh *em; + float loc[3], rot[3], mat[4][4], dia; + int enter_editmode; + int state; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + + make_prim_init(C, &dia, mat, &state, loc, rot); + + obedit= CTX_data_edit_object(C); + me = obedit->data; + em = me->edit_btmesh; + + if (!EDBM_CallAndSelectOpf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, 2.0f)) + return OPERATOR_CANCELLED; + + /* BMESH_TODO make plane side this: sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */ + make_prim_finish(C, &state, enter_editmode); + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_cube_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Cube"; + ot->description= "Construct a cube mesh."; + ot->idname= "MESH_OT_primitive_cube_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_cube_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + ED_object_add_generic_props(ot, TRUE); +} + +static int add_primitive_circle_exec(bContext *C, wmOperator *op) +{ +#if 0 + int enter_editmode; + float loc[3], rot[3]; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + + make_prim_ext(C, loc, rot, enter_editmode, + PRIM_CIRCLE, RNA_int_get(op->ptr, "vertices"), 0, 0, + RNA_float_get(op->ptr,"radius"), 0.0f, 0, + RNA_boolean_get(op->ptr, "fill")); +#endif + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_circle_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Circle"; + ot->description= "Construct a circle mesh."; + ot->idname= "MESH_OT_primitive_circle_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_circle_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 3, 500); + RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); + RNA_def_boolean(ot->srna, "fill", 0, "Fill", ""); + + ED_object_add_generic_props(ot, TRUE); +} + +static int add_primitive_tube_exec(bContext *C, wmOperator *op) +{ +#if 0 + int enter_editmode; + float loc[3], rot[3]; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + + make_prim_ext(C, loc, rot, enter_editmode, + PRIM_CYLINDER, RNA_int_get(op->ptr, "vertices"), 0, 0, + RNA_float_get(op->ptr, "radius"), + RNA_float_get(op->ptr, "depth"), 1, + RNA_boolean_get(op->ptr, "cap_ends")); +#endif + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_tube_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Tube"; + ot->description= "Construct a tube mesh."; + ot->idname= "MESH_OT_primitive_tube_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_tube_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500); + RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); + RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00); + RNA_def_boolean(ot->srna, "cap_ends", 1, "Cap Ends", ""); + + ED_object_add_generic_props(ot, TRUE); +} + +static int add_primitive_cone_exec(bContext *C, wmOperator *op) +{ +#if 0 + int enter_editmode; + float loc[3], rot[3]; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + + make_prim_ext(C, loc, rot, enter_editmode, + PRIM_CONE, RNA_int_get(op->ptr, "vertices"), 0, 0, + RNA_float_get(op->ptr,"radius"), RNA_float_get(op->ptr, "depth"), + 0, RNA_boolean_get(op->ptr, "cap_end")); +#endif + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_cone_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Cone"; + ot->description= "Construct a conic mesh (ends filled)."; + ot->idname= "MESH_OT_primitive_cone_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_cone_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500); + RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); + RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00); + RNA_def_boolean(ot->srna, "cap_end", 0, "Cap End", ""); + + ED_object_add_generic_props(ot, TRUE); +} + +static int add_primitive_grid_exec(bContext *C, wmOperator *op) +{ +#if 0 + int enter_editmode; + float loc[3], rot[3]; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + + make_prim_ext(C, loc, rot, enter_editmode, + PRIM_GRID, RNA_int_get(op->ptr, "x_subdivisions"), + RNA_int_get(op->ptr, "y_subdivisions"), 0, + RNA_float_get(op->ptr,"size"), 0.0f, 0, 1); +#endif + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_grid_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Grid"; + ot->description= "Construct a grid mesh."; + ot->idname= "MESH_OT_primitive_grid_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_grid_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "x_subdivisions", 10, INT_MIN, INT_MAX, "X Subdivisions", "", 3, 1000); + RNA_def_int(ot->srna, "y_subdivisions", 10, INT_MIN, INT_MAX, "Y Subdivisions", "", 3, 1000); + RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX); + + ED_object_add_generic_props(ot, TRUE); +} + +static int add_primitive_monkey_exec(bContext *C, wmOperator *op) +{ +#if 0 + int enter_editmode; + float loc[3], rot[3]; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + + make_prim_ext(C, loc, rot, enter_editmode, + PRIM_MONKEY, 0, 0, 2, 0.0f, 0.0f, 0, 0); +#endif + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_monkey_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Monkey"; + ot->description= "Construct a Suzanne mesh."; + ot->idname= "MESH_OT_primitive_monkey_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_monkey_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + ED_object_add_generic_props(ot, TRUE); +} + + +static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) +{ + Object *obedit; + Mesh *me; + BMEditMesh *em; + float loc[3], rot[3], mat[4][4], dia; + int enter_editmode; + int state; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + make_prim_init(C, &dia, mat, &state, loc, rot); + + obedit = CTX_data_edit_object(C); + me = obedit->data; + em = me->edit_btmesh; + + if (!EDBM_CallAndSelectOpf(em, op, "vertout", + "create_uvsphere segments=%i revolutions=%i diameter=%f mat=%m4", + RNA_int_get(op->ptr, "rings"), RNA_int_get(op->ptr, "segments"), + RNA_float_get(op->ptr,"size"), mat)) + return OPERATOR_CANCELLED; + + make_prim_finish(C, &state, enter_editmode); + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add UV Sphere"; + ot->description= "Construct a UV sphere mesh."; + ot->idname= "MESH_OT_primitive_uv_sphere_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_uvsphere_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500); + RNA_def_int(ot->srna, "rings", 24, INT_MIN, INT_MAX, "Rings", "", 3, 500); + RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, 100.00); + + ED_object_add_generic_props(ot, TRUE); +} + +static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) +{ +#if 0 + int enter_editmode; + float loc[3], rot[3]; + + ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); + + make_prim_ext(C, loc, rot, enter_editmode, + PRIM_ICOSPHERE, 0, 0, RNA_int_get(op->ptr, "subdivisions"), + RNA_float_get(op->ptr,"size"), 0.0f, 0, 0); +#endif + + return OPERATOR_FINISHED; +} + +void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Ico Sphere"; + ot->description= "Construct an Icosphere mesh."; + ot->idname= "MESH_OT_primitive_ico_sphere_add"; + + /* api callbacks */ + ot->invoke= ED_object_add_generic_invoke; + ot->exec= add_primitive_icosphere_exec; + ot->poll= ED_operator_scene_editable; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* props */ + RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8); + RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00); + + ED_object_add_generic_props(ot, TRUE); +} diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 4fa7a19a1b3..396ba6b0fde 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -61,6 +61,7 @@ #include "BKE_utildefines.h" #include "BKE_customdata.h" #include "BKE_context.h" +#include "BKE_tessmesh.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -94,40 +95,54 @@ void object_facesel_flush_dm(Object *ob) { Mesh *me= get_mesh(ob); DerivedMesh *dm= ob->derivedFinal; - MFace *faces, *mf, *mf_orig; - int *index_array = NULL; + MPoly *faces, *mf, *mf_orig; + DMFaceIter *fiter; + int *index = NULL; int totface; int i; if(me==NULL || dm==NULL) return; - index_array = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + fiter = dm->newFaceIter(dm); + totface = dm->getNumFaces(dm); - if(!index_array) - return; - - faces = dm->getTessFaceArray(dm); - totface = dm->getNumTessFaces(dm); - - mf= faces; - - for (i= 0; i<totface; i++, mf++) { /* loop over derived mesh faces */ - mf_orig= me->mface + index_array[i]; - mf->flag= mf_orig->flag;; + for (i=0; !fiter->done; fiter->step(fiter), i++) { + index = fiter->getCDData(fiter, CD_ORIGINDEX, -1); + if (!index) { + fiter->free(fiter); + return; + } + + mf_orig = me->mpoly + *index; + fiter->flags = mf_orig->flag; } + + fiter->free(fiter); } /* returns 0 if not found, otherwise 1 */ -int facesel_face_pick(struct bContext *C, Mesh *me, short *mval, unsigned int *index, short rect) +int facesel_face_pick(struct bContext *C, Mesh *me, Object *ob, + short *mval, unsigned int *index, short rect) { + Scene *scene = CTX_data_scene(C); ViewContext vc; view3d_set_viewcontext(C, &vc); - if (!me || me->totface==0) + if (!me || me->totpoly==0) return 0; -// XXX if (v3d->flag & V3D_INVALID_BACKBUF) { + /*we can't assume mfaces have a correct origindex layer that indices to mpolys. + so instead we have to regenerate the tesselation faces altogether. + + the final 0, 0 paramters causes it to use the index of each mpoly, instead + of reading from the origindex layer.*/ + me->totface = mesh_recalcTesselation(&me->fdata, &me->ldata, &me->pdata, + me->mvert, me->totface, me->totloop, me->totpoly, 0, 0); + mesh_update_customdata_pointers(me); + makeDerivedMesh(scene, ob, NULL, CD_MASK_BAREMESH); + + // XXX if (v3d->flag & V3D_INVALID_BACKBUF) { // XXX drawview.c! check_backbuf(); // XXX persp(PERSP_VIEW); // XXX } @@ -144,7 +159,7 @@ int facesel_face_pick(struct bContext *C, Mesh *me, short *mval, unsigned int *i *index = view3d_sample_backbuf(&vc, mval[0], mval[1]); } - if ((*index)<=0 || (*index)>(unsigned int)me->totface) + if ((*index)<=0 || (*index)>(unsigned int)me->totpoly) return 0; (*index)--; @@ -154,41 +169,37 @@ int facesel_face_pick(struct bContext *C, Mesh *me, short *mval, unsigned int *i /* last_sel, use em->act_face otherwise get the last selected face in the editselections * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */ -MTFace *EM_get_active_mtface(EditMesh *em, EditFace **act_efa, MCol **mcol, int sloppy) +MTexPoly *EDBM_get_active_mtface(BMEditMesh *em, BMFace **act_efa, int sloppy) { - EditFace *efa = NULL; + BMFace *efa = NULL; + BMLoop *l; + BMIter iter, liter; - if(!EM_texFaceCheck(em)) + if(!EDBM_texFaceCheck(em)) return NULL; - efa = EM_get_actFace(em, sloppy); + efa = EDBM_get_actFace(em, sloppy); if (efa) { - if (mcol) { - if (CustomData_has_layer(&em->fdata, CD_MCOL)) - *mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - else - *mcol = NULL; - } if (act_efa) *act_efa = efa; - return CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); } + if (act_efa) *act_efa= NULL; - if(mcol) *mcol = NULL; return NULL; } void reveal_tface(Scene *scene) { Mesh *me; - MFace *mface; + MPoly *mface; int a; me= get_mesh(OBACT); - if(me==0 || me->totface==0) return; + if(me==0 || me->totpoly==0) return; - mface= me->mface; - a= me->totface; + mface= me->mpoly; + a= me->totpoly; while(a--) { if(mface->flag & ME_HIDE) { mface->flag |= ME_FACE_SEL; @@ -204,20 +215,20 @@ void reveal_tface(Scene *scene) void hide_tface(Scene *scene) { Mesh *me; - MFace *mface; + MPoly *mface; int a; int shift=0, alt= 0; // XXX me= get_mesh(OBACT); - if(me==0 || me->totface==0) return; + if(me==0 || me->totpoly==0) return; if(alt) { reveal_tface(scene); return; } - mface= me->mface; - a= me->totface; + mface= me->mpoly; + a= me->totpoly; while(a--) { if(mface->flag & ME_HIDE); else { @@ -239,30 +250,30 @@ void hide_tface(Scene *scene) /* Set tface seams based on edge data, uses hash table to find seam edges. */ -static void hash_add_face(EdgeHash *ehash, MFace *mf) +static void hash_add_face(EdgeHash *ehash, MPoly *mf, MLoop *mloop) { - BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); - BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); - if(mf->v4) { - BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); - BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); - } - else - BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); + MLoop *ml, *ml2; + int i; + + for (i=0, ml=mloop; i<mf->totloop; i++, ml++) { + ml2 = mloop + (i+1) % mf->totloop; + BLI_edgehash_insert(ehash, ml->v, ml2->v, NULL); + } } void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) { - MFace *mf; - int a, doit=1, mark=0; - char *linkflag; EdgeHash *ehash, *seamhash; + MPoly *mf; + MLoop *ml; MEdge *med; + char *linkflag; + int a, b, doit=1, mark=0; ehash= BLI_edgehash_new(); seamhash = BLI_edgehash_new(); - linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv"); + linkflag= MEM_callocN(sizeof(char)*me->totpoly, "linkflaguv"); for(med=me->medge, a=0; a < me->totedge; a++, med++) if(med->flag & ME_SEAM) @@ -270,17 +281,17 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) if (mode==0 || mode==1) { /* only put face under cursor in array */ - mf= ((MFace*)me->mface) + index; - hash_add_face(ehash, mf); + mf= ((MPoly*)me->mpoly) + index; + hash_add_face(ehash, mf, me->mloop + mf->loopstart); linkflag[index]= 1; } else { /* fill array by selection */ - mf= me->mface; - for(a=0; a<me->totface; a++, mf++) { + mf= me->mpoly; + for(a=0; a<me->totpoly; a++, mf++) { if(mf->flag & ME_HIDE); else if(mf->flag & ME_FACE_SEL) { - hash_add_face(ehash, mf); + hash_add_face(ehash, mf, me->mloop + mf->loopstart); linkflag[a]= 1; } } @@ -290,35 +301,26 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) doit= 0; /* expand selection */ - mf= me->mface; - for(a=0; a<me->totface; a++, mf++) { + mf= me->mpoly; + for(a=0; a<me->totpoly; a++, mf++) { if(mf->flag & ME_HIDE) continue; if(!linkflag[a]) { + MLoop *mnextl; mark= 0; - if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2)) - if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) - mark= 1; - if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3)) - if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) - mark= 1; - if(mf->v4) { - if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4)) - if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) - mark= 1; - if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1)) - if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) - mark= 1; + ml = me->mloop + mf->loopstart; + for (b=0; b<mf->totloop; b++, ml++) { + mnextl = b < mf->totloop-1 ? ml - 1 : me->mloop + mf->loopstart; + if (!BLI_edgehash_haskey(seamhash, ml->v, mnextl->v)) + if (!BLI_edgehash_haskey(ehash, ml->v, mnextl->v)) + mark = 1; } - else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1)) - if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) - mark = 1; if(mark) { linkflag[a]= 1; - hash_add_face(ehash, mf); + hash_add_face(ehash, mf, me->mloop + mf->loopstart); doit= 1; } } @@ -330,24 +332,24 @@ void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) BLI_edgehash_free(seamhash, NULL); if(mode==0 || mode==2) { - for(a=0, mf=me->mface; a<me->totface; a++, mf++) + for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++) if(linkflag[a]) mf->flag |= ME_FACE_SEL; else mf->flag &= ~ME_FACE_SEL; } else if(mode==1) { - for(a=0, mf=me->mface; a<me->totface; a++, mf++) + for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++) if(linkflag[a] && (mf->flag & ME_FACE_SEL)) break; - if (a<me->totface) { - for(a=0, mf=me->mface; a<me->totface; a++, mf++) + if (a<me->totpoly) { + for(a=0, mf=me->mpoly; a<me->totpoly; a++, mf++) if(linkflag[a]) mf->flag &= ~ME_FACE_SEL; } else { - for(a=0, mf=me->mface; a<me->totface; a++, mf++) + for(a=0, mf=me->mface; a<me->totpoly; a++, mf++) if(linkflag[a]) mf->flag |= ME_FACE_SEL; } @@ -365,7 +367,7 @@ void select_linked_tfaces(bContext *C, Object *ob, short mval[2], int mode) unsigned int index=0; me = get_mesh(ob); - if(me==0 || me->totface==0) return; + if(me==0 || me->totpoly==0) return; if (mode==0 || mode==1) { // XXX - Causes glitches, not sure why @@ -383,7 +385,7 @@ void select_linked_tfaces(bContext *C, Object *ob, short mval[2], int mode) void selectall_tface(Object *ob, int action) { Mesh *me; - MFace *mface; + MPoly *mface; int a; me= get_mesh(ob); @@ -392,8 +394,8 @@ void selectall_tface(Object *ob, int action) if (action == SEL_TOGGLE) { action = SEL_SELECT; - mface= me->mface; - a= me->totface; + mface= me->mpoly; + a= me->totpoly; while(a--) { if((mface->flag & ME_HIDE) == 0 && mface->flag & ME_FACE_SEL) { action = SEL_DESELECT; @@ -403,8 +405,8 @@ void selectall_tface(Object *ob, int action) } } - mface= me->mface; - a= me->totface; + mface= me->mpoly; + a= me->totpoly; while(a--) { if((mface->flag & ME_HIDE) == 0) { switch (action) { @@ -429,14 +431,14 @@ void selectall_tface(Object *ob, int action) void selectswap_tface(Scene *scene) { Mesh *me; - MFace *mface; + MPoly *mface; int a; me= get_mesh(OBACT); if(me==0) return; - mface= me->mface; - a= me->totface; + mface= me->mpoly; + a= me->totpoly; while(a--) { if(mface->flag & ME_HIDE); else { @@ -454,49 +456,39 @@ int minmax_tface(Scene *scene, float *min, float *max) { Object *ob; Mesh *me; - MFace *mf; - MTFace *tf; + MPoly *mf; + MTexPoly *tf; + MLoop *ml; MVert *mv; - int a, ok=0; + int a, b, ok=0; float vec[3], bmat[3][3]; ob = OBACT; if (ob==0) return ok; + me= get_mesh(ob); - if(me==0 || me->mtface==0) return ok; + if(!me || !me->mtpoly) return ok; copy_m3_m4(bmat, ob->obmat); mv= me->mvert; - mf= me->mface; - tf= me->mtface; - for (a=me->totface; a>0; a--, mf++, tf++) { + mf= me->mpoly; + tf= me->mtpoly; + for (a=me->totpoly; a>0; a--, mf++, tf++) { if (mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL)) continue; - VECCOPY(vec, (mv+mf->v1)->co); - mul_m3_v3(bmat, vec); - add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); - - VECCOPY(vec, (mv+mf->v2)->co); - mul_m3_v3(bmat, vec); - add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); - - VECCOPY(vec, (mv+mf->v3)->co); - mul_m3_v3(bmat, vec); - add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); - - if (mf->v4) { - VECCOPY(vec, (mv+mf->v4)->co); + ml = me->mloop + mf->totloop; + for (b=0; b<mf->totloop; b++, ml++) { + VECCOPY(vec, (mv+ml->v)->co); mul_m3_v3(bmat, vec); add_v3_v3v3(vec, vec, ob->obmat[3]); - DO_MINMAX(vec, min, max); + DO_MINMAX(vec, min, max); } + ok= 1; } + return ok; } @@ -504,12 +496,12 @@ int minmax_tface(Scene *scene, float *min, float *max) #define ME_SEAM_DONE 2 /* reuse this flag */ -static float edgetag_cut_cost(EditMesh *em, int e1, int e2, int vert) +static float edgetag_cut_cost(BMEditMesh *em, int e1, int e2, int vert) { - EditVert *v = EM_get_vert_for_index(vert); - EditEdge *eed1 = EM_get_edge_for_index(e1), *eed2 = EM_get_edge_for_index(e2); - EditVert *v1 = EM_get_vert_for_index( (eed1->v1->tmp.l == vert)? eed1->v2->tmp.l: eed1->v1->tmp.l ); - EditVert *v2 = EM_get_vert_for_index( (eed2->v1->tmp.l == vert)? eed2->v2->tmp.l: eed2->v1->tmp.l ); + BMVert *v = EDBM_get_vert_for_index(em, vert); + BMEdge *eed1 = EDBM_get_edge_for_index(em, e1), *eed2 = EDBM_get_edge_for_index(em, e2); + BMVert *v1 = EDBM_get_vert_for_index(em, (BMINDEX_GET(eed1->v1) == vert)? BMINDEX_GET(eed1->v2): BMINDEX_GET(eed1->v1) ); + BMVert *v2 = EDBM_get_vert_for_index(em, (BMINDEX_GET(eed2->v1) == vert)? BMINDEX_GET(eed2->v2): BMINDEX_GET(eed2->v1) ); float cost, d1[3], d2[3]; cost = len_v3v3(v1->co, v->co); @@ -523,16 +515,17 @@ static float edgetag_cut_cost(EditMesh *em, int e1, int e2, int vert) return cost; } -static void edgetag_add_adjacent(EditMesh *em, Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost) +static void edgetag_add_adjacent(BMEditMesh *em, Heap *heap, int mednum, int vertnum, + int *nedges, int *edges, int *prevedge, float *cost) { int startadj, endadj = nedges[vertnum+1]; for (startadj = nedges[vertnum]; startadj < endadj; startadj++) { int adjnum = edges[startadj]; - EditEdge *eedadj = EM_get_edge_for_index(adjnum); + BMEdge *eedadj = EDBM_get_edge_for_index(em, adjnum); float newcost; - if (eedadj->f2 & ME_SEAM_DONE) + if (eedadj->head.eflag2 & ME_SEAM_DONE) continue; newcost = cost[mednum] + edgetag_cut_cost(em, mednum, adjnum, vertnum); @@ -545,20 +538,20 @@ static void edgetag_add_adjacent(EditMesh *em, Heap *heap, int mednum, int vertn } } -void edgetag_context_set(Scene *scene, EditEdge *eed, int val) +void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *eed, int val) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - EM_select_edge(eed, val); + BM_Select(em->bm, eed, val); break; case EDGE_MODE_TAG_SEAM: - if (val) {eed->seam = 255;} - else {eed->seam = 0;} + if (val) {BM_SetHFlag(eed, BM_SEAM);} + else {BM_ClearHFlag(eed, BM_SEAM);} break; case EDGE_MODE_TAG_SHARP: - if (val) {eed->sharp = 1;} - else {eed->sharp = 0;} + if (val) {BM_SetHFlag(eed, BM_SEAM);} + else {BM_ClearHFlag(eed, BM_SEAM);} break; case EDGE_MODE_TAG_CREASE: if (val) {eed->crease = 1.0f;} @@ -571,15 +564,15 @@ void edgetag_context_set(Scene *scene, EditEdge *eed, int val) } } -int edgetag_context_check(Scene *scene, EditEdge *eed) +int edgetag_context_check(Scene *scene, BMEdge *eed) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - return (eed->f & SELECT) ? 1 : 0; + return BM_TestHFlag(eed, BM_SELECT) ? 1 : 0; case EDGE_MODE_TAG_SEAM: - return eed->seam ? 1 : 0; + return BM_TestHFlag(eed, BM_SEAM); case EDGE_MODE_TAG_SHARP: - return eed->sharp ? 1 : 0; + return BM_TestHFlag(eed, BM_SHARP); case EDGE_MODE_TAG_CREASE: return eed->crease ? 1 : 0; case EDGE_MODE_TAG_BEVEL: @@ -589,28 +582,29 @@ int edgetag_context_check(Scene *scene, EditEdge *eed) } -int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target) +int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, BMEdge *target) { - EditEdge *eed; - EditVert *ev; - + BMEdge *eed; + BMVert *ev; + BMIter iter; Heap *heap; float *cost; int a, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; /* we need the vert */ - for (ev= em->verts.first, totvert=0; ev; ev= ev->next) { - ev->tmp.l = totvert; + BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + BMINDEX_SET(ev, totvert); totvert++; } - for (eed= em->edges.first; eed; eed = eed->next) { - eed->f2 = 0; - if (eed->h) { - eed->f2 |= ME_SEAM_DONE; + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + eed->head.eflag2 = 0; + if (BM_TestHFlag(eed, BM_SELECT)) { + eed->head.eflag2 |= ME_SEAM_DONE; } - eed->tmp.l = totedge; + + BMINDEX_SET(eed, totedge); totedge++; } @@ -621,9 +615,9 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge cost = MEM_mallocN(sizeof(*cost)*totedge, "SeamPathCost"); /* count edges, compute adjacent edges offsets and fill adjacent edges */ - for (eed= em->edges.first; eed; eed = eed->next) { - nedges[eed->v1->tmp.l+1]++; - nedges[eed->v2->tmp.l+1]++; + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + nedges[BMINDEX_GET(eed->v1)+1]++; + nedges[BMINDEX_GET(eed->v2)+1]++; } for (a=1; a<totvert; a++) { @@ -633,107 +627,108 @@ int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge } nedges[0] = nedges[1] = 0; - for (a=0, eed= em->edges.first; eed; a++, eed = eed->next) { - edges[nedges[eed->v1->tmp.l+1]++] = a; - edges[nedges[eed->v2->tmp.l+1]++] = a; + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + edges[nedges[BMINDEX_GET(eed->v1)+1]++] = a; + edges[nedges[BMINDEX_GET(eed->v2)+1]++] = a; cost[a] = 1e20f; prevedge[a] = -1; + a++; } /* regular dijkstra shortest path, but over edges instead of vertices */ heap = BLI_heap_new(); - BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(source->tmp.l)); - cost[source->tmp.l] = 0.0f; - - EM_init_index_arrays(em, 1, 1, 0); + BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(BMINDEX_GET(source))); + cost[BMINDEX_GET(source)] = 0.0f; + EDBM_init_index_arrays(em, 1, 1, 0); while (!BLI_heap_empty(heap)) { mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); - eed = EM_get_edge_for_index( mednum ); + eed = EDBM_get_edge_for_index(em, mednum); - if (mednum == target->tmp.l) + if (mednum == BMINDEX_GET(target)) break; - if (eed->f2 & ME_SEAM_DONE) + if (eed->head.eflag2 & ME_SEAM_DONE) continue; - eed->f2 |= ME_SEAM_DONE; + eed->head.eflag2 |= ME_SEAM_DONE; - edgetag_add_adjacent(em, heap, mednum, eed->v1->tmp.l, nedges, edges, prevedge, cost); - edgetag_add_adjacent(em, heap, mednum, eed->v2->tmp.l, nedges, edges, prevedge, cost); + edgetag_add_adjacent(em, heap, mednum, BMINDEX_GET(eed->v1), nedges, edges, prevedge, cost); + edgetag_add_adjacent(em, heap, mednum, BMINDEX_GET(eed->v2), nedges, edges, prevedge, cost); } - MEM_freeN(nedges); MEM_freeN(edges); MEM_freeN(cost); BLI_heap_free(heap, NULL); - for (eed= em->edges.first; eed; eed = eed->next) { - eed->f2 &= ~ME_SEAM_DONE; + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + eed->head.eflag2 &= ~ME_SEAM_DONE; } - if (mednum != target->tmp.l) { + if (mednum != BMINDEX_GET(target)) { MEM_freeN(prevedge); - EM_free_index_arrays(); + EDBM_free_index_arrays(em); return 0; } /* follow path back to source and mark as seam */ - if (mednum == target->tmp.l) { + if (mednum == BMINDEX_GET(target)) { short allseams = 1; - mednum = target->tmp.l; + mednum = BMINDEX_GET(target); do { - eed = EM_get_edge_for_index( mednum ); + eed = EDBM_get_edge_for_index(eed, mednum); if (!edgetag_context_check(scene, eed)) { allseams = 0; break; } mednum = prevedge[mednum]; - } while (mednum != source->tmp.l); + } while (mednum != BMINDEX_GET(source)); - mednum = target->tmp.l; + mednum = BMINDEX_GET(target); do { - eed = EM_get_edge_for_index( mednum ); + eed = EDBM_get_edge_for_index(em, mednum); if (allseams) - edgetag_context_set(scene, eed, 0); + edgetag_context_set(em, scene, eed, 0); else - edgetag_context_set(scene, eed, 1); + edgetag_context_set(em, scene, eed, 1); mednum = prevedge[mednum]; } while (mednum != -1); } MEM_freeN(prevedge); - EM_free_index_arrays(); + EDBM_free_index_arrays(em); return 1; } /* *************************************** */ -static void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf) +static void seam_edgehash_insert_face(EdgeHash *ehash, MPoly *mf, MLoop *loopstart) { - BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); - BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); - if (mf->v4) { - BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); - BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); - } - else - BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); + MLoop *ml1, *ml2; + int a; + + for (a=0; a<mf->totloop; a++) { + ml1 = loopstart + a; + ml2 = loopstart + (a+1) % mf->totloop; + + BLI_edgehash_insert(ehash, ml1->v, ml2->v, NULL); + } } void seam_mark_clear_tface(Scene *scene, short mode) { Mesh *me; - MFace *mf; + MPoly *mf; + MLoop *ml1, *ml2; MEdge *med; - int a; + int a, b; me= get_mesh(OBACT); - if(me==0 || me->totface==0) return; + if(me==0 || me->totpoly==0) return; if (mode == 0) mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2"); @@ -744,9 +739,9 @@ void seam_mark_clear_tface(Scene *scene, short mode) if (mode == 2) { EdgeHash *ehash = BLI_edgehash_new(); - for (a=0, mf=me->mface; a<me->totface; a++, mf++) + for (a=0, mf=me->mpoly; a<me->totpoly; a++, mf++) if (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL)) - seam_edgehash_insert_face(ehash, mf); + seam_edgehash_insert_face(ehash, mf, me->mloop + mf->loopstart); for (a=0, med=me->medge; a<me->totedge; a++, med++) if (BLI_edgehash_haskey(ehash, med->v1, med->v2)) @@ -759,11 +754,11 @@ void seam_mark_clear_tface(Scene *scene, short mode) EdgeHash *ehash1 = BLI_edgehash_new(); EdgeHash *ehash2 = BLI_edgehash_new(); - for (a=0, mf=me->mface; a<me->totface; a++, mf++) { + for (a=0, mf=me->mpoly; a<me->totpoly; a++, mf++) { if ((mf->flag & ME_HIDE) || !(mf->flag & ME_FACE_SEL)) - seam_edgehash_insert_face(ehash1, mf); + seam_edgehash_insert_face(ehash1, mf, me->mloop + mf->loopstart); else - seam_edgehash_insert_face(ehash2, mf); + seam_edgehash_insert_face(ehash2, mf, me->mloop + mf->loopstart); } for (a=0, med=me->medge; a<me->totedge; a++, med++) @@ -786,21 +781,24 @@ void seam_mark_clear_tface(Scene *scene, short mode) int face_select(struct bContext *C, Object *ob, short mval[2], int extend) { Mesh *me; - MFace *mface, *msel; + MPoly *mface, *msel; unsigned int a, index; /* Get the face under the cursor */ me = get_mesh(ob); - if (!facesel_face_pick(C, me, mval, &index, 1)) + if (!facesel_face_pick(C, me, ob, mval, &index, 1)) return 0; - msel= (((MFace*)me->mface)+index); + if (index >= me->totpoly || index < 0) + return 0; + + msel= me->mpoly + index; if (msel->flag & ME_HIDE) return 0; /* clear flags */ - mface = me->mface; - a = me->totface; + mface = me->mpoly; + a = me->totpoly; if (!extend) { while (a--) { mface->flag &= ~ME_FACE_SEL; @@ -830,28 +828,28 @@ int face_select(struct bContext *C, Object *ob, short mval[2], int extend) void face_borderselect(struct bContext *C, Object *ob, rcti *rect, int select, int extend) { Mesh *me; - MFace *mface; + MPoly *mface; struct ImBuf *ibuf; unsigned int *rt; - int a, sx, sy, index; char *selar; + int a, sx, sy, index; ViewContext vc; view3d_set_viewcontext(C, &vc); me= get_mesh(ob); if(me==0) return; - if(me->totface==0) return; + if(me->totpoly==0) return; - selar= MEM_callocN(me->totface+1, "selar"); + selar= MEM_callocN(me->totpoly+1, "selar"); sx= (rect->xmax-rect->xmin+1); sy= (rect->ymax-rect->ymin+1); if(sx*sy<=0) return; if (extend == 0 && select) { - mface= me->mface; - for(a=1; a<=me->totface; a++, mface++) { + mface= me->mpoly; + for(a=1; a<=me->totpoly; a++, mface++) { if((mface->flag & ME_HIDE) == 0) mface->flag &= ~ME_FACE_SEL; } @@ -873,8 +871,8 @@ void face_borderselect(struct bContext *C, Object *ob, rcti *rect, int select, i rt++; } - mface= me->mface; - for(a=1; a<=me->totface; a++, mface++) { + mface= me->mpoly; + for(a=1; a<=me->totpoly; a++, mface++) { if(selar[a]) { if(mface->flag & ME_HIDE); else { diff --git a/source/blender/editors/mesh/editmesh.c b/source/blender/editors/mesh/editmesh.c deleted file mode 100644 index 0b6c589a59c..00000000000 --- a/source/blender/editors/mesh/editmesh.c +++ /dev/null @@ -1,1622 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * Contributor(s): Blender Foundation, full recode 2002-2008 - * - * ***** END GPL LICENSE BLOCK ***** - */ - - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - -#include "PIL_time.h" - -#include "DNA_customdata_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_object_force.h" -#include "DNA_screen_types.h" -#include "DNA_key_types.h" -#include "DNA_scene_types.h" -#include "DNA_view3d_types.h" -#include "DNA_material_types.h" -#include "DNA_modifier_types.h" -#include "DNA_texture_types.h" -#include "DNA_userdef_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_editVert.h" -#include "BLI_dynstr.h" -#include "BLI_rand.h" -#include "BLI_mempool.h" - -#include "BKE_cloth.h" -#include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_depsgraph.h" -#include "BKE_DerivedMesh.h" -#include "BKE_global.h" -#include "BKE_key.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_material.h" -#include "BKE_mesh.h" -#include "BKE_modifier.h" -#include "BKE_object.h" -#include "BKE_paint.h" -#include "BKE_pointcache.h" -#include "BKE_softbody.h" -#include "BKE_texture.h" -#include "BKE_utildefines.h" -#include "BKE_tessmesh.h" - -#include "LBM_fluidsim.h" - - -#include "ED_mesh.h" -#include "ED_object.h" -#include "ED_retopo.h" -#include "ED_screen.h" -#include "ED_util.h" -#include "ED_view3d.h" - -#include "RNA_access.h" -#include "RNA_define.h" - -#include "WM_api.h" -#include "WM_types.h" - -/* own include */ -#include "mesh_intern.h" - -#include "bmesh.h" - -/* -editmesh.c: - - add/alloc/free data - - hashtables - - enter/exit editmode -*/ - -/* XXX */ -static void BIF_undo_push() {} -static void error() {} - - -/* ***************** HASH ********************* */ - - -#define EDHASHSIZE (512*512) -#define EDHASH(a, b) (a % EDHASHSIZE) - - -/* ************ ADD / REMOVE / FIND ****************** */ - -static void init_editMesh(EditMesh *em) { - if (!em->vertpool) em->vertpool = BLI_mempool_create(sizeof(EditVert), 1, 512); - if (!em->edgepool) em->edgepool = BLI_mempool_create(sizeof(EditEdge), 1, 512); - if (!em->facepool) em->facepool = BLI_mempool_create(sizeof(EditFace), 1, 512); -} - -EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example) -{ - EditVert *eve; - static int hashnr= 0; - - if (!em->vertpool) init_editMesh(em); - - eve= BLI_mempool_calloc(em->vertpool); - - BLI_addtail(&em->verts, eve); - em->totvert++; - - if(vec) VECCOPY(eve->co, vec); - - eve->hash= hashnr++; - if( hashnr>=EDHASHSIZE) hashnr= 0; - - /* new verts get keyindex of -1 since they did not - * have a pre-editmode vertex order - */ - eve->keyindex = -1; - - if(example) { - CustomData_em_copy_data(&em->vdata, &em->vdata, example->data, &eve->data); - eve->bweight = example->bweight; - } - else { - CustomData_em_set_default(&em->vdata, &eve->data); - } - - return eve; -} - -void free_editvert (EditMesh *em, EditVert *eve) -{ - - EM_remove_selection(em, eve, EDITVERT); - CustomData_em_free_block(&em->vdata, &eve->data); - BLI_mempool_free(em->vertpool, eve); - - em->totvert--; -} - - -EditEdge *findedgelist(EditMesh *em, EditVert *v1, EditVert *v2) -{ - EditVert *v3; - struct HashEdge *he; - - /* swap ? */ - if( v1 > v2) { - v3= v2; - v2= v1; - v1= v3; - } - - if(em->hashedgetab==NULL) - em->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab"); - - he= em->hashedgetab + EDHASH(v1->hash, v2->hash); - - while(he) { - - if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed; - - he= he->next; - } - return 0; -} - -static void insert_hashedge(EditMesh *em, EditEdge *eed) -{ - /* assuming that eed is not in the list yet, and that a find has been done before */ - - struct HashEdge *first, *he; - - first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); - - if( first->eed==0 ) { - first->eed= eed; - } - else { - he= &eed->hash; - he->eed= eed; - he->next= first->next; - first->next= he; - } -} - -static void remove_hashedge(EditMesh *em, EditEdge *eed) -{ - /* assuming eed is in the list */ - - struct HashEdge *first, *he, *prev=NULL; - - he=first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash); - - while(he) { - if(he->eed == eed) { - /* remove from list */ - if(he==first) { - if(first->next) { - he= first->next; - first->eed= he->eed; - first->next= he->next; - } - else he->eed= 0; - } - else { - prev->next= he->next; - } - return; - } - prev= he; - he= he->next; - } -} - -EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *example) -{ - EditVert *v3; - EditEdge *eed; - int swap= 0; - - if(v1==v2) return NULL; - if(v1==NULL || v2==NULL) return NULL; - - /* swap ? */ - if(v1>v2) { - v3= v2; - v2= v1; - v1= v3; - swap= 1; - } - - /* find in hashlist */ - if (!em->edgepool) init_editMesh(em); - eed= findedgelist(em, v1, v2); - - if(eed==NULL) { - - eed= (EditEdge *)BLI_mempool_calloc(em->edgepool); - eed->v1= v1; - eed->v2= v2; - BLI_addtail(&em->edges, eed); - eed->dir= swap; - insert_hashedge(em, eed); - em->totedge++; - - /* copy edge data: - rule is to do this with addedgelist call, before addfacelist */ - if(example) { - eed->crease= example->crease; - eed->bweight= example->bweight; - eed->sharp = example->sharp; - eed->seam = example->seam; - eed->h |= (example->h & EM_FGON); - } - } - - return eed; -} - -void remedge(EditMesh *em, EditEdge *eed) -{ - BLI_remlink(&em->edges, eed); - remove_hashedge(em, eed); - - em->totedge--; -} - -void free_editedge(EditMesh *em, EditEdge *eed) -{ - EM_remove_selection(em, eed, EDITEDGE); - - BLI_mempool_free(em->edgepool, eed); -} - -void free_editface(EditMesh *em, EditFace *efa) -{ - EM_remove_selection(em, efa, EDITFACE); - - if (em->act_face==efa) { - EM_set_actFace(em, em->faces.first == efa ? NULL : em->faces.first); - } - - CustomData_em_free_block(&em->fdata, &efa->data); - BLI_mempool_free(em->facepool, efa); - - em->totface--; -} - -void free_vertlist(EditMesh *em, ListBase *edve) -{ - EditVert *eve, *next; - - if (!edve) return; - - eve= edve->first; - while(eve) { - next= eve->next; - free_editvert(em, eve); - eve= next; - } - edve->first= edve->last= NULL; - em->totvert= em->totvertsel= 0; -} - -void free_edgelist(EditMesh *em, ListBase *lb) -{ - EditEdge *eed, *next; - - eed= lb->first; - while(eed) { - next= eed->next; - free_editedge(em, eed); - eed= next; - } - lb->first= lb->last= NULL; - em->totedge= em->totedgesel= 0; -} - -void free_facelist(EditMesh *em, ListBase *lb) -{ - EditFace *efa, *next; - - efa= lb->first; - while(efa) { - next= efa->next; - free_editface(em, efa); - efa= next; - } - lb->first= lb->last= NULL; - em->totface= em->totfacesel= 0; -} - -EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges) -{ - EditFace *efa; - EditEdge *e1, *e2=0, *e3=0, *e4=0; - - /* added sanity check... seems to happen for some tools, or for enter editmode for corrupted meshes */ - if(v1==v4 || v2==v4 || v3==v4) v4= NULL; - - /* add face to list and do the edges */ - if(exampleEdges) { - e1= addedgelist(em, v1, v2, exampleEdges->e1); - e2= addedgelist(em, v2, v3, exampleEdges->e2); - if(v4) e3= addedgelist(em, v3, v4, exampleEdges->e3); - else e3= addedgelist(em, v3, v1, exampleEdges->e3); - if(v4) e4= addedgelist(em, v4, v1, exampleEdges->e4); - } - else { - e1= addedgelist(em, v1, v2, NULL); - e2= addedgelist(em, v2, v3, NULL); - if(v4) e3= addedgelist(em, v3, v4, NULL); - else e3= addedgelist(em, v3, v1, NULL); - if(v4) e4= addedgelist(em, v4, v1, NULL); - } - - if(v1==v2 || v2==v3 || v1==v3) return NULL; - if(e2==0) return NULL; - - if (!em->facepool) init_editMesh(em); - efa= (EditFace *)BLI_mempool_calloc(em->facepool); - - efa->v1= v1; - efa->v2= v2; - efa->v3= v3; - efa->v4= v4; - - efa->e1= e1; - efa->e2= e2; - efa->e3= e3; - efa->e4= e4; - - if(example) { - efa->mat_nr= example->mat_nr; - efa->flag= example->flag; - CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data); - } - else { - efa->mat_nr= em->mat_nr; - - CustomData_em_set_default(&em->fdata, &efa->data); - } - - BLI_addtail(&em->faces, efa); - em->totface++; - - if(efa->v4) { - normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - } - else { - normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co); - cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co); - } - - return efa; -} - -/* ************************ end add/new/find ************ */ - -/* ************************ Edit{Vert,Edge,Face} utilss ***************************** */ - -/* some nice utility functions */ - -EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve) -{ - if (eve==eed->v1) { - return eed->v2; - } else if (eve==eed->v2) { - return eed->v1; - } else { - return NULL; - } -} - -EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2) -{ - if (eed->v1==eed2->v1 || eed->v1==eed2->v2) { - return eed->v1; - } else if (eed->v2==eed2->v1 || eed->v2==eed2->v2) { - return eed->v2; - } else { - return NULL; - } -} - -int editedge_containsVert(EditEdge *eed, EditVert *eve) -{ - return (eed->v1==eve || eed->v2==eve); -} - -int editface_containsVert(EditFace *efa, EditVert *eve) -{ - return (efa->v1==eve || efa->v2==eve || efa->v3==eve || (efa->v4 && efa->v4==eve)); -} - -int editface_containsEdge(EditFace *efa, EditEdge *eed) -{ - return (efa->e1==eed || efa->e2==eed || efa->e3==eed || (efa->e4 && efa->e4==eed)); -} - - -/* ************************ stuct EditMesh manipulation ***************************** */ - -void set_editMesh(EditMesh *dst, EditMesh *src) -{ - free_editMesh(dst); - *dst = *src; -} - -/* do not free editmesh itself here */ -void free_editMesh(EditMesh *em) -{ - if(em==NULL) return; - - if(em->verts.first) free_vertlist(em, &em->verts); - if(em->edges.first) free_edgelist(em, &em->edges); - if(em->faces.first) free_facelist(em, &em->faces); - if(em->selected.first) BLI_freelistN(&(em->selected)); - - if (em->vertpool) BLI_mempool_destroy(em->vertpool); - if (em->edgepool) BLI_mempool_destroy(em->edgepool); - if (em->facepool) BLI_mempool_destroy(em->facepool); - em->vertpool = em->edgepool = em->facepool = NULL; - - CustomData_free(&em->vdata, 0); - CustomData_free(&em->fdata, 0); - - if(em->derivedFinal) { - if (em->derivedFinal!=em->derivedCage) { - em->derivedFinal->needsFree= 1; - em->derivedFinal->release(em->derivedFinal); - } - em->derivedFinal= NULL; - } - if(em->derivedCage) { - em->derivedCage->needsFree= 1; - em->derivedCage->release(em->derivedCage); - em->derivedCage= NULL; - } - - /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */ -#if 0 - if(em->hashedgetab) { - HashEdge *he, *hen; - int a, used=0, max=0, nr; - he= em->hashedgetab; - for(a=0; a<EDHASHSIZE; a++, he++) { - if(he->eed) used++; - hen= he->next; - nr= 0; - while(hen) { - nr++; - hen= hen->next; - } - if(max<nr) max= nr; - } - printf("hastab used %d max %d\n", used, max); - } -#endif - if(em->hashedgetab) MEM_freeN(em->hashedgetab); - em->hashedgetab= NULL; - - if(em->allverts) MEM_freeN(em->allverts); - if(em->alledges) MEM_freeN(em->alledges); - if(em->allfaces) MEM_freeN(em->allfaces); - - em->allverts= em->curvert= NULL; - em->alledges= em->curedge= NULL; - em->allfaces= em->curface= NULL; - - mesh_octree_table(NULL, NULL, NULL, 'e'); - - em->totvert= em->totedge= em->totface= 0; - -// XXX if(em->retopo_paint_data) retopo_free_paint_data(em->retopo_paint_data); - em->retopo_paint_data= NULL; - em->act_face = NULL; -} - -static void editMesh_set_hash(EditMesh *em) -{ - EditEdge *eed; - - if(em->hashedgetab) MEM_freeN(em->hashedgetab); - em->hashedgetab= NULL; - - for(eed=em->edges.first; eed; eed= eed->next) { - if( findedgelist(em, eed->v1, eed->v2)==NULL ) - insert_hashedge(em, eed); - } - -} - - -/* ************************ IN & OUT EDITMODE ***************************** */ - - -static void edge_normal_compare(EditEdge *eed, EditFace *efa1) -{ - EditFace *efa2; - float cent1[3], cent2[3]; - float inp; - - efa2 = eed->tmp.f; - if(efa1==efa2) return; - - inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2]; - if(inp<0.999 && inp >-0.999) eed->f2= 1; - - if(efa1->v4) cent_quad_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co); - else cent_tri_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co); - if(efa2->v4) cent_quad_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co); - else cent_tri_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co); - - sub_v3_v3v3(cent1, cent2, cent1); - normalize_v3(cent1); - inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2]; - - if(inp < -0.001 ) eed->f1= 1; -} - -#if 0 -typedef struct { - EditEdge *eed; - float noLen,no[3]; - int adjCount; -} EdgeDrawFlagInfo; - -static int edgeDrawFlagInfo_cmp(const void *av, const void *bv) -{ - const EdgeDrawFlagInfo *a = av; - const EdgeDrawFlagInfo *b = bv; - - if (a->noLen<b->noLen) return -1; - else if (a->noLen>b->noLen) return 1; - else return 0; -} -#endif - -static void edge_drawflags(Mesh *me, EditMesh *em) -{ - EditVert *eve; - EditEdge *eed, *e1, *e2, *e3, *e4; - EditFace *efa; - - /* - count number of times edges are used in faces: 0 en 1 time means draw edge - * - edges more than 1 time used: in *tmp.f is pointer to first face - * - check all faces, when normal differs to much: draw (flag becomes 1) - */ - - /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old - game engine (2.04) - */ - - recalc_editnormals(em); - - /* init */ - eve= em->verts.first; - while(eve) { - eve->f1= 1; /* during test it's set at zero */ - eve= eve->next; - } - eed= em->edges.first; - while(eed) { - eed->f2= eed->f1= 0; - eed->tmp.f = 0; - eed= eed->next; - } - - efa= em->faces.first; - while(efa) { - e1= efa->e1; - e2= efa->e2; - e3= efa->e3; - e4= efa->e4; - if(e1->f2<4) e1->f2+= 1; - if(e2->f2<4) e2->f2+= 1; - if(e3->f2<4) e3->f2+= 1; - if(e4 && e4->f2<4) e4->f2+= 1; - - if(e1->tmp.f == 0) e1->tmp.f = (void *) efa; - if(e2->tmp.f == 0) e2->tmp.f = (void *) efa; - if(e3->tmp.f ==0) e3->tmp.f = (void *) efa; - if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa; - - efa= efa->next; - } - - if(me->drawflag & ME_ALLEDGES) { - efa= em->faces.first; - while(efa) { - if(efa->e1->f2>=2) efa->e1->f2= 1; - if(efa->e2->f2>=2) efa->e2->f2= 1; - if(efa->e3->f2>=2) efa->e3->f2= 1; - if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1; - - efa= efa->next; - } - } - else { - - /* handle single-edges for 'test cylinder flag' (old engine) */ - - eed= em->edges.first; - while(eed) { - if(eed->f2==1) eed->f1= 1; - eed= eed->next; - } - - /* all faces, all edges with flag==2: compare normal */ - efa= em->faces.first; - while(efa) { - if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa); - else efa->e1->f2= 1; - if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa); - else efa->e2->f2= 1; - if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa); - else efa->e3->f2= 1; - if(efa->e4) { - if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa); - else efa->e4->f2= 1; - } - efa= efa->next; - } - - /* sphere collision flag */ - - eed= em->edges.first; - while(eed) { - if(eed->f1!=1) { - eed->v1->f1= eed->v2->f1= 0; - } - eed= eed->next; - } - - } -} - -/* turns Mesh into editmesh */ -EditMesh *make_editMesh(Scene *scene, Object *ob) -{ - Mesh *me= ob->data; - MFace *mface; - MVert *mvert; - MSelect *mselect; - KeyBlock *actkey; - EditMesh *em; - EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4; - EditFace *efa; - EditEdge *eed; - EditSelection *ese; - float *co, (*keyco)[3]= NULL; - int tot, a, eekadoodle= 0; - - em= MEM_callocN(sizeof(EditMesh), "editmesh"); - - em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced - em->act_face = NULL; - em->totvert= tot= me->totvert; - em->totedge= me->totedge; - em->totface= me->totface; - - if(tot==0) { - return; - } - - if(ob->actcol > 0) - em->mat_nr= ob->actcol-1; - - actkey = ob_get_keyblock(ob); - if(actkey) { - keyco= actkey->data; - em->shapenr= ob->shapenr; - } - - /* make editverts */ - CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); - mvert= me->mvert; - - evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist"); - for(a=0; a<tot; a++, mvert++) { - - co= mvert->co; - - /* edit the shape key coordinate if available */ - if(keyco && a < actkey->totelem) - co= keyco[a]; - - eve= addvertlist(em, co, NULL); - evlist[a]= eve; - - /* face select sets selection in next loop */ - if(!paint_facesel_test(ob)) - eve->f |= (mvert->flag & 1); - - if (mvert->flag & ME_HIDE) eve->h= 1; - eve->no[0]= mvert->no[0]/32767.0; - eve->no[1]= mvert->no[1]/32767.0; - eve->no[2]= mvert->no[2]/32767.0; - - eve->bweight= ((float)mvert->bweight)/255.0f; - - /* lets overwrite the keyindex of the editvert - * with the order it used to be in before - * editmode - */ - eve->keyindex = a; - - CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data); - } - - if(actkey && actkey->totelem!=me->totvert); - else { - MEdge *medge= me->medge; - - CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0); - /* make edges */ - for(a=0; a<me->totedge; a++, medge++) { - eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL); - /* eed can be zero when v1 and v2 are identical, dxf import does this... */ - if(eed) { - eed->crease= ((float)medge->crease)/255.0f; - eed->bweight= ((float)medge->bweight)/255.0f; - - if(medge->flag & ME_SEAM) eed->seam= 1; - if(medge->flag & ME_SHARP) eed->sharp = 1; - if(medge->flag & SELECT) eed->f |= SELECT; - if(medge->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines! - if(medge->flag & ME_HIDE) eed->h |= 1; - if(em->selectmode==SCE_SELECT_EDGE) - EM_select_edge(eed, eed->f & SELECT); // force edge selection to vertices, seems to be needed ... - CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data); - } - } - - CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0); - - /* make faces */ - mface= me->mface; - - for(a=0; a<me->totface; a++, mface++) { - eve1= evlist[mface->v1]; - eve2= evlist[mface->v2]; - if(!mface->v3) eekadoodle= 1; - eve3= evlist[mface->v3]; - if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL; - - efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL); - - if(efa) { - CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data); - - efa->mat_nr= mface->mat_nr; - efa->flag= mface->flag & ~ME_HIDE; - - /* select and hide face flag */ - if(mface->flag & ME_HIDE) { - efa->h= 1; - } else { - if (a==me->act_face) { - EM_set_actFace(em, efa); - } - - /* dont allow hidden and selected */ - if(mface->flag & ME_FACE_SEL) { - efa->f |= SELECT; - - if(paint_facesel_test(ob)) { - EM_select_face(efa, 1); /* flush down */ - } - } - } - } - } - } - - if(eekadoodle) - error("This Mesh has old style edgecodes, please put it in the bugtracker!"); - - MEM_freeN(evlist); - - if(me->mselect){ - //restore editselections - EM_init_index_arrays(em, 1,1,1); - mselect = me->mselect; - - for(a=0; a<me->totselect; a++, mselect++){ - /*check if recorded selection is still valid, if so copy into editmesh*/ - if( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ){ - ese = MEM_callocN(sizeof(EditSelection), "Edit Selection"); - ese->type = mselect->type; - if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else - if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else - if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index); - BLI_addtail(&(em->selected),ese); - } - } - EM_free_index_arrays(); - } - /* this creates coherent selections. also needed for older files */ - EM_selectmode_set(em); - /* paranoia check to enforce hide rules */ - EM_hide_reset(em); - /* sets helper flags which arent saved */ - EM_fgon_flags(em); - - if (EM_get_actFace(em, 0)==NULL) { - EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */ - } -} - -/* makes Mesh out of editmesh */ -void load_editMesh(Scene *scene, Object *ob, EditMesh *em) -{ - Mesh *me= ob->data; - MVert *mvert, *oldverts; - MEdge *medge; - MFace *mface; - MSelect *mselect; - EditVert *eve; - EditFace *efa, *efa_act; - EditEdge *eed; - EditSelection *ese; - float *fp, *newkey, *oldkey, nor[3]; - int i, a, ototvert; - - /* this one also tests of edges are not in faces: */ - /* eed->f2==0: not in face, f2==1: draw it */ - /* eed->f1 : flag for dynaface (cylindertest, old engine) */ - /* eve->f1 : flag for dynaface (sphere test, old engine) */ - /* eve->f2 : being used in vertexnormals */ - edge_drawflags(me, em); - - EM_stats_update(em); - - /* new Vertex block */ - if(em->totvert==0) mvert= NULL; - else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert"); - - /* new Edge block */ - if(em->totedge==0) medge= NULL; - else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge"); - - /* new Face block */ - if(em->totface==0) mface= NULL; - else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face"); - - /* lets save the old verts just in case we are actually working on - * a key ... we now do processing of the keys at the end */ - oldverts= me->mvert; - ototvert= me->totvert; - - /* don't free this yet */ - CustomData_set_layer(&me->vdata, CD_MVERT, NULL); - - /* free custom data */ - CustomData_free(&me->vdata, me->totvert); - CustomData_free(&me->edata, me->totedge); - CustomData_free(&me->fdata, me->totface); - - /* add new custom data */ - me->totvert= em->totvert; - me->totedge= em->totedge; - me->totface= em->totface; - - CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert); - CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge); - CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface); - - CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); - CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); - CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface); - mesh_update_customdata_pointers(me); - - /* the vertices, use ->tmp.l as counter */ - eve= em->verts.first; - a= 0; - - while(eve) { - VECCOPY(mvert->co, eve->co); - - mvert->mat_nr= 32767; /* what was this for, halos? */ - - /* vertex normal */ - VECCOPY(nor, eve->no); - mul_v3_fl(nor, 32767.0); - VECCOPY(mvert->no, nor); - - /* note: it used to remove me->dvert when it was not in use, cancelled - that... annoying when you have a fresh vgroup */ - CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a); - - eve->tmp.l = a++; /* counter */ - - mvert->flag= 0; - mvert->flag |= (eve->f & SELECT); - if (eve->h) mvert->flag |= ME_HIDE; - - mvert->bweight= (char)(255.0*eve->bweight); - - eve= eve->next; - mvert++; - } - - /* the edges */ - a= 0; - eed= em->edges.first; - while(eed) { - medge->v1= (unsigned int) eed->v1->tmp.l; - medge->v2= (unsigned int) eed->v2->tmp.l; - - medge->flag= (eed->f & SELECT) | ME_EDGERENDER; - if(eed->f2<2) medge->flag |= ME_EDGEDRAW; - if(eed->f2==0) medge->flag |= ME_LOOSEEDGE; - if(eed->sharp) medge->flag |= ME_SHARP; - if(eed->seam) medge->flag |= ME_SEAM; - if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes - if(eed->h & 1) medge->flag |= ME_HIDE; - - medge->crease= (char)(255.0*eed->crease); - medge->bweight= (char)(255.0*eed->bweight); - CustomData_from_em_block(&em->edata, &me->edata, eed->data, a); - - eed->tmp.l = a++; - - medge++; - eed= eed->next; - } - - /* the faces */ - a = 0; - efa= em->faces.first; - efa_act= EM_get_actFace(em, 0); - i = 0; - me->act_face = -1; - while(efa) { - mface= &((MFace *) me->mface)[i]; - - mface->v1= (unsigned int) efa->v1->tmp.l; - mface->v2= (unsigned int) efa->v2->tmp.l; - mface->v3= (unsigned int) efa->v3->tmp.l; - if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l; - - mface->mat_nr= efa->mat_nr; - - mface->flag= efa->flag; - /* bit 0 of flag is already taken for smooth... */ - - if(efa->h) { - mface->flag |= ME_HIDE; - mface->flag &= ~ME_FACE_SEL; - } else { - if(efa->f & 1) mface->flag |= ME_FACE_SEL; - else mface->flag &= ~ME_FACE_SEL; - } - - /* mat_nr in vertex */ - if(me->totcol>1) { - mvert= me->mvert+mface->v1; - if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; - mvert= me->mvert+mface->v2; - if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; - mvert= me->mvert+mface->v3; - if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; - if(mface->v4) { - mvert= me->mvert+mface->v4; - if(mvert->mat_nr == (char)32767) mvert->mat_nr= mface->mat_nr; - } - } - - /* watch: efa->e1->f2==0 means loose edge */ - - if(efa->e1->f2==1) { - efa->e1->f2= 2; - } - if(efa->e2->f2==1) { - efa->e2->f2= 2; - } - if(efa->e3->f2==1) { - efa->e3->f2= 2; - } - if(efa->e4 && efa->e4->f2==1) { - efa->e4->f2= 2; - } - - CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i); - - /* no index '0' at location 3 or 4 */ - test_index_face(mface, &me->fdata, i, efa->v4?4:3); - - if (efa_act == efa) - me->act_face = a; - - efa->tmp.l = a++; - i++; - efa= efa->next; - } - - /* patch hook indices and vertex parents */ - { - Object *ob; - ModifierData *md; - EditVert **vertMap = NULL; - int i,j; - - for (ob=G.main->object.first; ob; ob=ob->id.next) { - if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) { - - /* duplicate code from below, make it function later...? */ - if (!vertMap) { - vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); - - for (eve=em->verts.first; eve; eve=eve->next) { - if (eve->keyindex!=-1) - vertMap[eve->keyindex] = eve; - } - } - if(ob->par1 < ototvert) { - eve = vertMap[ob->par1]; - if(eve) ob->par1= eve->tmp.l; - } - if(ob->par2 < ototvert) { - eve = vertMap[ob->par2]; - if(eve) ob->par2= eve->tmp.l; - } - if(ob->par3 < ototvert) { - eve = vertMap[ob->par3]; - if(eve) ob->par3= eve->tmp.l; - } - - } - if (ob->data==me) { - for (md=ob->modifiers.first; md; md=md->next) { - if (md->type==eModifierType_Hook) { - HookModifierData *hmd = (HookModifierData*) md; - - if (!vertMap) { - vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap"); - - for (eve=em->verts.first; eve; eve=eve->next) { - if (eve->keyindex!=-1) - vertMap[eve->keyindex] = eve; - } - } - - for (i=j=0; i<hmd->totindex; i++) { - if(hmd->indexar[i] < ototvert) { - eve = vertMap[hmd->indexar[i]]; - - if (eve) { - hmd->indexar[j++] = eve->tmp.l; - } - } - else j++; - } - - hmd->totindex = j; - } - } - } - } - - if (vertMap) MEM_freeN(vertMap); - } - - /* are there keys? */ - if(me->key) { - KeyBlock *currkey; - KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1); - - /* Lets reorder the key data so that things line up roughly - * with the way things were before editmode */ - currkey = me->key->block.first; - while(currkey) { - - fp= newkey= MEM_callocN(me->key->elemsize*em->totvert, "currkey->data"); - oldkey = currkey->data; - - eve= em->verts.first; - - i = 0; - mvert = me->mvert; - while(eve) { - if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex - if(currkey == actkey) { - if(actkey == me->key->refkey) { - VECCOPY(fp, mvert->co); - } - else { - VECCOPY(fp, mvert->co); - if(oldverts) { - VECCOPY(mvert->co, oldverts[eve->keyindex].co); - } - } - } - else { - if(oldkey) { - VECCOPY(fp, oldkey + 3 * eve->keyindex); - } - } - } - else { - VECCOPY(fp, mvert->co); - } - fp+= 3; - ++i; - ++mvert; - eve= eve->next; - } - currkey->totelem= em->totvert; - if(currkey->data) MEM_freeN(currkey->data); - currkey->data = newkey; - - currkey= currkey->next; - } - } - - if(oldverts) MEM_freeN(oldverts); - - i = 0; - for(ese=em->selected.first; ese; ese=ese->next) i++; - me->totselect = i; - if(i==0) mselect= NULL; - else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections"); - - if(me->mselect) MEM_freeN(me->mselect); - me->mselect= mselect; - - for(ese=em->selected.first; ese; ese=ese->next){ - mselect->type = ese->type; - if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l; - else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l; - else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l; - mselect++; - } - - /* to be sure: clear ->tmp.l pointers */ - eve= em->verts.first; - while(eve) { - eve->tmp.l = 0; - eve= eve->next; - } - - eed= em->edges.first; - while(eed) { - eed->tmp.l = 0; - eed= eed->next; - } - - efa= em->faces.first; - while(efa) { - efa->tmp.l = 0; - efa= efa->next; - } - - /* remake softbody of all users */ - if(me->id.us>1) { - Base *base; - for(base= scene->base.first; base; base= base->next) - if(base->object->data==me) - base->object->recalc |= OB_RECALC_DATA; - } - - mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); -} - -void remake_editMesh(Scene *scene, Object *ob) -{ - make_editMesh(scene, ob); - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - BIF_undo_push("Undo all changes"); -} - -/* *************** Operator: separate parts *************/ - -static EnumPropertyItem prop_separate_types[] = { - {0, "SELECTED", 0, "Selection", ""}, - {1, "MATERIAL", 0, "By Material", ""}, - {2, "LOOSE", 0, "By loose parts", ""}, - {0, NULL, 0, NULL, NULL} -}; - -/* return 1: success */ -static int mesh_separate_selected(Scene *scene, Base *editbase) -{ -#if 0 - EditMesh *em, *emnew; - EditVert *eve, *v1; - EditEdge *eed, *e1; - EditFace *efa, *f1; - Object *obedit; - Mesh *me, *menew; - Base *basenew; - - if(editbase==NULL) return 0; - - obedit= editbase->object; - me= obedit->data; - em= BKE_mesh_get_editmesh(me); - if(me->key) { - error("Can't separate with vertex keys"); - BKE_mesh_end_editmesh(me, em); - return 0; - } - - if(em->selected.first) - BLI_freelistN(&(em->selected)); /* clear the selection order */ - - EM_selectmode_set(em); // enforce full consistent selection flags - - EM_stats_update(em); - - if(em->totvertsel==0) { - BKE_mesh_end_editmesh(me, em); - return 0; - } - - /* we are going to work as follows: - * 1. add a linked duplicate object: this will be the new one, we remember old pointer - * 2. give new object empty mesh and put in editmode - * 3: do a split if needed on current editmesh. - * 4. copy over: all NOT selected verts, edges, faces - * 5. call load_editMesh() on the new object - */ - - /* 1 */ - basenew= ED_object_add_duplicate(scene, editbase, 0); /* 0 = fully linked */ - ED_base_object_select(basenew, BA_DESELECT); - - /* 2 */ - basenew->object->data= menew= add_mesh(me->id.name+2); /* empty */ - assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */ - me->id.us--; - emnew = make_editMesh(scene, basenew->object); - //emnew= menew->edit_mesh; - CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); - CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0); - CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0); - - /* 3 */ - /* SPLIT: first make duplicate */ - adduplicateflag(em, SELECT); - /* SPLIT: old faces have 3x flag 128 set, delete these ones */ - delfaceflag(em, 128); - /* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */ - EM_selectmode_set(em); - - /* 4 */ - /* move over: everything that is selected */ - for(eve= em->verts.first; eve; eve= v1) { - v1= eve->next; - if(eve->f & SELECT) { - BLI_remlink(&em->verts, eve); - BLI_addtail(&emnew->verts, eve); - } - } - - for(eed= em->edges.first; eed; eed= e1) { - e1= eed->next; - if(eed->f & SELECT) { - BLI_remlink(&em->edges, eed); - BLI_addtail(&emnew->edges, eed); - } - } - - for(efa= em->faces.first; efa; efa= f1) { - f1= efa->next; - if (efa == em->act_face && (efa->f & SELECT)) { - EM_set_actFace(em, NULL); - } - - if(efa->f & SELECT) { - BLI_remlink(&em->faces, efa); - BLI_addtail(&emnew->faces, efa); - } - } - - /* 5 */ - load_editMesh(scene, basenew->object, emnew); - free_editMesh(emnew); - MEM_freeN(menew->edit_mesh); - menew->edit_mesh= NULL; - - /* hashedges are invalid now, make new! */ - editMesh_set_hash(em); - - DAG_id_flush_update(&obedit->id, OB_RECALC_DATA); - DAG_id_flush_update(&basenew->object->id, OB_RECALC_DATA); - - BKE_mesh_end_editmesh(me, em); - - return 1; -#endif -} - -/* return 1: success */ -static int mesh_separate_material(Scene *scene, Base *editbase) -{ -#if 0 - Mesh *me= editbase->object->data; - EditMesh *em= BKE_mesh_get_editmesh(me); - unsigned char curr_mat; - - for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) { - /* clear selection, we're going to use that to select material group */ - EM_clear_flag_all(em, SELECT); - /* select the material */ - EM_select_by_material(em, curr_mat); - /* and now separate */ - if(0==mesh_separate_selected(scene, editbase)) { - BKE_mesh_end_editmesh(me, em); - return 0; - } - } - - BKE_mesh_end_editmesh(me, em); - return 1; -#endif -} - -/* return 1: success */ -static int mesh_separate_loose(Scene *scene, Base *editbase) -{ - return 0; -#if 0 - Mesh *me; - EditMesh *em; - int doit= 1; - - me= editbase->object->data; - em= BKE_mesh_get_editmesh(me); - - if(me->key) { - error("Can't separate with vertex keys"); - BKE_mesh_end_editmesh(me, em); - return 0; - } - - EM_clear_flag_all(em, SELECT); - - while(doit && em->verts.first) { - /* Select a random vert to start with */ - EditVert *eve= em->verts.first; - eve->f |= SELECT; - - selectconnected_mesh_all(em); - - /* and now separate */ - doit= mesh_separate_selected(scene, editbase); - } - - BKE_mesh_end_editmesh(me, em); - return 1; -#endif -} - - -static int mesh_separate_exec(bContext *C, wmOperator *op) -{ - Scene *scene= CTX_data_scene(C); - Base *base= CTX_data_active_base(C); - int retval= 0, type= RNA_enum_get(op->ptr, "type"); - - if(type == 0) - retval= mesh_separate_selected(scene, base); - else if(type == 1) - retval= mesh_separate_material (scene, base); - else if(type == 2) - retval= mesh_separate_loose(scene, base); - - if(retval) { - WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data); - return OPERATOR_FINISHED; - } - return OPERATOR_CANCELLED; -} - -void MESH_OT_separate(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Separate"; - ot->description= "Separate selected geometry into a new mesh."; - ot->idname= "MESH_OT_separate"; - - /* api callbacks */ - ot->invoke= WM_menu_invoke; - ot->exec= mesh_separate_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", ""); -} - - -/* ******************************************** */ - -/* *************** UNDO ***************************** */ -/* new mesh undo, based on pushing editmesh data itself */ -/* reuses same code as for global and curve undo... unify that (ton) */ - -/* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */ - -/* a compressed version of editmesh data */ - -typedef struct EditVertC -{ - float no[3]; - float co[3]; - unsigned char f, h; - short bweight; - int keyindex; -} EditVertC; - -typedef struct EditEdgeC -{ - int v1, v2; - unsigned char f, h, seam, sharp, pad; - short crease, bweight, fgoni; -} EditEdgeC; - -typedef struct EditFaceC -{ - int v1, v2, v3, v4; - unsigned char flag, f, h, fgonf, pad1; - short mat_nr; -} EditFaceC; - -typedef struct EditSelectionC{ - short type; - int index; -}EditSelectionC; - -typedef struct UndoMesh { - EditVertC *verts; - EditEdgeC *edges; - EditFaceC *faces; - EditFaceC *act_face; - EditSelectionC *selected; - int totvert, totedge, totface, totsel; - short selectmode; - RetopoPaintData *retopo_paint_data; - char retopo_mode; - CustomData vdata, edata, fdata; -} UndoMesh; - - -/* *************** END UNDO *************/ - -static EditVert **g_em_vert_array = NULL; -static EditEdge **g_em_edge_array = NULL; -static EditFace **g_em_face_array = NULL; - -void EM_init_index_arrays(EditMesh *em, int forVert, int forEdge, int forFace) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - int i; - - if (forVert) { - em->totvert= BLI_countlist(&em->verts); - - if(em->totvert) { - g_em_vert_array = MEM_mallocN(sizeof(*g_em_vert_array)*em->totvert, "em_v_arr"); - - for (i=0,eve=em->verts.first; eve; i++,eve=eve->next) - g_em_vert_array[i] = eve; - } - } - - if (forEdge) { - em->totedge= BLI_countlist(&em->edges); - - if(em->totedge) { - g_em_edge_array = MEM_mallocN(sizeof(*g_em_edge_array)*em->totedge, "em_e_arr"); - - for (i=0,eed=em->edges.first; eed; i++,eed=eed->next) - g_em_edge_array[i] = eed; - } - } - - if (forFace) { - em->totface= BLI_countlist(&em->faces); - - if(em->totface) { - g_em_face_array = MEM_mallocN(sizeof(*g_em_face_array)*em->totface, "em_f_arr"); - - for (i=0,efa=em->faces.first; efa; i++,efa=efa->next) - g_em_face_array[i] = efa; - } - } -} - -void EM_free_index_arrays(void) -{ - if (g_em_vert_array) MEM_freeN(g_em_vert_array); - if (g_em_edge_array) MEM_freeN(g_em_edge_array); - if (g_em_face_array) MEM_freeN(g_em_face_array); - g_em_vert_array = NULL; - g_em_edge_array = NULL; - g_em_face_array = NULL; -} - -EditVert *EM_get_vert_for_index(int index) -{ - return g_em_vert_array?g_em_vert_array[index]:NULL; -} - -EditEdge *EM_get_edge_for_index(int index) -{ - return g_em_edge_array?g_em_edge_array[index]:NULL; -} - -EditFace *EM_get_face_for_index(int index) -{ - return g_em_face_array?g_em_face_array[index]:NULL; -} - -/* can we edit UV's for this mesh?*/ -int EM_texFaceCheck(EditMesh *em) -{ - /* some of these checks could be a touch overkill */ - if ( (em) && - (em->faces.first) && - (CustomData_has_layer(&em->fdata, CD_MTFACE))) - return 1; - return 0; -} - -/* can we edit colors for this mesh?*/ -int EM_vertColorCheck(EditMesh *em) -{ - /* some of these checks could be a touch overkill */ - if ( (em) && - (em->faces.first) && - (CustomData_has_layer(&em->fdata, CD_MCOL))) - return 1; - return 0; -} - - -void em_setup_viewcontext(bContext *C, ViewContext *vc) -{ - view3d_set_viewcontext(C, vc); - - if(vc->obedit) { - Mesh *me= vc->obedit->data; - vc->em= me->edit_btmesh; - } -} diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c deleted file mode 100644 index ad61dff37cd..00000000000 --- a/source/blender/editors/mesh/editmesh_add.c +++ /dev/null @@ -1,1554 +0,0 @@ -/** - * $Id: - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2004 by Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_space_types.h" -#include "DNA_screen_types.h" -#include "DNA_userdef_types.h" -#include "DNA_view3d_types.h" -#include "DNA_windowmanager_types.h" - -#include "RNA_types.h" -#include "RNA_define.h" -#include "RNA_access.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_editVert.h" - -#include "BKE_context.h" -#include "BKE_depsgraph.h" -#include "BKE_global.h" -#include "BKE_library.h" -#include "BKE_mesh.h" -#include "BKE_object.h" -#include "BKE_utildefines.h" -#include "BKE_report.h" -#include "BKE_tessmesh.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "ED_mesh.h" -#include "ED_retopo.h" -#include "ED_screen.h" -#include "ED_transform.h" -#include "ED_util.h" -#include "ED_view3d.h" -#include "ED_object.h" - -#include "bmesh.h" - -#include "mesh_intern.h" - -/* bpymenu removed XXX */ - -/* XXX */ -#define add_numbut(a, b, c, d, e, f, g) {} -/* XXX */ - -static float icovert[12][3] = { - {0.0f,0.0f,-200.0f}, - {144.72f, -105.144f,-89.443f}, - {-55.277f, -170.128,-89.443f}, - {-178.885f,0.0f,-89.443f}, - {-55.277f,170.128f,-89.443f}, - {144.72f,105.144f,-89.443f}, - {55.277f,-170.128f,89.443f}, - {-144.72f,-105.144f,89.443f}, - {-144.72f,105.144f,89.443f}, - {55.277f,170.128f,89.443f}, - {178.885f,0.0f,89.443f}, - {0.0f,0.0f,200.0f} -}; -static short icoface[20][3] = { - {1,0,2}, - {1,0,5}, - {2,0,3}, - {3,0,4}, - {4,0,5}, - {1,5,10}, - {2,1,6}, - {3,2,7}, - {4,3,8}, - {5,4,9}, - {10,1,6}, - {6,2,7}, - {7,3,8}, - {8,4,9}, - {9,5,10}, - {6,10,11}, - {7,6,11}, - {8,7,11}, - {9,8,11}, - {10,9,11} -}; - -/* ********************** */ - -/* selected faces get hidden edges */ -int make_fgon(EditMesh *em, wmOperator *op, int make) -{ - EditFace *efa; - EditEdge *eed; - EditVert *eve; - float *nor=NULL; // reference - int done=0; - - if(make==0) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - efa->fgonf= 0; - efa->e1->h &= ~EM_FGON; - efa->e2->h &= ~EM_FGON; - efa->e3->h &= ~EM_FGON; - if(efa->e4) efa->e4->h &= ~EM_FGON; - done= 1; - } - } - EM_fgon_flags(em); // redo flags and indices for fgons - - return done; - } - - /* tagging edges. rule is: - - edge used by exactly 2 selected faces - - no vertices allowed with only tagged edges (return) - - face normals are allowed to difffer - - */ - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; // amount of selected - eed->f2= 0; // amount of unselected - } - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - if(nor==NULL) nor= efa->n; - if(efa->e1->f1 < 3) efa->e1->f1++; - if(efa->e2->f1 < 3) efa->e2->f1++; - if(efa->e3->f1 < 3) efa->e3->f1++; - if(efa->e4 && efa->e4->f1 < 3) efa->e4->f1++; - } - else { - if(efa->e1->f2 < 3) efa->e1->f2++; - if(efa->e2->f2 < 3) efa->e2->f2++; - if(efa->e3->f2 < 3) efa->e3->f2++; - if(efa->e4 && efa->e4->f2 < 3) efa->e4->f2++; - } - } - // now eed->f1 becomes tagged edge - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f1==2 && eed->f2==0) eed->f1= 1; - else eed->f1= 0; - } - - // no vertices allowed with only tagged edges - for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f1) { - eed->v1->f1 |= 1; - eed->v2->f1 |= 1; - } - else { - eed->v1->f1 |= 2; - eed->v2->f1 |= 2; - } - } - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f1==1) break; - } - if(eve) { - BKE_report(op->reports, RPT_ERROR, "Cannot make a polygon with interior vertices"); - return 0; - } - - // check for faces - if(nor==NULL) { - BKE_report(op->reports, RPT_ERROR, "No faces were selected to make FGon"); - return 0; - } - - // and there we go - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f1) { - eed->h |= EM_FGON; - done= 1; - } - } - - if(done) - EM_fgon_flags(em); // redo flags and indices for fgons - return done; -} - -static int make_fgon_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - if( make_fgon(em, op, 1) ) { - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; - } - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; -} - -void MESH_OT_fgon_make(struct wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Make F-gon"; - ot->description= "Make fgon from selected faces."; - ot->idname= "MESH_OT_fgon_make"; - - /* api callbacks */ - ot->exec= make_fgon_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int clear_fgon_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - if( make_fgon(em, op, 0) ) { - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; - } - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; -} - -void MESH_OT_fgon_clear(struct wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Clear F-gon"; - ot->description= "Clear fgon from selected face."; - ot->idname= "MESH_OT_fgon_clear"; - - /* api callbacks */ - ot->exec= clear_fgon_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -/* precondition; 4 vertices selected, check for 4 edges and create face */ -static EditFace *addface_from_edges(EditMesh *em) -{ - EditEdge *eed, *eedar[4]={NULL, NULL, NULL, NULL}; - EditVert *v1=NULL, *v2=NULL, *v3=NULL, *v4=NULL; - int a; - - /* find the 4 edges */ - for(eed= em->edges.first; eed; eed= eed->next) { - if( (eed->f & SELECT) || (eed->v1->f & eed->v2->f & SELECT) ) { - if(eedar[0]==NULL) eedar[0]= eed; - else if(eedar[1]==NULL) eedar[1]= eed; - else if(eedar[2]==NULL) eedar[2]= eed; - else eedar[3]= eed; - - } - } - - - if(eedar[3]) { - /* first 2 points */ - v1= eedar[0]->v1; - v2= eedar[0]->v2; - - /* find the 2 edges connected to first edge */ - for(a=1; a<4; a++) { - if( eedar[a]->v1 == v2) v3= eedar[a]->v2; - else if(eedar[a]->v2 == v2) v3= eedar[a]->v1; - else if( eedar[a]->v1 == v1) v4= eedar[a]->v2; - else if(eedar[a]->v2 == v1) v4= eedar[a]->v1; - } - - /* verify if last edge exists */ - if(v3 && v4) { - for(a=1; a<4; a++) { - if( eedar[a]->v1==v3 && eedar[a]->v2==v4) break; - if( eedar[a]->v2==v3 && eedar[a]->v1==v4) break; - } - if(a!=4) { - return addfacelist(em, v1, v2, v3, v4, NULL, NULL); - } - } - } - return NULL; -} - -/* ******************************* */ - -/* this also allows to prevent triangles being made in quads */ -static int compareface_overlaps(EditFace *vl1, EditFace *vl2) -{ - EditVert *v1, *v2, *v3, *v4; - int equal= 0; - - v1= vl2->v1; - v2= vl2->v2; - v3= vl2->v3; - v4= vl2->v4; - - if(vl1==vl2) return 0; - - if(v4==NULL && vl1->v4==NULL) { - if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) equal++; - if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) equal++; - if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) equal++; - } - else { - if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) equal++; - if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) equal++; - if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) equal++; - if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) equal++; - } - - if(v4 && vl1->v4) { - if(equal==4) return 1; - } - else - if(equal>=3) return 1; - - return 0; -} - -/* checks for existance, and for tria overlapping inside quad */ -static EditFace *exist_face_overlaps(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4) -{ - EditFace *efa, efatest; - - efatest.v1= v1; - efatest.v2= v2; - efatest.v3= v3; - efatest.v4= v4; - - efa= em->faces.first; - while(efa) { - if(compareface_overlaps(&efatest, efa)) return efa; - efa= efa->next; - } - return NULL; -} - -/* will be new face smooth or solid? depends on smoothness of face neighbours - * of new face, if function return 1, then new face will be smooth, when functio - * will return zero, then new face will be solid */ -static void fix_new_face(EditMesh *em, EditFace *eface) -{ - struct EditFace *efa; - struct EditEdge *eed=NULL; - struct EditVert *v1 = eface->v1, *v2 = eface->v2, *v3 = eface->v3, *v4 = eface->v4; - struct EditVert *ev1=NULL, *ev2=NULL; - short smooth=0; /* "total smoothnes" of faces in neighbourhood */ - short coef; /* "weight" of smoothness */ - short count=0; /* number of edges with same direction as eface */ - short vi00=0, vi01=0, vi10=0, vi11=0; /* vertex indexes */ - - efa = em->faces.first; - - while(efa) { - - if(efa==eface) { - efa = efa->next; - continue; - } - - coef = 0; - ev1 = ev2 = NULL; - eed = NULL; - - if(efa->v1==v1 || efa->v2==v1 || efa->v3==v1 || efa->v4==v1) { - ev1 = v1; - coef++; - } - if(efa->v1==v2 || efa->v2==v2 || efa->v3==v2 || efa->v4==v2) { - if(ev1) ev2 = v2; - else ev1 = v2; - coef++; - } - if(efa->v1==v3 || efa->v2==v3 || efa->v3==v3 || efa->v4==v3) { - if(coef<2) { - if(ev1) ev2 = v3; - else ev1 = v3; - } - coef++; - } - if((v4) && (efa->v1==v4 || efa->v2==v4 || efa->v3==v4 || efa->v4==v4)) { - if(ev1 && coef<2) ev2 = v4; - coef++; - } - - /* "democracy" of smoothness */ - if(efa->flag & ME_SMOOTH) - smooth += coef; - else - smooth -= coef; - - /* try to find edge using vertexes ev1 and ev2 */ - if((ev1) && (ev2) && (ev1!=ev2)) eed = findedgelist(em, ev1, ev2); - - /* has bordering edge of efa same direction as edge of eface ? */ - if(eed) { - if(eed->v1==v1) vi00 = 1; - else if(eed->v1==v2) vi00 = 2; - else if(eed->v1==v3) vi00 = 3; - else if(v4 && eed->v1==v4) vi00 = 4; - - if(eed->v2==v1) vi01 = 1; - else if(eed->v2==v2) vi01 = 2; - else if(eed->v2==v3) vi01 = 3; - else if(v4 && eed->v2==v4) vi01 = 4; - - if(v4) { - if(vi01==1 && vi00==4) vi00 = 0; - if(vi01==4 && vi00==1) vi01 = 0; - } - else { - if(vi01==1 && vi00==3) vi00 = 0; - if(vi01==3 && vi00==1) vi01 = 0; - } - - if(eed->v1==efa->v1) vi10 = 1; - else if(eed->v1==efa->v2) vi10 = 2; - else if(eed->v1==efa->v3) vi10 = 3; - else if(efa->v4 && eed->v1==efa->v4) vi10 = 4; - - if(eed->v2==efa->v1) vi11 = 1; - else if(eed->v2==efa->v2) vi11 = 2; - else if(eed->v2==efa->v3) vi11 = 3; - else if(efa->v4 && eed->v2==efa->v4) vi11 = 4; - - if(efa->v4) { - if(vi11==1 && vi10==4) vi10 = 0; - if(vi11==4 && vi10==1) vi11 = 0; - } - else { - if(vi11==1 && vi10==3) vi10 = 0; - if(vi11==3 && vi10==1) vi11 = 0; - } - - if(((vi00>vi01) && (vi10>vi11)) || - ((vi00<vi01) && (vi10<vi11))) - count++; - else - count--; - } - - efa = efa->next; - } - - /* set up smoothness according voting of face in neighbourhood */ - if(smooth >= 0) - eface->flag |= ME_SMOOTH; - else - eface->flag &= ~ME_SMOOTH; - - /* flip face, when too much "face normals" in neighbourhood is different */ - if(count > 0) { - flipface(em, eface); - } -} - -/* only adds quads or trias when there's edges already */ -void addfaces_from_edgenet(EditMesh *em) -{ - EditVert *eve1, *eve2, *eve3, *eve4; - - for(eve1= em->verts.first; eve1; eve1= eve1->next) { - for(eve2= em->verts.first; (eve1->f & 1) && eve2; eve2= eve2->next) { - if(findedgelist(em, eve1,eve2)) { - for(eve3= em->verts.first; (eve2->f & 1) && eve3; eve3= eve3->next) { - if((eve2!=eve3 && (eve3->f & 1) && findedgelist(em, eve1,eve3))) { - EditEdge *sh_edge= NULL; - EditVert *sh_vert= NULL; - - sh_edge= findedgelist(em, eve2,eve3); - - if(sh_edge) { /* Add a triangle */ - if(!exist_face_overlaps(em, eve1,eve2,eve3,NULL)) - fix_new_face(em, addfacelist(em, eve1,eve2,eve3,NULL,NULL,NULL)); - } - else { /* Check for a shared vertex */ - for(eve4= em->verts.first; eve4; eve4= eve4->next) { - if(eve4!=eve1 && eve4!=eve2 && eve4!=eve3 && (eve4->f & 1) && - !findedgelist(em, eve1,eve4) && findedgelist(em, eve2,eve4) && - findedgelist(em, eve3,eve4)) { - sh_vert= eve4; - break; - } - } - - if(sh_vert) { - if(sh_vert) { - if(!exist_face_overlaps(em, eve1,eve2,eve4,eve3)) - fix_new_face(em, addfacelist(em, eve1,eve2,eve4,eve3,NULL,NULL)); - } - } - } - } - } - } - } - } - - EM_select_flush(em); - -// XXX DAG_id_flush_update(obedit->data, OB_RECALC_DATA); -} - -static void addedgeface_mesh(Mesh *me, BMEditMesh *bem, wmOperator *op) -{ - EditMesh *em; - EditVert *eve, *neweve[4]; - EditEdge *eed; - EditFace *efa; - short amount=0; - - /*return if bmesh vert connect does anything.*/ - if (bem->selectmode & SCE_SELECT_VERTEX) { - BMesh *bm = bem->bm; - BMOperator bmop; - int len, ok; - - EDBM_InitOpf(bem, &bmop, op, "connectverts verts=%hv", BM_SELECT); - BMO_Exec_Op(bem->bm, &bmop); - - len = BMO_GetSlot(&bmop, "edgeout")->len; - - ok = EDBM_FinishOp(bem, &bmop, op, 1); - if (!ok) return; - - if (len) return; - } - - /*return if bmesh face dissolve finds stuff to - dissolve. this entire tool should be - bmeshafied eventually, but until then - hacks like this to integrate with it - are necassary.*/ - if (bem->selectmode & SCE_SELECT_VERTEX) { - BMesh *bm = bem->bm; - BMOperator bmop; - int len, ok; - - EDBM_InitOpf(bem, &bmop, op, "dissolvefaces faces=%hf", BM_SELECT); - BMO_Exec_Op(bem->bm, &bmop); - - len = BMO_GetSlot(&bmop, "regionout")->len; - - ok = EDBM_FinishOp(bem, &bmop, op, 1); - if (!ok) return; - - if (len) return; - } - - em = BKE_mesh_get_editmesh(me); - - /* how many selected ? */ - if(em->selectmode & SCE_SELECT_EDGE) { - /* in edge mode finding selected vertices means flushing down edge codes... */ - /* can't make face with only edge selection info... */ - EM_selectmode_set(em); - } - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) { - amount++; - if(amount>4) break; - neweve[amount-1]= eve; - } - } - - if(amount==2) { - eed= addedgelist(em, neweve[0], neweve[1], NULL); - EM_select_edge(eed, 1); - - BKE_mesh_end_editmesh(me, em); - // XXX DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - return; - } - else if(amount > 4) { - addfaces_from_edgenet(em); - BKE_mesh_end_editmesh(me, em); - return; - } - else if(amount<2) { - BKE_report(op->reports, RPT_ERROR, "More vertices are needed to make an edge/face"); - BKE_mesh_end_editmesh(me, em); - return; - } - - efa= NULL; // check later - - if(amount==3) { - - if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], NULL)==0) { - efa= addfacelist(em, neweve[0], neweve[1], neweve[2], 0, NULL, NULL); - EM_select_face(efa, 1); - } - else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face"); - } - else if(amount==4) { - /* this test survives when theres 2 triangles */ - if(exist_face(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) { - int tria= 0; - - /* remove trias if they exist, 4 cases.... */ - if(exist_face(em, neweve[0], neweve[1], neweve[2], NULL)) tria++; - if(exist_face(em, neweve[0], neweve[1], neweve[3], NULL)) tria++; - if(exist_face(em, neweve[0], neweve[2], neweve[3], NULL)) tria++; - if(exist_face(em, neweve[1], neweve[2], neweve[3], NULL)) tria++; - - if(tria==2) join_triangles(em); - else if(exist_face_overlaps(em, neweve[0], neweve[1], neweve[2], neweve[3])==0) { - /* If there are 4 Verts, But more selected edges, we need to call addfaces_from_edgenet */ - EditEdge *eedcheck; - int count; - count = 0; - for(eedcheck= em->edges.first; eedcheck; eedcheck= eedcheck->next) { - if(eedcheck->f & SELECT) { - count++; - } - } - - if(count++ > 4){ - addfaces_from_edgenet(em); - BKE_mesh_end_editmesh(me, em); - return; - } else { - /* if 4 edges exist, we just create the face, convex or not */ - efa= addface_from_edges(em); - if(efa==NULL) { - - /* the order of vertices can be anything, 6 cases to check */ - if( convex(neweve[0]->co, neweve[1]->co, neweve[2]->co, neweve[3]->co) ) { - efa= addfacelist(em, neweve[0], neweve[1], neweve[2], neweve[3], NULL, NULL); - } - else if( convex(neweve[0]->co, neweve[2]->co, neweve[3]->co, neweve[1]->co) ) { - efa= addfacelist(em, neweve[0], neweve[2], neweve[3], neweve[1], NULL, NULL); - } - else if( convex(neweve[0]->co, neweve[2]->co, neweve[1]->co, neweve[3]->co) ) { - efa= addfacelist(em, neweve[0], neweve[2], neweve[1], neweve[3], NULL, NULL); - } - else if( convex(neweve[0]->co, neweve[1]->co, neweve[3]->co, neweve[2]->co) ) { - efa= addfacelist(em, neweve[0], neweve[1], neweve[3], neweve[2], NULL, NULL); - } - else if( convex(neweve[0]->co, neweve[3]->co, neweve[2]->co, neweve[1]->co) ) { - efa= addfacelist(em, neweve[0], neweve[3], neweve[2], neweve[1], NULL, NULL); - } - else if( convex(neweve[0]->co, neweve[3]->co, neweve[1]->co, neweve[2]->co) ) { - efa= addfacelist(em, neweve[0], neweve[3], neweve[1], neweve[2], NULL, NULL); - } - else printf("cannot find nice quad from concave set of vertices\n"); - } - } - } - else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face"); - } - else BKE_report(op->reports, RPT_ERROR, "The selected vertices already form a face"); - } - - if(efa) { - EM_select_face(efa, 1); - - fix_new_face(em, efa); - - recalc_editnormals(em); - } - - BKE_mesh_end_editmesh(me, em); -} - -/* ************************ primitives ******************* */ - -// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker -// this hack is only used so that scons+mingw + split-sources hack works - // ------------------------------- start copied code -/* these are not the monkeys you are looking for */ -int monkeyo= 4; -int monkeynv= 271; -int monkeynf= 250; -signed char monkeyv[271][3]= { -{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92}, -{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83}, -{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102}, -{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92}, -{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74}, -{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99}, -{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105}, -{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100}, -{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100}, -{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73}, -{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45}, -{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68}, -{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68}, -{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80}, -{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96}, -{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90}, -{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85}, -{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94}, -{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96}, -{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95}, -{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84}, -{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109}, -{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88}, -{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82}, -{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96}, -{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96}, -{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100}, -{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104}, -{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71}, -{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88}, -{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84}, -{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81}, -{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99}, -{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87}, -{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100}, -{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97}, -{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86}, -{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96}, -{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79}, -{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59}, -{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37}, -{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59}, -{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7}, -{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9}, -{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52}, -{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51}, -{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55}, -{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34}, -{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30}, -{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7}, -{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57}, -{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26}, -{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16}, -{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54}, -{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52}, -{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28}, -{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57}, -{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27}, -{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35}, -{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24}, -{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41}, -{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41}, -{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62}, -{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42}, -{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48}, -{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62}, -{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63}, -{-26,-16,-42},{-17,49,-49}, -}; - -signed char monkeyf[250][4]= { -{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, -{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, -{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, -{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, -{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, -{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, -{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, -{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, -{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, -{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, -{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, -{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, -{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, -{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, -{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, -{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, -{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, -{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, -{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, -{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, -{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, -{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, -{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, -{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, -{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, -{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, -{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, -{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, -{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, -{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, -{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, -{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, -{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, -{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, -{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, -{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, -{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, -{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, -{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, -{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, -{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, -{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, -{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, -{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, -{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, -{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, -{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, -{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, -{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, -{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, -{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, -{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, -{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, -{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, -{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, -{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, -{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, -{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, -{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, -{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, -{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, -{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, -{-68,-67,24,-33}, -}; - // ------------------------------- end copied code - - -#define PRIM_PLANE 0 -#define PRIM_CUBE 1 -#define PRIM_CIRCLE 4 -#define PRIM_CYLINDER 5 -#define PRIM_CONE 7 -#define PRIM_GRID 10 -#define PRIM_UVSPHERE 11 -#define PRIM_ICOSPHERE 12 -#define PRIM_MONKEY 13 - -static void make_prim(Object *obedit, int type, float mat[4][4], int tot, int seg, - int subdiv, float dia, float depth, int ext, int fill) -{ - /* - * type - for the type of shape - * dia - the radius for cone,sphere cylinder etc. - * depth - - * ext - extrude - * fill - end capping, and option to fill in circle - * cent[3] - center of the data. - * */ - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - EditVert *eve, *v1=NULL, *v2, *v3, *v4=NULL, *vtop, *vdown; - float phi, phid, vec[3]; - float q[4], cmat[3][3], nor[3]= {0.0, 0.0, 0.0}; - short a, b; - - EM_clear_flag_all(em, SELECT); - - phid= 2.0f*(float)M_PI/tot; - phi= .25f*(float)M_PI; - - switch(type) { - case PRIM_GRID: /* grid */ - /* clear flags */ - eve= em->verts.first; - while(eve) { - eve->f= 0; - eve= eve->next; - } - /* one segment first: the X axis */ - phi= 1.0; - phid= 2.0/((float)tot-1); - for(a=0;a<tot;a++) { - vec[0]= dia*phi; - vec[1]= - dia; - vec[2]= 0.0f; - mul_m4_v3(mat,vec); - eve= addvertlist(em, vec, NULL); - eve->f= 1+2+4; - if (a) { - addedgelist(em, eve->prev, eve, NULL); - } - phi-=phid; - } - /* extrude and translate */ - vec[0]= vec[2]= 0.0; - vec[1]= dia*phid; - mul_mat3_m4_v3(mat, vec); - - for(a=0;a<seg-1;a++) { - extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused - translateflag(em, 2, vec); - } - break; - case PRIM_UVSPHERE: /* UVsphere */ - - /* clear all flags */ - eve= em->verts.first; - while(eve) { - eve->f= 0; - eve= eve->next; - } - - /* one segment first */ - phi= 0; - phid/=2; - for(a=0; a<=tot; a++) { - vec[0]= dia*sin(phi); - vec[1]= 0.0; - vec[2]= dia*cos(phi); - eve= addvertlist(em, vec, NULL); - eve->f= 1+2+4; - if(a==0) v1= eve; - else addedgelist(em, eve->prev, eve, NULL); - phi+= phid; - } - - /* extrude and rotate */ - phi= M_PI/seg; - q[0]= cos(phi); - q[3]= sin(phi); - q[1]=q[2]= 0; - quat_to_mat3( cmat,q); - - for(a=0; a<seg; a++) { - extrudeflag_vert(obedit, em, 2, nor, 0); // nor unused - rotateflag(em, 2, v1->co, cmat); - } - - removedoublesflag(em, 4, 0, 0.0001); - - /* and now do imat */ - eve= em->verts.first; - while(eve) { - if(eve->f & SELECT) { - mul_m4_v3(mat,eve->co); - } - eve= eve->next; - } - break; - case PRIM_ICOSPHERE: /* Icosphere */ - { - EditVert *eva[12]; - EditEdge *eed; - - /* clear all flags */ - eve= em->verts.first; - while(eve) { - eve->f= 0; - eve= eve->next; - } - dia/=200; - for(a=0;a<12;a++) { - vec[0]= dia*icovert[a][0]; - vec[1]= dia*icovert[a][1]; - vec[2]= dia*icovert[a][2]; - eva[a]= addvertlist(em, vec, NULL); - eva[a]->f= 1+2; - } - for(a=0;a<20;a++) { - EditFace *evtemp; - v1= eva[ icoface[a][0] ]; - v2= eva[ icoface[a][1] ]; - v3= eva[ icoface[a][2] ]; - evtemp = addfacelist(em, v1, v2, v3, 0, NULL, NULL); - evtemp->e1->f = 1+2; - evtemp->e2->f = 1+2; - evtemp->e3->f = 1+2; - } - - dia*=200; - - for(a=1; a<subdiv; a++) esubdivideflag(obedit, em, 2, dia, 0.0, 0, 1, 0); - - /* and now do imat */ - eve= em->verts.first; - while(eve) { - if(eve->f & 2) { - mul_m4_v3(mat,eve->co); - } - eve= eve->next; - } - - // Clear the flag 2 from the edges - for(eed=em->edges.first;eed;eed=eed->next){ - if(eed->f & 2){ - eed->f &= !2; - } - } - } - break; - case PRIM_MONKEY: /* Monkey */ - { - //extern int monkeyo, monkeynv, monkeynf; - //extern signed char monkeyf[][4]; - //extern signed char monkeyv[][3]; - EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv"); - int i; - - for (i=0; i<monkeynv; i++) { - float v[3]; - v[0]= (monkeyv[i][0]+127)/128.0, v[1]= monkeyv[i][1]/128.0, v[2]= monkeyv[i][2]/128.0; - tv[i]= addvertlist(em, v, NULL); - tv[i]->f |= SELECT; - tv[monkeynv+i]= (fabs(v[0]= -v[0])<0.001)?tv[i]:addvertlist(em, v, NULL); - tv[monkeynv+i]->f |= SELECT; - } - for (i=0; i<monkeynf; i++) { - addfacelist(em, tv[monkeyf[i][0]+i-monkeyo], tv[monkeyf[i][1]+i-monkeyo], tv[monkeyf[i][2]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL); - addfacelist(em, tv[monkeynv+monkeyf[i][2]+i-monkeyo], tv[monkeynv+monkeyf[i][1]+i-monkeyo], tv[monkeynv+monkeyf[i][0]+i-monkeyo], (monkeyf[i][3]!=monkeyf[i][2])?tv[monkeynv+monkeyf[i][3]+i-monkeyo]:NULL, NULL, NULL); - } - - MEM_freeN(tv); - - /* and now do imat */ - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) { - mul_m4_v3(mat,eve->co); - } - } - recalc_editnormals(em); - } - break; - default: /* all types except grid, sphere... */ - if(type==PRIM_CONE); - else if(ext==0) - depth= 0.0f; - - /* vertices */ - vtop= vdown= v1= v2= 0; - for(b=0; b<=ext; b++) { - for(a=0; a<tot; a++) { - - vec[0]= dia*sin(phi); - vec[1]= dia*cos(phi); - vec[2]= b?depth:-depth; - - mul_m4_v3(mat, vec); - eve= addvertlist(em, vec, NULL); - eve->f= SELECT; - if(a==0) { - if(b==0) v1= eve; - else v2= eve; - } - phi+=phid; - } - } - - /* center vertices */ - /* type PRIM_CONE can only have 1 one side filled - * if the cone has no capping, dont add vtop */ - if(type == PRIM_CONE || (fill && !ELEM(type, PRIM_PLANE, PRIM_CUBE))) { - vec[0]= vec[1]= 0.0f; - vec[2]= type==PRIM_CONE ? depth : -depth; - mul_m4_v3(mat, vec); - vdown= addvertlist(em, vec, NULL); - if((ext || type==PRIM_CONE) && fill) { - vec[0]= vec[1]= 0.0f; - vec[2]= type==PRIM_CONE ? -depth : depth; - mul_m4_v3(mat,vec); - vtop= addvertlist(em, vec, NULL); - } - } else { - vdown= v1; - vtop= v2; - } - if(vtop) vtop->f= SELECT; - if(vdown) vdown->f= SELECT; - - /* top and bottom face */ - if(fill || type==PRIM_CONE) { - if(tot==4 && ELEM(type, PRIM_PLANE, PRIM_CUBE)) { - v3= v1->next->next; - if(ext) v4= v2->next->next; - - addfacelist(em, v3, v1->next, v1, v3->next, NULL, NULL); - if(ext) addfacelist(em, v2, v2->next, v4, v4->next, NULL, NULL); - - } - else { - v3= v1; - v4= v2; - for(a=1; a<tot; a++) { - addfacelist(em, vdown, v3, v3->next, 0, NULL, NULL); - v3= v3->next; - if(ext && fill) { - addfacelist(em, vtop, v4, v4->next, 0, NULL, NULL); - v4= v4->next; - } - } - if(!ELEM(type, PRIM_PLANE, PRIM_CUBE)) { - addfacelist(em, vdown, v3, v1, 0, NULL, NULL); - if(ext) addfacelist(em, vtop, v4, v2, 0, NULL, NULL); - } - } - } - else if(type==PRIM_CIRCLE) { /* we need edges for a circle */ - v3= v1; - for(a=1;a<tot;a++) { - addedgelist(em, v3, v3->next, NULL); - v3= v3->next; - } - addedgelist(em, v3, v1, NULL); - } - /* side faces */ - if(ext) { - v3= v1; - v4= v2; - for(a=1; a<tot; a++) { - addfacelist(em, v3, v3->next, v4->next, v4, NULL, NULL); - v3= v3->next; - v4= v4->next; - } - addfacelist(em, v3, v1, v2, v4, NULL, NULL); - } - else if(fill && type==PRIM_CONE) { - /* add the bottom flat area of the cone - * if capping is disabled dont bother */ - v3= v1; - for(a=1; a<tot; a++) { - addfacelist(em, vtop, v3->next, v3, 0, NULL, NULL); - v3= v3->next; - } - addfacelist(em, vtop, v1, v3, 0, NULL, NULL); - } - } - - EM_stats_update(em); - /* simple selection flush OK, based on fact it's a single model */ - EM_select_flush(em); /* flushes vertex -> edge -> face selection */ - - if(type!=PRIM_PLANE && type!=PRIM_MONKEY) - EM_recalc_normal_direction(em, 0, 0); /* otherwise monkey has eyes in wrong direction */ - - BKE_mesh_end_editmesh(obedit->data, em); -} - - -/* uses context to figure out transform for primitive */ -/* returns standard diameter */ -static float new_primitive_matrix(bContext *C, float *loc, float *rot, float primmat[][4]) -{ - Object *obedit= CTX_data_edit_object(C); - View3D *v3d =CTX_wm_view3d(C); - float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3]; - - unit_m4(primmat); - - eul_to_mat3(rmat, rot); - invert_m3(rmat); - - /* inverse transform for initial rotation and object */ - copy_m3_m4(mat, obedit->obmat); - mul_m3_m3m3(cmat, rmat, mat); - invert_m3_m3(imat, cmat); - copy_m4_m3(primmat, imat); - - /* center */ - VECCOPY(primmat[3], loc); - VECSUB(primmat[3], primmat[3], obedit->obmat[3]); - invert_m3_m3(imat, mat); - mul_m3_v3(imat, primmat[3]); - - if(v3d) return v3d->grid; - return 1.0f; -} - -/* ********* add primitive operators ************* */ - -static void make_prim_ext(bContext *C, float *loc, float *rot, int enter_editmode, - int type, int tot, int seg, - int subdiv, float dia, float depth, int ext, int fill) -{ - Object *obedit= CTX_data_edit_object(C); - int newob = 0; - float mat[4][4]; - - if(obedit==NULL || obedit->type!=OB_MESH) { - obedit= ED_object_add_type(C, OB_MESH, loc, rot, FALSE); - - /* create editmode */ - ED_object_enter_editmode(C, EM_DO_UNDO|EM_IGNORE_LAYER); /* rare cases the active layer is messed up */ - newob = 1; - } - else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA); - - dia *= new_primitive_matrix(C, loc, rot, mat); - - make_prim(obedit, type, mat, tot, seg, subdiv, dia, depth, ext, fill); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - - /* userdef */ - if (newob && !enter_editmode) { - ED_object_exit_editmode(C, EM_FREEDATA); /* adding EM_DO_UNDO messes up operator redo */ - } - WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit); -} - -static int add_primitive_plane_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */ - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_PLANE, 4, 0, 0, sqrt(2.0f), 0.0f, 0, 1); - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_plane_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Plane"; - ot->description= "Construct a filled planar mesh with 4 vertices."; - ot->idname= "MESH_OT_primitive_plane_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_plane_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_cube_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - /* sqrt(2.0f) - plane (diameter of 1.41 makes it unit size) */ - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_CUBE, 4, 0, 0, sqrt(2.0f), 1.0f, 1, 1); - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_cube_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Cube"; - ot->description= "Construct a cube mesh."; - ot->idname= "MESH_OT_primitive_cube_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_cube_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_circle_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_CIRCLE, RNA_int_get(op->ptr, "vertices"), 0, 0, - RNA_float_get(op->ptr,"radius"), 0.0f, 0, - RNA_boolean_get(op->ptr, "fill")); - - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_circle_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Circle"; - ot->description= "Construct a circle mesh."; - ot->idname= "MESH_OT_primitive_circle_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_circle_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 3, 500); - RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); - RNA_def_boolean(ot->srna, "fill", 0, "Fill", ""); - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_tube_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_CYLINDER, RNA_int_get(op->ptr, "vertices"), 0, 0, - RNA_float_get(op->ptr,"radius"), - RNA_float_get(op->ptr, "depth"), 1, - RNA_boolean_get(op->ptr, "cap_ends")); - - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_tube_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Tube"; - ot->description= "Construct a tube mesh."; - ot->idname= "MESH_OT_primitive_tube_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_tube_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500); - RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); - RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00); - RNA_def_boolean(ot->srna, "cap_ends", 1, "Cap Ends", ""); - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_cone_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_CONE, RNA_int_get(op->ptr, "vertices"), 0, 0, - RNA_float_get(op->ptr,"radius"), RNA_float_get(op->ptr, "depth"), - 0, RNA_boolean_get(op->ptr, "cap_end")); - - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_cone_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Cone"; - ot->description= "Construct a conic mesh (ends filled)."; - ot->idname= "MESH_OT_primitive_cone_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_cone_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_int(ot->srna, "vertices", 32, INT_MIN, INT_MAX, "Vertices", "", 2, 500); - RNA_def_float(ot->srna, "radius", 1.0f, 0.0, FLT_MAX, "Radius", "", 0.001, 100.00); - RNA_def_float(ot->srna, "depth", 1.0f, 0.0, FLT_MAX, "Depth", "", 0.001, 100.00); - RNA_def_boolean(ot->srna, "cap_end", 0, "Cap End", ""); - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_grid_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_GRID, RNA_int_get(op->ptr, "x_subdivisions"), - RNA_int_get(op->ptr, "y_subdivisions"), 0, - RNA_float_get(op->ptr,"size"), 0.0f, 0, 1); - - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_grid_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Grid"; - ot->description= "Construct a grid mesh."; - ot->idname= "MESH_OT_primitive_grid_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_grid_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_int(ot->srna, "x_subdivisions", 10, INT_MIN, INT_MAX, "X Subdivisions", "", 3, 1000); - RNA_def_int(ot->srna, "y_subdivisions", 10, INT_MIN, INT_MAX, "Y Subdivisions", "", 3, 1000); - RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, FLT_MAX); - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_monkey_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_MONKEY, 0, 0, 2, 0.0f, 0.0f, 0, 0); - - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_monkey_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Monkey"; - ot->description= "Construct a Suzanne mesh."; - ot->idname= "MESH_OT_primitive_monkey_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_monkey_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_UVSPHERE, RNA_int_get(op->ptr, "rings"), - RNA_int_get(op->ptr, "segments"), 0, - RNA_float_get(op->ptr,"size"), 0.0f, 0, 0); - - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add UV Sphere"; - ot->description= "Construct a UV sphere mesh."; - ot->idname= "MESH_OT_primitive_uv_sphere_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_uvsphere_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_int(ot->srna, "segments", 32, INT_MIN, INT_MAX, "Segments", "", 3, 500); - RNA_def_int(ot->srna, "rings", 24, INT_MIN, INT_MAX, "Rings", "", 3, 500); - RNA_def_float(ot->srna, "size", 1.0f, 0.0, FLT_MAX, "Size", "", 0.001, 100.00); - - ED_object_add_generic_props(ot, TRUE); -} - -static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) -{ - int enter_editmode; - float loc[3], rot[3]; - - ED_object_add_generic_get_opts(op, loc, rot, &enter_editmode); - - make_prim_ext(C, loc, rot, enter_editmode, - PRIM_ICOSPHERE, 0, 0, RNA_int_get(op->ptr, "subdivisions"), - RNA_float_get(op->ptr,"size"), 0.0f, 0, 0); - - return OPERATOR_FINISHED; -} - -void MESH_OT_primitive_ico_sphere_add(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Add Ico Sphere"; - ot->description= "Construct an Icosphere mesh."; - ot->idname= "MESH_OT_primitive_ico_sphere_add"; - - /* api callbacks */ - ot->invoke= ED_object_add_generic_invoke; - ot->exec= add_primitive_icosphere_exec; - ot->poll= ED_operator_scene_editable; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_int(ot->srna, "subdivisions", 2, 0, 6, "Subdivisions", "", 0, 8); - RNA_def_float(ot->srna, "size", 1.0f, 0.0f, FLT_MAX, "Size", "", 0.001f, 100.00); - - ED_object_add_generic_props(ot, TRUE); -} diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c deleted file mode 100644 index e6c1462bcd0..00000000000 --- a/source/blender/editors/mesh/editmesh_lib.c +++ /dev/null @@ -1,2424 +0,0 @@ -/** - * $Id: - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2004 by Blender Foundation - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/* - -editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data - -*/ - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_windowmanager_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_editVert.h" - -#include "BKE_customdata.h" -#include "BKE_context.h" -#include "BKE_global.h" -#include "BKE_mesh.h" -#include "BKE_utildefines.h" - -#include "ED_mesh.h" -#include "ED_screen.h" -#include "ED_view3d.h" - -#include "mesh_intern.h" -#include "bmesh.h" - -/* ****************** stats *************** */ - -int EM_nfaces_selected(EditMesh *em) -{ - EditFace *efa; - int count= 0; - - for (efa= em->faces.first; efa; efa= efa->next) - if (efa->f & SELECT) - count++; - - em->totfacesel= count; - - return count; -} - -int EM_nedges_selected(EditMesh *em) -{ - EditEdge *eed; - int count= 0; - - for (eed= em->edges.first; eed; eed= eed->next) - if(eed->f & SELECT) - count++; - - em->totedgesel= count; - - return count; -} - -int EM_nvertices_selected(EditMesh *em) -{ - EditVert *eve; - int count= 0; - - for (eve= em->verts.first; eve; eve= eve->next) - if (eve->f & SELECT) - count++; - - em->totvertsel= count; - - return count; -} - -void EM_stats_update(EditMesh *em) -{ - - em->totvert= BLI_countlist(&em->verts); - em->totedge= BLI_countlist(&em->edges); - em->totface= BLI_countlist(&em->faces); - - EM_nvertices_selected(em); - EM_nedges_selected(em); - EM_nfaces_selected(em); -} - -/* ************************************** */ - -/* this replaces the active flag used in uv/face mode */ -void EM_set_actFace(EditMesh *em, EditFace *efa) -{ - em->act_face = efa; -} - -EditFace *EM_get_actFace(EditMesh *em, int sloppy) -{ - if (em->act_face) { - return em->act_face; - } else if (sloppy) { - EditFace *efa= NULL; - EditSelection *ese; - - ese = em->selected.last; - for (; ese; ese=ese->prev){ - if(ese->type == EDITFACE) { - efa = (EditFace *)ese->data; - - if (efa->h) efa= NULL; - else break; - } - } - if (efa==NULL) { - for (efa= em->faces.first; efa; efa= efa->next) { - if (efa->f & SELECT) - break; - } - } - return efa; /* can still be null */ - } - return NULL; -} - -int EM_get_actSelection(EditMesh *em, EditSelection *ese) -{ - EditSelection *ese_last = em->selected.last; - EditFace *efa = EM_get_actFace(em, 0); - - ese->next = ese->prev = NULL; - - if (ese_last) { - if (ese_last->type == EDITFACE) { /* if there is an active face, use it over the last selected face */ - if (efa) { - ese->data = (void *)efa; - } else { - ese->data = ese_last->data; - } - ese->type = EDITFACE; - } else { - ese->data = ese_last->data; - ese->type = ese_last->type; - } - } else if (efa) { /* no */ - ese->data = (void *)efa; - ese->type = EDITFACE; - } else { - ese->data = NULL; - return 0; - } - return 1; -} - -/* ********* Selection History ************ */ -static int EM_check_selection(EditMesh *em, void *data) -{ - EditSelection *ese; - - for(ese = em->selected.first; ese; ese = ese->next){ - if(ese->data == data) return 1; - } - - return 0; -} - -void EM_remove_selection(EditMesh *em, void *data, int type) -{ - EditSelection *ese; - for(ese=em->selected.first; ese; ese = ese->next){ - if(ese->data == data){ - BLI_freelinkN(&(em->selected),ese); - break; - } - } -} - -void EM_store_selection(EditMesh *em, void *data, int type) -{ - EditSelection *ese; - if(!EM_check_selection(em, data)){ - ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection"); - ese->type = type; - ese->data = data; - BLI_addtail(&(em->selected),ese); - } -} - -void EM_validate_selections(EditMesh *em) -{ - EditSelection *ese, *nextese; - - ese = em->selected.first; - - while(ese){ - nextese = ese->next; - if(ese->type == EDITVERT && !(((EditVert*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); - else if(ese->type == EDITEDGE && !(((EditEdge*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); - else if(ese->type == EDITFACE && !(((EditFace*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese); - ese = nextese; - } -} - -static void EM_strip_selections(EditMesh *em) -{ - EditSelection *ese, *nextese; - if(!(em->selectmode & SCE_SELECT_VERTEX)){ - ese = em->selected.first; - while(ese){ - nextese = ese->next; - if(ese->type == EDITVERT) BLI_freelinkN(&(em->selected),ese); - ese = nextese; - } - } - if(!(em->selectmode & SCE_SELECT_EDGE)){ - ese=em->selected.first; - while(ese){ - nextese = ese->next; - if(ese->type == EDITEDGE) BLI_freelinkN(&(em->selected), ese); - ese = nextese; - } - } - if(!(em->selectmode & SCE_SELECT_FACE)){ - ese=em->selected.first; - while(ese){ - nextese = ese->next; - if(ese->type == EDITFACE) BLI_freelinkN(&(em->selected), ese); - ese = nextese; - } - } -} - -/* generic way to get data from an EditSelection type -These functions were written to be used by the Modifier widget when in Rotate about active mode, -but can be used anywhere. -EM_editselection_center -EM_editselection_normal -EM_editselection_plane -*/ -void EM_editselection_center(float *center, EditSelection *ese) -{ - if (ese->type==EDITVERT) { - EditVert *eve= ese->data; - copy_v3_v3(center, eve->co); - } else if (ese->type==EDITEDGE) { - EditEdge *eed= ese->data; - add_v3_v3v3(center, eed->v1->co, eed->v2->co); - mul_v3_fl(center, 0.5); - } else if (ese->type==EDITFACE) { - EditFace *efa= ese->data; - copy_v3_v3(center, efa->cent); - } -} - -void EM_editselection_normal(float *normal, EditSelection *ese) -{ - if (ese->type==EDITVERT) { - EditVert *eve= ese->data; - copy_v3_v3(normal, eve->no); - } else if (ese->type==EDITEDGE) { - EditEdge *eed= ese->data; - float plane[3]; /* need a plane to correct the normal */ - float vec[3]; /* temp vec storage */ - - add_v3_v3v3(normal, eed->v1->no, eed->v2->no); - sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); - - /* the 2 vertex normals will be close but not at rightangles to the edge - for rotate about edge we want them to be at right angles, so we need to - do some extra colculation to correct the vert normals, - we need the plane for this */ - cross_v3_v3v3(vec, normal, plane); - cross_v3_v3v3(normal, plane, vec); - normalize_v3(normal); - - } else if (ese->type==EDITFACE) { - EditFace *efa= ese->data; - copy_v3_v3(normal, efa->n); - } -} - -/* Calculate a plane that is rightangles to the edge/vert/faces normal -also make the plane run allong an axis that is related to the geometry, -because this is used for the manipulators Y axis.*/ -void EM_editselection_plane(float *plane, EditSelection *ese) -{ - if (ese->type==EDITVERT) { - EditVert *eve= ese->data; - float vec[3]={0,0,0}; - - if (ese->prev) { /*use previously selected data to make a usefull vertex plane */ - EM_editselection_center(vec, ese->prev); - sub_v3_v3v3(plane, vec, eve->co); - } else { - /* make a fake plane thats at rightangles to the normal - we cant make a crossvec from a vec thats the same as the vec - unlikely but possible, so make sure if the normal is (0,0,1) - that vec isnt the same or in the same direction even.*/ - if (eve->no[0]<0.5) vec[0]=1; - else if (eve->no[1]<0.5) vec[1]=1; - else vec[2]=1; - cross_v3_v3v3(plane, eve->no, vec); - } - } else if (ese->type==EDITEDGE) { - EditEdge *eed= ese->data; - - /*the plane is simple, it runs allong the edge - however selecting different edges can swap the direction of the y axis. - this makes it less likely for the y axis of the manipulator - (running along the edge).. to flip less often. - at least its more pradictable */ - if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */ - sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); - else - sub_v3_v3v3(plane, eed->v1->co, eed->v2->co); - - } else if (ese->type==EDITFACE) { - EditFace *efa= ese->data; - float vec[3]; - if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/ - float vecA[3], vecB[3]; - sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co); - sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co); - add_v3_v3v3(plane, vecA, vecB); - - sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co); - sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co); - add_v3_v3v3(vec, vecA, vecB); - /*use the biggest edge length*/ - if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) - copy_v3_v3(plane, vec); - } else { - /*start with v1-2 */ - sub_v3_v3v3(plane, efa->v1->co, efa->v2->co); - - /*test the edge between v2-3, use if longer */ - sub_v3_v3v3(vec, efa->v2->co, efa->v3->co); - if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) - copy_v3_v3(plane, vec); - - /*test the edge between v1-3, use if longer */ - sub_v3_v3v3(vec, efa->v3->co, efa->v1->co); - if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]) - copy_v3_v3(plane, vec); - } - } - normalize_v3(plane); -} - - - -void EM_select_face(EditFace *efa, int sel) -{ - if(sel) { - efa->f |= SELECT; - efa->e1->f |= SELECT; - efa->e2->f |= SELECT; - efa->e3->f |= SELECT; - if(efa->e4) efa->e4->f |= SELECT; - efa->v1->f |= SELECT; - efa->v2->f |= SELECT; - efa->v3->f |= SELECT; - if(efa->v4) efa->v4->f |= SELECT; - } - else { - efa->f &= ~SELECT; - efa->e1->f &= ~SELECT; - efa->e2->f &= ~SELECT; - efa->e3->f &= ~SELECT; - if(efa->e4) efa->e4->f &= ~SELECT; - efa->v1->f &= ~SELECT; - efa->v2->f &= ~SELECT; - efa->v3->f &= ~SELECT; - if(efa->v4) efa->v4->f &= ~SELECT; - } -} - -void EM_select_edge(EditEdge *eed, int sel) -{ - if(sel) { - eed->f |= SELECT; - eed->v1->f |= SELECT; - eed->v2->f |= SELECT; - } - else { - eed->f &= ~SELECT; - eed->v1->f &= ~SELECT; - eed->v2->f &= ~SELECT; - } -} - -void EM_select_face_fgon(EditMesh *em, EditFace *efa, int val) -{ - short index=0; - - if(efa->fgonf==0) EM_select_face(efa, val); - else { - if(efa->e1->fgoni) index= efa->e1->fgoni; - if(efa->e2->fgoni) index= efa->e2->fgoni; - if(efa->e3->fgoni) index= efa->e3->fgoni; - if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni; - - if(index==0) printf("wrong fgon select\n"); - - // select all ngon faces with index - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->fgonf) { - if(efa->e1->fgoni==index || efa->e2->fgoni==index || - efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) { - EM_select_face(efa, val); - } - } - } - } -} - - -/* only vertices */ -int faceselectedOR(EditFace *efa, int flag) -{ - if ((efa->v1->f | efa->v2->f | efa->v3->f | (efa->v4?efa->v4->f:0))&flag) { - return 1; - } else { - return 0; - } -} - -// replace with (efa->f & SELECT) -int faceselectedAND(EditFace *efa, int flag) -{ - if ((efa->v1->f & efa->v2->f & efa->v3->f & (efa->v4?efa->v4->f:flag))&flag) { - return 1; - } else { - return 0; - } -} - -void EM_clear_flag_all(EditMesh *em, int flag) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag; - for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag; - for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag; - - if(flag & SELECT) { - BLI_freelistN(&(em->selected)); - em->totvertsel= em->totedgesel= em->totfacesel= 0; - } -} - -void EM_set_flag_all(EditMesh *em, int flag) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag; - for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag; - for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag; - - if(flag & SELECT) { - em->totvertsel= em->totvert; - em->totedgesel= em->totedge; - em->totfacesel= em->totface; - } -} - -/* flush for changes in vertices only */ -void EM_deselect_flush(EditMesh *em) -{ - EditEdge *eed; - EditFace *efa; - - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->v1->f & eed->v2->f & SELECT); - else eed->f &= ~SELECT; - } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->v4) { - if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ); - else efa->f &= ~SELECT; - } - else { - if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ); - else efa->f &= ~SELECT; - } - } - EM_nedges_selected(em); - EM_nfaces_selected(em); -} - - -/* flush selection to edges & faces */ - -/* this only based on coherent selected vertices, for example when adding new - objects. call clear_flag_all() before you select vertices to be sure it ends OK! - -*/ - -void EM_select_flush(EditMesh *em) -{ - EditEdge *eed; - EditFace *efa; - - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT; - } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->v4) { - if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT; - } - else { - if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT; - } - } - EM_nedges_selected(em); - EM_nfaces_selected(em); -} - -/* when vertices or edges can be selected, also make fgon consistent */ -static void check_fgons_selection(EditMesh *em) -{ - EditFace *efa, *efan; - EditEdge *eed; - ListBase *lbar; - int sel, desel, index, totfgon= 0; - - /* count amount of fgons */ - for(eed= em->edges.first; eed; eed= eed->next) - if(eed->fgoni>totfgon) totfgon= eed->fgoni; - - if(totfgon==0) return; - - lbar= MEM_callocN((totfgon+1)*sizeof(ListBase), "listbase array"); - - /* put all fgons in lbar */ - for(efa= em->faces.first; efa; efa= efan) { - efan= efa->next; - index= efa->e1->fgoni; - if(index==0) index= efa->e2->fgoni; - if(index==0) index= efa->e3->fgoni; - if(index==0 && efa->e4) index= efa->e4->fgoni; - if(index) { - BLI_remlink(&em->faces, efa); - BLI_addtail(&lbar[index], efa); - } - } - - /* now check the fgons */ - for(index=1; index<=totfgon; index++) { - /* we count on vertices/faces/edges being set OK, so we only have to set ngon itself */ - sel= desel= 0; - for(efa= lbar[index].first; efa; efa= efa->next) { - if(efa->e1->fgoni==0) { - if(efa->e1->f & SELECT) sel++; - else desel++; - } - if(efa->e2->fgoni==0) { - if(efa->e2->f & SELECT) sel++; - else desel++; - } - if(efa->e3->fgoni==0) { - if(efa->e3->f & SELECT) sel++; - else desel++; - } - if(efa->e4 && efa->e4->fgoni==0) { - if(efa->e4->f & SELECT) sel++; - else desel++; - } - - if(sel && desel) break; - } - - if(sel && desel) sel= 0; - else if(sel) sel= 1; - else sel= 0; - - /* select/deselect and put back */ - for(efa= lbar[index].first; efa; efa= efa->next) { - if(sel) efa->f |= SELECT; - else efa->f &= ~SELECT; - } - addlisttolist(&em->faces, &lbar[index]); - } - - MEM_freeN(lbar); -} - - -/* flush to edges & faces */ - -/* based on select mode it selects edges/faces - assumed is that verts/edges/faces were properly selected themselves - with the calls above -*/ - -void EM_selectmode_flush(EditMesh *em) -{ - EditEdge *eed; - EditFace *efa; - - // flush to edges & faces - if(em->selectmode & SCE_SELECT_VERTEX) { - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT; - else eed->f &= ~SELECT; - } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->v4) { - if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT; - else efa->f &= ~SELECT; - } - else { - if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT; - else efa->f &= ~SELECT; - } - } - } - // flush to faces - else if(em->selectmode & SCE_SELECT_EDGE) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e4) { - if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT; - else efa->f &= ~SELECT; - } - else { - if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT; - else efa->f &= ~SELECT; - } - } - } - // make sure selected faces have selected edges too, for extrude (hack?) - else if(em->selectmode & SCE_SELECT_FACE) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) EM_select_face(efa, 1); - } - } - - if(!(em->selectmode & SCE_SELECT_FACE)) - check_fgons_selection(em); - - EM_nvertices_selected(em); - EM_nedges_selected(em); - EM_nfaces_selected(em); -} - -void EM_convertsel(EditMesh *em, short oldmode, short selectmode) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - /*clear flags*/ - for(eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0; - for(eed= em->edges.first; eed; eed= eed->next) eed->f1 = 0; - for(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0; - - /*have to find out what the selectionmode was previously*/ - if(oldmode == SCE_SELECT_VERTEX) { - if(selectmode == SCE_SELECT_EDGE){ - /*select all edges associated with every selected vertex*/ - for(eed= em->edges.first; eed; eed= eed->next){ - if(eed->v1->f&SELECT) eed->f1 = 1; - else if(eed->v2->f&SELECT) eed->f1 = 1; - } - - for(eed= em->edges.first; eed; eed= eed->next){ - if(eed->f1 == 1) EM_select_edge(eed,1); - } - } - else if(selectmode == SCE_SELECT_FACE){ - /*select all faces associated with every selected vertex*/ - for(efa= em->faces.first; efa; efa= efa->next){ - if(efa->v1->f&SELECT) efa->f1 = 1; - else if(efa->v2->f&SELECT) efa->f1 = 1; - else if(efa->v3->f&SELECT) efa->f1 = 1; - else{ - if(efa->v4){ - if(efa->v4->f&SELECT) efa->f1 =1; - } - } - } - for(efa= em->faces.first; efa; efa= efa->next){ - if(efa->f1 == 1) EM_select_face(efa,1); - } - } - } - - if(oldmode == SCE_SELECT_EDGE){ - if(selectmode == SCE_SELECT_FACE){ - for(efa= em->faces.first; efa; efa= efa->next){ - if(efa->e1->f&SELECT) efa->f1 = 1; - else if(efa->e2->f&SELECT) efa->f1 = 1; - else if(efa->e3->f&SELECT) efa->f1 = 1; - else if(efa->e4){ - if(efa->e4->f&SELECT) efa->f1 = 1; - } - } - for(efa= em->faces.first; efa; efa= efa->next){ - if(efa->f1 == 1) EM_select_face(efa,1); - } - } - } - - check_fgons_selection(em); - - EM_nvertices_selected(em); - EM_nedges_selected(em); - EM_nfaces_selected(em); -} - -/* when switching select mode, makes sure selection is consistent for editing */ -/* also for paranoia checks to make sure edge or face mode works */ -void EM_selectmode_set(EditMesh *em) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - EM_strip_selections(em); /*strip EditSelections from em->selected that are not relevant to new mode*/ - - if(em->selectmode & SCE_SELECT_VERTEX) { - /* vertices -> edges -> faces */ - for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT; - for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~SELECT; - - EM_select_flush(em); - } - else if(em->selectmode & SCE_SELECT_EDGE) { - /* deselect vertices, and select again based on edge select */ - for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT; - for(eed= em->edges.first; eed; eed= eed->next) - if(eed->f & SELECT) EM_select_edge(eed, 1); - /* selects faces based on edge status */ - EM_selectmode_flush(em); - } - else if(em->selectmode & SCE_SELECT_FACE) { - /* deselect eges, and select again based on face select */ - for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0); - - for(efa= em->faces.first; efa; efa= efa->next) - if(efa->f & SELECT) EM_select_face(efa, 1); - } - - EM_nvertices_selected(em); - EM_nedges_selected(em); - EM_nfaces_selected(em); -} - -/* paranoia check, actually only for entering editmode. rule: -- vertex hidden, always means edge is hidden too -- edge hidden, always means face is hidden too -- face hidden, dont change anything -*/ -void EM_hide_reset(EditMesh *em) -{ - EditEdge *eed; - EditFace *efa; - - for(eed= em->edges.first; eed; eed= eed->next) - if(eed->v1->h || eed->v2->h) eed->h |= 1; - - for(efa= em->faces.first; efa; efa= efa->next) - if((efa->e1->h & 1) || (efa->e2->h & 1) || (efa->e3->h & 1) || (efa->e4 && (efa->e4->h & 1))) - efa->h= 1; - -} - -void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *eve, float fac) -{ - void *src[2]; - float w[2]; - - if (v1->data && v2->data) { - src[0]= v1->data; - src[1]= v2->data; - w[0] = 1.0f-fac; - w[1] = fac; - - CustomData_em_interp(&em->vdata, src, w, NULL, 2, eve->data); - } -} - -void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4) -{ - float w[2][4][4]; - void *src[2]; - int count = (efa2)? 2: 1; - - if (efa1->data) { - /* set weights for copying from corners directly to other corners */ - memset(w, 0, sizeof(w)); - - w[i1/4][0][i1%4]= 1.0f; - w[i2/4][1][i2%4]= 1.0f; - w[i3/4][2][i3%4]= 1.0f; - if (i4 != -1) - w[i4/4][3][i4%4]= 1.0f; - - src[0]= efa1->data; - src[1]= (efa2)? efa2->data: NULL; - - CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data); - } -} - -EditFace *EM_face_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4) -{ - EditFace *efan; - EditVert **v[2]; - - v[0]= &efa1->v1; - v[1]= (efa2)? &efa2->v1: NULL; - - efan= addfacelist(em, v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4], - (i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL); - - EM_data_interp_from_faces(em, efa1, efa2, efan, i1, i2, i3, i4); - - return efan; -} - -static void update_data_blocks(EditMesh *em, CustomData *olddata, CustomData *data) -{ - EditFace *efa; - EditVert *eve; - void *block; - - if (data == &em->vdata) { - for(eve= em->verts.first; eve; eve= eve->next) { - block = NULL; - CustomData_em_set_default(data, &block); - CustomData_em_copy_data(olddata, data, eve->data, &block); - CustomData_em_free_block(olddata, &eve->data); - eve->data= block; - } - } - else if (data == &em->fdata) { - for(efa= em->faces.first; efa; efa= efa->next) { - block = NULL; - CustomData_em_set_default(data, &block); - CustomData_em_copy_data(olddata, data, efa->data, &block); - CustomData_em_free_block(olddata, &efa->data); - efa->data= block; - } - } -} - -void EM_add_data_layer(EditMesh *em, CustomData *data, int type) -{ - CustomData olddata; - - olddata= *data; - olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL; - CustomData_add_layer(data, type, CD_CALLOC, NULL, 0); - - update_data_blocks(em, &olddata, data); - if (olddata.layers) MEM_freeN(olddata.layers); -} - -void EM_free_data_layer(EditMesh *em, CustomData *data, int type) -{ - CustomData olddata; - - olddata= *data; - olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL; - CustomData_free_layer_active(data, type, 0); - - update_data_blocks(em, &olddata, data); - if (olddata.layers) MEM_freeN(olddata.layers); -} - -/* ******** EXTRUDE ********* */ - -static void add_normal_aligned(float *nor, float *add) -{ - if( INPR(nor, add) < -0.9999f) - sub_v3_v3v3(nor, nor, add); - else - add_v3_v3v3(nor, nor, add); -} - -static void set_edge_directions_f2(EditMesh *em, int val) -{ - EditFace *efa; - int do_all= 1; - - /* edge directions are used for extrude, to detect direction of edges that make new faces */ - /* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */ - /* the val argument differs... so we need it as arg */ - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - do_all= 0; - if(efa->e1->f2<val) { - if(efa->e1->v1 == efa->v1) efa->e1->dir= 0; - else efa->e1->dir= 1; - } - if(efa->e2->f2<val) { - if(efa->e2->v1 == efa->v2) efa->e2->dir= 0; - else efa->e2->dir= 1; - } - if(efa->e3->f2<val) { - if(efa->e3->v1 == efa->v3) efa->e3->dir= 0; - else efa->e3->dir= 1; - } - if(efa->e4 && efa->e4->f2<val) { - if(efa->e4->v1 == efa->v4) efa->e4->dir= 0; - else efa->e4->dir= 1; - } - } - } - /* ok, no faces done... then we at least set it for exterior edges */ - if(do_all) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e1->v1 == efa->v1) efa->e1->dir= 0; - else efa->e1->dir= 1; - if(efa->e2->v1 == efa->v2) efa->e2->dir= 0; - else efa->e2->dir= 1; - if(efa->e3->v1 == efa->v3) efa->e3->dir= 0; - else efa->e3->dir= 1; - if(efa->e4) { - if(efa->e4->v1 == efa->v4) efa->e4->dir= 0; - else efa->e4->dir= 1; - } - } - } -} - -/* individual face extrude */ -/* will use vertex normals for extrusion directions, so *nor is unaffected */ -short extrudeflag_face_indiv(EditMesh *em, short flag, float *nor) -{ - EditVert *eve, *v1, *v2, *v3, *v4; - EditEdge *eed; - EditFace *efa, *nextfa; - - if(em==NULL) return 0; - - /* selected edges with 1 or more selected face become faces */ - /* selected faces each makes new faces */ - /* always remove old faces, keeps volumes manifold */ - /* select the new extrusion, deselect old */ - - /* step 1; init, count faces in edges */ - recalc_editnormals(em); - - for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; // new select flag - - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f2= 0; // amount of unselected faces - } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT); - else { - efa->e1->f2++; - efa->e2->f2++; - efa->e3->f2++; - if(efa->e4) efa->e4->f2++; - } - } - - /* step 2: make new faces from faces */ - for(efa= em->faces.last; efa; efa= efa->prev) { - if(efa->f & SELECT) { - v1= addvertlist(em, efa->v1->co, efa->v1); - v2= addvertlist(em, efa->v2->co, efa->v2); - v3= addvertlist(em, efa->v3->co, efa->v3); - - v1->f1= v2->f1= v3->f1= 1; - VECCOPY(v1->no, efa->n); - VECCOPY(v2->no, efa->n); - VECCOPY(v3->no, efa->n); - if(efa->v4) { - v4= addvertlist(em, efa->v4->co, efa->v4); - v4->f1= 1; - VECCOPY(v4->no, efa->n); - } - else v4= NULL; - - /* side faces, clockwise */ - addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL); - addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL); - if(efa->v4) { - addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL); - addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL); - } - else { - addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL); - } - /* top face */ - addfacelist(em, v1, v2, v3, v4, efa, NULL); - } - } - - /* step 3: remove old faces */ - efa= em->faces.first; - while(efa) { - nextfa= efa->next; - if(efa->f & SELECT) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextfa; - } - - /* step 4: redo selection */ - EM_clear_flag_all(em, SELECT); - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f1) eve->f |= SELECT; - } - - EM_select_flush(em); - - return 'n'; -} - - -/* extrudes individual edges */ -/* nor is filled with constraint vector */ -short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL; - for(eed= em->edges.first; eed; eed= eed->next) { - eed->tmp.f = NULL; - eed->f2= ((eed->f & flag)!=0); - } - - set_edge_directions_f2(em, 2); - - /* sample for next loop */ - for(efa= em->faces.first; efa; efa= efa->next) { - efa->e1->tmp.f = efa; - efa->e2->tmp.f = efa; - efa->e3->tmp.f = efa; - if(efa->e4) efa->e4->tmp.f = efa; - } - /* make the faces */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & flag) { - if(eed->v1->tmp.v == NULL) - eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1); - if(eed->v2->tmp.v == NULL) - eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2); - - if(eed->dir==1) - addfacelist(em, eed->v1, eed->v2, - eed->v2->tmp.v, eed->v1->tmp.v, - eed->tmp.f, NULL); - else - addfacelist(em, eed->v2, eed->v1, - eed->v1->tmp.v, eed->v2->tmp.v, - eed->tmp.f, NULL); - - /* for transform */ - if(eed->tmp.f) { - efa = eed->tmp.f; - if (efa->f & SELECT) add_normal_aligned(nor, efa->n); - } - } - } - normalize_v3(nor); - - /* set correct selection */ - EM_clear_flag_all(em, SELECT); - for(eve= em->verts.last; eve; eve= eve->prev) { - if(eve->tmp.v) { - eve->tmp.v->f |= flag; - } - } - - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->v1->f & eed->v2->f & flag) eed->f |= flag; - } - - if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab - return 'n'; // n is for normal constraint -} - -/* extrudes individual vertices */ -short extrudeflag_verts_indiv(EditMesh *em, short flag, float *nor) -{ - EditVert *eve; - - /* make the edges */ - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & flag) { - eve->tmp.v = addvertlist(em, eve->co, eve); - addedgelist(em, eve, eve->tmp.v, NULL); - } - else eve->tmp.v = NULL; - } - - /* set correct selection */ - EM_clear_flag_all(em, SELECT); - - for(eve= em->verts.last; eve; eve= eve->prev) - if (eve->tmp.v) - eve->tmp.v->f |= flag; - - return 'g'; // g is grab -} - -short BM_extrude_edgeflag(Object *obedit, BMesh *bm, int eflag, float *nor) -{ - BMIter iter; - BMOIter siter; - BMOperator extop; - BMEdge *edge; - BMFace *f; - void *el; - ModifierData *md; - int flag; - - switch (eflag) { - case SELECT: - flag = BM_SELECT; - break; - default: - flag = BM_SELECT; - break; - } - - for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);f;f=BMIter_Step(&iter)) { - add_normal_aligned(nor, f->no); - } - normalize_v3(nor); - - BMO_Init_Op(&extop, "extrudefaceregion"); - BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein", - flag, BM_VERT|BM_EDGE|BM_FACE); - - for (edge=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); edge; edge=BMIter_Step(&iter)) { - BM_Select_Edge(bm, edge, 0); - } - - for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL); f; f=BMIter_Step(&iter)) { - BM_Select_Face(bm, f, 0); - } - - /* If a mirror modifier with clipping is on, we need to adjust some - * of the cases above to handle edges on the line of symmetry. - */ - md = obedit->modifiers.first; - for (; md; md=md->next) { - if (md->type==eModifierType_Mirror) { - MirrorModifierData *mmd = (MirrorModifierData*) md; - - if(mmd->flag & MOD_MIR_CLIPPING) { - float mtx[4][4]; - if (mmd->mirror_ob) { - float imtx[4][4]; - invert_m4_m4(imtx, mmd->mirror_ob->obmat); - mul_m4_m4m4(mtx, obedit->obmat, imtx); - } - - for (edge=BMIter_New(&iter,bm,BM_EDGES_OF_MESH,NULL); - edge; edge=BMIter_Step(&iter)) - { - if(edge->head.flag & flag) { - float co1[3], co2[3]; - - copy_v3_v3(co1, edge->v1->co); - copy_v3_v3(co2, edge->v2->co); - - if (mmd->mirror_ob) { - mul_v3_m4v3(co1, mtx, co1); - mul_v3_m4v3(co2, mtx, co2); - } - - if (mmd->flag & MOD_MIR_AXIS_X) - if ( (fabs(co1[0]) < mmd->tolerance) && - (fabs(co2[0]) < mmd->tolerance) ) - BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); - - if (mmd->flag & MOD_MIR_AXIS_Y) - if ( (fabs(co1[1]) < mmd->tolerance) && - (fabs(co2[1]) < mmd->tolerance) ) - BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); - - if (mmd->flag & MOD_MIR_AXIS_Z) - if ( (fabs(co1[2]) < mmd->tolerance) && - (fabs(co2[2]) < mmd->tolerance) ) - BMO_Insert_MapPointer(bm, &extop, "exclude", edge, NULL); - } - } - } - } - } - - - BMO_Exec_Op(bm, &extop); - - el = BMO_IterNew(&siter, bm, &extop, "geomout", BM_ALL); - for (; el; el=BMO_IterStep(&siter)) { - BM_Select(bm, el, 1); - } - - BMO_Finish_Op(bm, &extop); - - if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab - return 'n'; // normal constraint - -} - - -static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor) { - short ret; - EditMesh *em2; - BMesh *bm = editmesh_to_bmesh(em); - - ret = BM_extrude_edgeflag(obedit, bm, flag, nor); - em2 = bmesh_to_editmesh(bm); - - set_editMesh(em, em2); - MEM_freeN(em2); - - EM_select_flush(em); - - return ret; -} - -/* this is actually a recode of extrudeflag(), using proper edge/face select */ -/* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */ -static short extrudeflag_edge_old(Object *obedit, EditMesh *em, short flag, float *nor) -{ - /* all select edges/faces: extrude */ - /* old select is cleared, in new ones it is set */ - EditVert *eve, *nextve; - EditEdge *eed, *nexted; - EditFace *efa, *nextfa, *efan; - short del_old= 0; - ModifierData *md; - - if(em==NULL) return 0; - - md = obedit->modifiers.first; - - /* selected edges with 0 or 1 selected face become faces */ - /* selected faces generate new faces */ - - /* if *one* selected face has edge with unselected face; remove old selected faces */ - - /* if selected edge is not used anymore; remove */ - /* if selected vertex is not used anymore: remove */ - - /* select the new extrusion, deselect old */ - - - /* step 1; init, count faces in edges */ - recalc_editnormals(em); - - for(eve= em->verts.first; eve; eve= eve->next) { - eve->tmp.v = NULL; - eve->f1= 0; - } - - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; // amount of unselected faces - eed->f2= 0; // amount of selected faces - if(eed->f & SELECT) { - eed->v1->f1= 1; // we call this 'selected vertex' now - eed->v2->f1= 1; - } - eed->tmp.f = NULL; // here we tuck face pointer, as sample - } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f & SELECT) { - efa->e1->f2++; - efa->e2->f2++; - efa->e3->f2++; - if(efa->e4) efa->e4->f2++; - - // sample for next loop - efa->e1->tmp.f = efa; - efa->e2->tmp.f = efa; - efa->e3->tmp.f = efa; - if(efa->e4) efa->e4->tmp.f = efa; - } - else { - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - } - - /* If a mirror modifier with clipping is on, we need to adjust some - * of the cases above to handle edges on the line of symmetry. - */ - for (; md; md=md->next) { - if (md->type==eModifierType_Mirror) { - MirrorModifierData *mmd = (MirrorModifierData*) md; - - if(mmd->flag & MOD_MIR_CLIPPING) { - float mtx[4][4]; - if (mmd->mirror_ob) { - float imtx[4][4]; - invert_m4_m4(imtx, mmd->mirror_ob->obmat); - mul_m4_m4m4(mtx, obedit->obmat, imtx); - } - - for (eed= em->edges.first; eed; eed= eed->next) { - if(eed->f2 == 1) { - float co1[3], co2[3]; - - copy_v3_v3(co1, eed->v1->co); - copy_v3_v3(co2, eed->v2->co); - - if (mmd->mirror_ob) { - mul_v3_m4v3(co1, mtx, co1); - mul_v3_m4v3(co2, mtx, co2); - } - - if (mmd->flag & MOD_MIR_AXIS_X) - if ( (fabs(co1[0]) < mmd->tolerance) && - (fabs(co2[0]) < mmd->tolerance) ) - ++eed->f2; - - if (mmd->flag & MOD_MIR_AXIS_Y) - if ( (fabs(co1[1]) < mmd->tolerance) && - (fabs(co2[1]) < mmd->tolerance) ) - ++eed->f2; - - if (mmd->flag & MOD_MIR_AXIS_Z) - if ( (fabs(co1[2]) < mmd->tolerance) && - (fabs(co2[2]) < mmd->tolerance) ) - ++eed->f2; - } - } - } - } - } - - set_edge_directions_f2(em, 2); - - /* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */ - for(efa= em->faces.last; efa; efa= efa->prev) { - if(efa->f & SELECT) { - if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) { - del_old= 1; - break; - } - } - } - - /* step 2: make new faces from edges */ - for(eed= em->edges.last; eed; eed= eed->prev) { - if(eed->f & SELECT) { - if(eed->f2<2) { - if(eed->v1->tmp.v == NULL) - eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1); - if(eed->v2->tmp.v == NULL) - eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2); - - /* if del_old, the preferred normal direction is exact - * opposite as for keep old faces - */ - if(eed->dir!=del_old) - addfacelist(em, eed->v1, eed->v2, - eed->v2->tmp.v, eed->v1->tmp.v, - eed->tmp.f, NULL); - else - addfacelist(em, eed->v2, eed->v1, - eed->v1->tmp.v, eed->v2->tmp.v, - eed->tmp.f, NULL); - } - } - } - - /* step 3: make new faces from faces */ - for(efa= em->faces.last; efa; efa= efa->prev) { - if(efa->f & SELECT) { - if (efa->v1->tmp.v == NULL) - efa->v1->tmp.v = addvertlist(em, efa->v1->co, efa->v1); - if (efa->v2->tmp.v ==NULL) - efa->v2->tmp.v = addvertlist(em, efa->v2->co, efa->v2); - if (efa->v3->tmp.v ==NULL) - efa->v3->tmp.v = addvertlist(em, efa->v3->co, efa->v3); - if (efa->v4 && (efa->v4->tmp.v == NULL)) - efa->v4->tmp.v = addvertlist(em, efa->v4->co, efa->v4); - - if(del_old==0) { // keep old faces means flipping normal - if(efa->v4) - efan = addfacelist(em, efa->v4->tmp.v, efa->v3->tmp.v, - efa->v2->tmp.v, efa->v1->tmp.v, efa, efa); - else - efan = addfacelist(em, efa->v3->tmp.v, efa->v2->tmp.v, - efa->v1->tmp.v, NULL, efa, efa); - } - else { - if(efa->v4) - efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v, - efa->v3->tmp.v, efa->v4->tmp.v, efa, efa); - else - efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v, - efa->v3->tmp.v, NULL, efa, efa); - } - - if (em->act_face == efa) { - em->act_face = efan; - } - - /* for transform */ - add_normal_aligned(nor, efa->n); - } - } - - if(del_old) { - - /* step 4: remove old faces, if del_old */ - efa= em->faces.first; - while(efa) { - nextfa= efa->next; - if(efa->f & SELECT) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextfa; - } - - - /* step 5: remove selected unused edges */ - /* start tagging again */ - for(eed= em->edges.first; eed; eed= eed->next) eed->f1=0; - for(efa= em->faces.first; efa; efa= efa->next) { - efa->e1->f1= 1; - efa->e2->f1= 1; - efa->e3->f1= 1; - if(efa->e4) efa->e4->f1= 1; - } - /* remove */ - eed= em->edges.first; - while(eed) { - nexted= eed->next; - if(eed->f & SELECT) { - if(eed->f1==0) { - remedge(em, eed); - free_editedge(em, eed); - } - } - eed= nexted; - } - - /* step 6: remove selected unused vertices */ - for(eed= em->edges.first; eed; eed= eed->next) - eed->v1->f1= eed->v2->f1= 0; - - eve= em->verts.first; - while(eve) { - nextve= eve->next; - if(eve->f1) { - // hack... but we need it for step 7, redoing selection - if(eve->tmp.v) eve->tmp.v->tmp.v= eve->tmp.v; - - BLI_remlink(&em->verts, eve); - free_editvert(em, eve); - } - eve= nextve; - } - } - - normalize_v3(nor); // translation normal grab - - /* step 7: redo selection */ - EM_clear_flag_all(em, SELECT); - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->tmp.v) { - eve->tmp.v->f |= SELECT; - } - } - - EM_select_flush(em); - - if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab - return 'n'; // normal constraint -} - -short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor, int all) -{ - /* all verts/edges/faces with (f & 'flag'): extrude */ - /* from old verts, 'flag' is cleared, in new ones it is set */ - EditVert *eve, *v1, *v2, *v3, *v4, *nextve; - EditEdge *eed, *e1, *e2, *e3, *e4, *nexted; - EditFace *efa, *efa2, *nextvl; - short sel=0, del_old= 0, is_face_sel=0; - ModifierData *md; - - if(em==NULL) return 0; - - md = obedit->modifiers.first; - - /* clear vert flag f1, we use this to detect a loose selected vertice */ - eve= em->verts.first; - while(eve) { - if(eve->f & flag) eve->f1= 1; - else eve->f1= 0; - eve= eve->next; - } - /* clear edges counter flag, if selected we set it at 1 */ - eed= em->edges.first; - while(eed) { - if( (eed->v1->f & flag) && (eed->v2->f & flag) ) { - eed->f2= 1; - eed->v1->f1= 0; - eed->v2->f1= 0; - } - else eed->f2= 0; - - eed->f1= 1; /* this indicates it is an 'old' edge (in this routine we make new ones) */ - eed->tmp.f = NULL; /* used as sample */ - - eed= eed->next; - } - - /* we set a flag in all selected faces, and increase the associated edge counters */ - - efa= em->faces.first; - while(efa) { - efa->f1= 0; - - if(faceselectedAND(efa, flag)) { - e1= efa->e1; - e2= efa->e2; - e3= efa->e3; - e4= efa->e4; - - if(e1->f2 < 3) e1->f2++; - if(e2->f2 < 3) e2->f2++; - if(e3->f2 < 3) e3->f2++; - if(e4 && e4->f2 < 3) e4->f2++; - - efa->f1= 1; - is_face_sel= 1; // for del_old - } - else if(faceselectedOR(efa, flag)) { - e1= efa->e1; - e2= efa->e2; - e3= efa->e3; - e4= efa->e4; - - if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2; - if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2; - if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2; - if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2; - } - - // sample for next loop - efa->e1->tmp.f = efa; - efa->e2->tmp.f = efa; - efa->e3->tmp.f = efa; - if(efa->e4) efa->e4->tmp.f = efa; - - efa= efa->next; - } - - set_edge_directions_f2(em, 3); - - /* the current state now is: - eve->f1==1: loose selected vertex - - eed->f2==0 : edge is not selected, no extrude - eed->f2==1 : edge selected, is not part of a face, extrude - eed->f2==2 : edge selected, is part of 1 face, extrude - eed->f2==3 : edge selected, is part of more faces, no extrude - - eed->f1==0: new edge - eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove - eed->f1==2: edge selected, part of a partially selected face - - efa->f1==1 : duplicate this face - */ - - /* If a mirror modifier with clipping is on, we need to adjust some - * of the cases above to handle edges on the line of symmetry. - */ - for (; md; md=md->next) { - if (md->type==eModifierType_Mirror) { - MirrorModifierData *mmd = (MirrorModifierData*) md; - - if(mmd->flag & MOD_MIR_CLIPPING) { - float mtx[4][4]; - if (mmd->mirror_ob) { - float imtx[4][4]; - invert_m4_m4(imtx, mmd->mirror_ob->obmat); - mul_m4_m4m4(mtx, obedit->obmat, imtx); - } - - for (eed= em->edges.first; eed; eed= eed->next) { - if(eed->f2 == 2) { - float co1[3], co2[3]; - - copy_v3_v3(co1, eed->v1->co); - copy_v3_v3(co2, eed->v2->co); - - if (mmd->mirror_ob) { - mul_v3_m4v3(co1, mtx, co1); - mul_v3_m4v3(co2, mtx, co2); - } - - if (mmd->flag & MOD_MIR_AXIS_X) - if ( (fabs(co1[0]) < mmd->tolerance) && - (fabs(co2[0]) < mmd->tolerance) ) - ++eed->f2; - - if (mmd->flag & MOD_MIR_AXIS_Y) - if ( (fabs(co1[1]) < mmd->tolerance) && - (fabs(co2[1]) < mmd->tolerance) ) - ++eed->f2; - if (mmd->flag & MOD_MIR_AXIS_Z) - if ( (fabs(co1[2]) < mmd->tolerance) && - (fabs(co2[2]) < mmd->tolerance) ) - ++eed->f2; - } - } - } - } - } - - /* copy all selected vertices, */ - /* write pointer to new vert in old struct at eve->tmp.v */ - eve= em->verts.last; - while(eve) { - eve->f &= ~128; /* clear, for later test for loose verts */ - if(eve->f & flag) { - sel= 1; - v1= addvertlist(em, 0, NULL); - - VECCOPY(v1->co, eve->co); - v1->f= eve->f; - eve->f-= flag; - eve->tmp.v = v1; - } - else eve->tmp.v = 0; - eve= eve->prev; - } - - if(sel==0) return 0; - - /* all edges with eed->f2==1 or eed->f2==2 become faces */ - - /* if del_old==1 then extrude is in partial geometry, to keep it manifold. - verts with f1==0 and (eve->f & 128)==0) are removed - edges with eed->f2>2 are removed - faces with efa->f1 are removed - if del_old==0 the extrude creates a volume. - */ - - /* find if we delete old faces */ - if(is_face_sel) { - for(eed= em->edges.first; eed; eed= eed->next) { - if( (eed->f2==1 || eed->f2==2) ) { - if(eed->f1==2) { - del_old= 1; - break; - } - } - } - } - - eed= em->edges.last; - while(eed) { - nexted= eed->prev; - if( eed->f2<3) { - eed->v1->f |= 128; /* = no loose vert! */ - eed->v2->f |= 128; - } - if( (eed->f2==1 || eed->f2==2) ) { - - /* if del_old, the preferred normal direction is exact opposite as for keep old faces */ - if(eed->dir != del_old) - efa2 = addfacelist(em, eed->v1, eed->v2, - eed->v2->tmp.v, eed->v1->tmp.v, - eed->tmp.f, NULL); - else - efa2 = addfacelist(em, eed->v2, eed->v1, - eed->v1->tmp.v, eed->v2->tmp.v, - eed->tmp.f, NULL); - - /* Needs smarter adaption of existing creases. - * If addedgelist is used, make sure seams are set to 0 on these - * new edges, since we do not want to add any seams on extrusion. - */ - efa2->e1->crease= eed->crease; - efa2->e2->crease= eed->crease; - efa2->e3->crease= eed->crease; - if(efa2->e4) efa2->e4->crease= eed->crease; - } - - eed= nexted; - } - if(del_old) { - eed= em->edges.first; - while(eed) { - nexted= eed->next; - if(eed->f2==3 && eed->f1==1) { - remedge(em, eed); - free_editedge(em, eed); - } - eed= nexted; - } - } - /* duplicate faces, if necessary remove old ones */ - efa= em->faces.first; - while(efa) { - nextvl= efa->next; - if(efa->f1 & 1) { - - v1 = efa->v1->tmp.v; - v2 = efa->v2->tmp.v; - v3 = efa->v3->tmp.v; - if(efa->v4) - v4 = efa->v4->tmp.v; - else - v4= 0; - - /* hmm .. not sure about edges here */ - if(del_old==0) // if we keep old, we flip normal - efa2= addfacelist(em, v3, v2, v1, v4, efa, efa); - else - efa2= addfacelist(em, v1, v2, v3, v4, efa, efa); - - /* for transform */ - add_normal_aligned(nor, efa->n); - - if(del_old) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - } - efa= nextvl; - } - - normalize_v3(nor); // for grab - - /* for all vertices with eve->tmp.v!=0 - if eve->f1==1: make edge - if flag!=128 : if del_old==1: remove - */ - eve= em->verts.last; - while(eve) { - nextve= eve->prev; - if(eve->tmp.v) { - if(eve->f1==1) addedgelist(em, eve, eve->tmp.v, NULL); - else if( (eve->f & 128)==0) { - if(del_old) { - BLI_remlink(&em->verts,eve); - free_editvert(em, eve); - eve= NULL; - } - } - } - if(eve) { - eve->f &= ~128; - } - eve= nextve; - } - // since its vertex select mode now, it also deselects higher order - EM_selectmode_flush(em); - - if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // g is grab, for correct undo print - return 'n'; -} - -/* generic extrude */ -short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor, int all) -{ - if(em->selectmode & SCE_SELECT_VERTEX) { - EditEdge *eed; - - /*ensure vert flags are consistent for edge selections*/ - for (eed=em->edges.first; eed; eed=eed->next) { - if (eed->f & flag) { - eed->v1->f |= flag; - eed->v2->f |= flag; - } else { - if ((eed->v1->f & flag) && (eed->v2->f & flag)) - eed->f |= flag; - } - } - - return extrudeflag_edge(obedit, em, flag, nor); - } else - return extrudeflag_edge(obedit, em, flag, nor); - -} - -void rotateflag(EditMesh *em, short flag, float *cent, float rotmat[][3]) -{ - /* all verts with (flag & 'flag') rotate */ - EditVert *eve; - - eve= em->verts.first; - while(eve) { - if(eve->f & flag) { - eve->co[0]-=cent[0]; - eve->co[1]-=cent[1]; - eve->co[2]-=cent[2]; - mul_m3_v3(rotmat,eve->co); - eve->co[0]+=cent[0]; - eve->co[1]+=cent[1]; - eve->co[2]+=cent[2]; - } - eve= eve->next; - } -} - -void translateflag(EditMesh *em, short flag, float *vec) -{ - /* all verts with (flag & 'flag') translate */ - EditVert *eve; - - eve= em->verts.first; - while(eve) { - if(eve->f & flag) { - eve->co[0]+=vec[0]; - eve->co[1]+=vec[1]; - eve->co[2]+=vec[2]; - } - eve= eve->next; - } -} - -/* helper call for below */ -static EditVert *adduplicate_vertex(EditMesh *em, EditVert *eve, int flag) -{ - /* FIXME: copy deformation weight from eve ok here? */ - EditVert *v1= addvertlist(em, eve->co, eve); - - v1->f= eve->f; - eve->f-= flag; - eve->f|= 128; - - eve->tmp.v = v1; - - return v1; -} - -/* old selection has flag 128 set, and flag 'flag' cleared -new selection has flag 'flag' set */ -void adduplicateflag(EditMesh *em, int flag) -{ - EditVert *eve, *v1, *v2, *v3, *v4; - EditEdge *eed, *newed; - EditFace *efa, *newfa, *act_efa = EM_get_actFace(em, 0); - - EM_clear_flag_all(em, 128); - EM_selectmode_set(em); // paranoia check, selection now is consistent - - /* vertices first */ - for(eve= em->verts.last; eve; eve= eve->prev) { - - if(eve->f & flag) - adduplicate_vertex(em, eve, flag); - else - eve->tmp.v = NULL; - } - - /* copy edges, note that vertex selection can be independent of edge */ - for(eed= em->edges.last; eed; eed= eed->prev) { - if( eed->f & flag ) { - v1 = eed->v1->tmp.v; - if(v1==NULL) v1= adduplicate_vertex(em, eed->v1, flag); - v2 = eed->v2->tmp.v; - if(v2==NULL) v2= adduplicate_vertex(em, eed->v2, flag); - - newed= addedgelist(em, v1, v2, eed); - - newed->f= eed->f; - eed->f -= flag; - eed->f |= 128; - } - } - - /* then duplicate faces, again create new vertices if needed */ - for(efa= em->faces.last; efa; efa= efa->prev) { - if(efa->f & flag) { - v1 = efa->v1->tmp.v; - if(v1==NULL) v1= adduplicate_vertex(em, efa->v1, flag); - v2 = efa->v2->tmp.v; - if(v2==NULL) v2= adduplicate_vertex(em, efa->v2, flag); - v3 = efa->v3->tmp.v; - if(v3==NULL) v3= adduplicate_vertex(em, efa->v3, flag); - if(efa->v4) { - v4 = efa->v4->tmp.v; - if(v4==NULL) v4= adduplicate_vertex(em, efa->v4, flag); - } - else v4= NULL; - - newfa= addfacelist(em, v1, v2, v3, v4, efa, efa); - - if (efa==act_efa) { - EM_set_actFace(em, newfa); - } - - newfa->f= efa->f; - efa->f -= flag; - efa->f |= 128; - } - } - - EM_fgon_flags(em); // redo flags and indices for fgons -} - -void delfaceflag(EditMesh *em, int flag) -{ - /* delete all faces with 'flag', including loose edges and loose vertices */ - /* this is maybe a bit weird, but this function is used for 'split' and 'separate' */ - /* in remaining vertices/edges 'flag' is cleared */ - EditVert *eve,*nextve; - EditEdge *eed, *nexted; - EditFace *efa,*nextvl; - - /* to detect loose edges, we put f2 flag on 1 */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & flag) eed->f2= 1; - else eed->f2= 0; - } - - /* delete faces */ - efa= em->faces.first; - while(efa) { - nextvl= efa->next; - if(efa->f & flag) { - - efa->e1->f2= 1; - efa->e2->f2= 1; - efa->e3->f2= 1; - if(efa->e4) { - efa->e4->f2= 1; - } - - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextvl; - } - - /* all remaining faces: make sure we keep the edges */ - for(efa= em->faces.first; efa; efa= efa->next) { - efa->e1->f2= 0; - efa->e2->f2= 0; - efa->e3->f2= 0; - if(efa->e4) { - efa->e4->f2= 0; - } - } - - /* remove tagged edges, and clear remaining ones */ - eed= em->edges.first; - while(eed) { - nexted= eed->next; - - if(eed->f2==1) { - remedge(em, eed); - free_editedge(em, eed); - } - else { - eed->f &= ~flag; - eed->v1->f &= ~flag; - eed->v2->f &= ~flag; - } - eed= nexted; - } - - /* vertices with 'flag' now are the loose ones, and will be removed */ - eve= em->verts.first; - while(eve) { - nextve= eve->next; - if(eve->f & flag) { - BLI_remlink(&em->verts, eve); - free_editvert(em, eve); - } - eve= nextve; - } - -} - -/* ********************* */ -#if 0 -static int check_vnormal_flip(float *n, float *vnorm) -{ - float inp; - - inp= n[0]*vnorm[0]+n[1]*vnorm[1]+n[2]*vnorm[2]; - - /* angles 90 degrees: dont flip */ - if(inp> -0.000001) return 0; - - return 1; -} -#endif - - - -/* does face centers too */ -void recalc_editnormals(EditMesh *em) -{ - EditFace *efa; - EditVert *eve; - - for(eve= em->verts.first; eve; eve=eve->next) { - eve->no[0] = eve->no[1] = eve->no[2] = 0.0; - } - - for(efa= em->faces.first; efa; efa=efa->next) { - if (efa->e1->fgoni||efa->e2->fgoni||efa->e3->fgoni) continue; - if (efa->e4 && efa->e4->fgoni) continue; - - if(efa->v4) { - normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - add_v3_v3v3(efa->v4->no, efa->v4->no, efa->n); - } - else { - normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co); - cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co); - } - add_v3_v3v3(efa->v1->no, efa->v1->no, efa->n); - add_v3_v3v3(efa->v2->no, efa->v2->no, efa->n); - add_v3_v3v3(efa->v3->no, efa->v3->no, efa->n); - } - - /* following Mesh convention; we use vertex coordinate itself for normal in this case */ - for(eve= em->verts.first; eve; eve=eve->next) { - if (normalize_v3(eve->no)==0.0) { - VECCOPY(eve->no, eve->co); - normalize_v3(eve->no); - } - } -} - -int compareface(EditFace *vl1, EditFace *vl2) -{ - EditVert *v1, *v2, *v3, *v4; - - if(vl1->v4 && vl2->v4) { - v1= vl2->v1; - v2= vl2->v2; - v3= vl2->v3; - v4= vl2->v4; - - if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) { - if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) { - if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) { - if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) { - return 1; - } - } - } - } - } - else if(vl1->v4==0 && vl2->v4==0) { - v1= vl2->v1; - v2= vl2->v2; - v3= vl2->v3; - - if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) { - if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) { - if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) { - return 1; - } - } - } - } - - return 0; -} - -/* checks for existance, not tria overlapping inside quad */ -EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4) -{ - EditFace *efa, efatest; - - efatest.v1= v1; - efatest.v2= v2; - efatest.v3= v3; - efatest.v4= v4; - - efa= em->faces.first; - while(efa) { - if(compareface(&efatest, efa)) return efa; - efa= efa->next; - } - return NULL; -} - -/* evaluate if entire quad is a proper convex quad */ -int convex(float *v1, float *v2, float *v3, float *v4) -{ - float nor[3], nor1[3], nor2[3], vec[4][2]; - - /* define projection, do both trias apart, quad is undefined! */ - normal_tri_v3( nor1,v1, v2, v3); - normal_tri_v3( nor2,v1, v3, v4); - nor[0]= ABS(nor1[0]) + ABS(nor2[0]); - nor[1]= ABS(nor1[1]) + ABS(nor2[1]); - nor[2]= ABS(nor1[2]) + ABS(nor2[2]); - - if(nor[2] >= nor[0] && nor[2] >= nor[1]) { - vec[0][0]= v1[0]; vec[0][1]= v1[1]; - vec[1][0]= v2[0]; vec[1][1]= v2[1]; - vec[2][0]= v3[0]; vec[2][1]= v3[1]; - vec[3][0]= v4[0]; vec[3][1]= v4[1]; - } - else if(nor[1] >= nor[0] && nor[1]>= nor[2]) { - vec[0][0]= v1[0]; vec[0][1]= v1[2]; - vec[1][0]= v2[0]; vec[1][1]= v2[2]; - vec[2][0]= v3[0]; vec[2][1]= v3[2]; - vec[3][0]= v4[0]; vec[3][1]= v4[2]; - } - else { - vec[0][0]= v1[1]; vec[0][1]= v1[2]; - vec[1][0]= v2[1]; vec[1][1]= v2[2]; - vec[2][0]= v3[1]; vec[2][1]= v3[2]; - vec[3][0]= v4[1]; vec[3][1]= v4[2]; - } - - /* linetests, the 2 diagonals have to instersect to be convex */ - if( isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1; - return 0; -} - - -/* ********************* Fake Polgon support (FGon) ***************** */ - - -/* results in: - - faces having ->fgonf flag set (also for draw) - - edges having ->fgoni index set (for select) -*/ - -float EM_face_area(EditFace *efa) -{ - if(efa->v4) return area_quad_v3(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - else return area_tri_v3(efa->v1->co, efa->v2->co, efa->v3->co); -} - -float EM_face_perimeter(EditFace *efa) -{ - if(efa->v4) return - len_v3v3(efa->v1->co, efa->v2->co)+ - len_v3v3(efa->v2->co, efa->v3->co)+ - len_v3v3(efa->v3->co, efa->v4->co)+ - len_v3v3(efa->v4->co, efa->v1->co); - - else return - len_v3v3(efa->v1->co, efa->v2->co)+ - len_v3v3(efa->v2->co, efa->v3->co)+ - len_v3v3(efa->v3->co, efa->v1->co); -} - -void EM_fgon_flags(EditMesh *em) -{ - EditFace *efa, *efan, *efamax; - EditEdge *eed; - ListBase listb={NULL, NULL}; - float size, maxsize; - short done, curindex= 1; - - // for each face with fgon edge AND not fgon flag set - for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0; // index - for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0; // flag - - // for speed & simplicity, put fgon face candidates in new listbase - efa= em->faces.first; - while(efa) { - efan= efa->next; - if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) || - (efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) { - BLI_remlink(&em->faces, efa); - BLI_addtail(&listb, efa); - } - efa= efan; - } - - // find an undone face with fgon edge - for(efa= listb.first; efa; efa= efa->next) { - if(efa->fgonf==0) { - - // init this face - efa->fgonf= EM_FGON; - if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex; - if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex; - if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex; - if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex; - - // we search for largest face, to give facedot drawing rights - maxsize= EM_face_area(efa); - efamax= efa; - - // now flush curendex over edges and set faceflags - done= 1; - while(done==1) { - done= 0; - - for(efan= listb.first; efan; efan= efan->next) { - if(efan->fgonf==0) { - // if one if its edges has index set, do other too - if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) || - (efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) { - - efan->fgonf= EM_FGON; - if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex; - if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex; - if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex; - if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex; - - size= EM_face_area(efan); - if(size>maxsize) { - efamax= efan; - maxsize= size; - } - done= 1; - } - } - } - } - - efamax->fgonf |= EM_FGON_DRAW; - curindex++; - - } - } - - // put fgon face candidates back in listbase - efa= listb.first; - while(efa) { - efan= efa->next; - BLI_remlink(&listb, efa); - BLI_addtail(&em->faces, efa); - efa= efan; - } - - // remove fgon flags when edge not in fgon (anymore) - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->fgoni==0) eed->h &= ~EM_FGON; - } - -} - -/* editmesh vertmap, copied from intern.mesh.c - * if do_face_idx_array is 0 it means we need to run it as well as freeing - * */ - -UvVertMap *EM_make_uv_vert_map(EditMesh *em, int selected, int do_face_idx_array, float *limit) -{ - EditVert *ev; - EditFace *efa; - int totverts; - - /* vars from original func */ - UvVertMap *vmap; - UvMapVert *buf; - MTFace *tf; - unsigned int a; - int i, totuv, nverts; - - if (do_face_idx_array) - EM_init_index_arrays(em, 0, 0, 1); - - /* we need the vert */ - for (ev= em->verts.first, totverts=0; ev; ev= ev->next, totverts++) { - ev->tmp.l = totverts; - } - - totuv = 0; - - /* generate UvMapVert array */ - for (efa= em->faces.first; efa; efa= efa->next) - if(!selected || ((!efa->h) && (efa->f & SELECT))) - totuv += (efa->v4)? 4: 3; - - if(totuv==0) { - if (do_face_idx_array) - EM_free_index_arrays(); - return NULL; - } - vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap"); - if (!vmap) { - if (do_face_idx_array) - EM_free_index_arrays(); - return NULL; - } - - vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*"); - buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert"); - - if (!vmap->vert || !vmap->buf) { - free_uv_vert_map(vmap); - if (do_face_idx_array) - EM_free_index_arrays(); - return NULL; - } - - for (a=0, efa= em->faces.first; efa; a++, efa= efa->next) { - if(!selected || ((!efa->h) && (efa->f & SELECT))) { - nverts= (efa->v4)? 4: 3; - - for(i=0; i<nverts; i++) { - buf->tfindex= i; - buf->f= a; - buf->separate = 0; - - buf->next= vmap->vert[(*(&efa->v1 + i))->tmp.l]; - vmap->vert[(*(&efa->v1 + i))->tmp.l]= buf; - - buf++; - } - } - } - - /* sort individual uvs for each vert */ - for(a=0, ev=em->verts.first; ev; a++, ev= ev->next) { - UvMapVert *newvlist= NULL, *vlist=vmap->vert[a]; - UvMapVert *iterv, *v, *lastv, *next; - float *uv, *uv2, uvdiff[2]; - - while(vlist) { - v= vlist; - vlist= vlist->next; - v->next= newvlist; - newvlist= v; - - efa = EM_get_face_for_index(v->f); - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - uv = tf->uv[v->tfindex]; - - lastv= NULL; - iterv= vlist; - - while(iterv) { - next= iterv->next; - efa = EM_get_face_for_index(iterv->f); - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - uv2 = tf->uv[iterv->tfindex]; - - sub_v2_v2v2(uvdiff, uv2, uv); - - if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) { - if(lastv) lastv->next= next; - else vlist= next; - iterv->next= newvlist; - newvlist= iterv; - } - else - lastv=iterv; - - iterv= next; - } - - newvlist->separate = 1; - } - - vmap->vert[a]= newvlist; - } - - if (do_face_idx_array) - EM_free_index_arrays(); - - return vmap; -} - -UvMapVert *EM_get_uv_map_vert(UvVertMap *vmap, unsigned int v) -{ - return vmap->vert[v]; -} - -void EM_free_uv_vert_map(UvVertMap *vmap) -{ - if (vmap) { - if (vmap->vert) MEM_freeN(vmap->vert); - if (vmap->buf) MEM_freeN(vmap->buf); - MEM_freeN(vmap); - } -} - -/* poll call for mesh operators requiring a view3d context */ -int EM_view3d_poll(bContext *C) -{ - if(ED_operator_editmesh(C) && ED_operator_view3d_active(C)) - return 1; - return 0; -} diff --git a/source/blender/editors/mesh/editmesh_loop.c b/source/blender/editors/mesh/editmesh_loop.c deleted file mode 100644 index 0806010ccd8..00000000000 --- a/source/blender/editors/mesh/editmesh_loop.c +++ /dev/null @@ -1,898 +0,0 @@ -/** - * $Id: - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2004 by Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/* - -editmesh_loop: tools with own drawing subloops, select, knife, subdiv - -*/ - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_view3d_types.h" -#include "DNA_windowmanager_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_editVert.h" -#include "BLI_ghash.h" - -#include "BKE_context.h" -#include "BKE_depsgraph.h" -#include "BKE_displist.h" -#include "BKE_global.h" -#include "BKE_library.h" -#include "BKE_mesh.h" -#include "BKE_object.h" -#include "BKE_report.h" -#include "BKE_utildefines.h" -#include "BKE_tessmesh.h" - -#include "PIL_time.h" - -#include "BIF_gl.h" - -#include "RNA_access.h" -#include "RNA_define.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "ED_mesh.h" -#include "ED_screen.h" -#include "ED_view3d.h" - -#include "mesh_intern.h" -#include "bmesh.h" - -/* **** XXX ******** */ -static void BIF_undo_push() {} -static void BIF_undo() {} -static void error() {} -static int qtest() {return 0;} -/* **** XXX ******** */ - - -/* New LoopCut */ -static void edgering_sel(EditMesh *em, EditEdge *startedge, int select, int previewlines) -{ - EditEdge *eed; - EditFace *efa; - EditVert *v[2][2]; - float co[2][3]; - int looking= 1,i; - - /* in eed->f1 we put the valence (amount of faces in edge) */ - /* in eed->f2 we put tagged flag as correct loop */ - /* in efa->f1 we put tagged flag as correct to select */ - - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; - eed->f2= 0; - } - for(efa= em->faces.first; efa; efa= efa->next) { - efa->f1= 0; - if(efa->h==0) { - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - } - - // tag startedge OK - startedge->f2= 1; - - while(looking) { - looking= 0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e4 && efa->f1==0 && efa->h == 0) { // not done quad - if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok - - // if edge tagged, select opposing edge and mark face ok - if(efa->e1->f2) { - efa->e3->f2= 1; - efa->f1= 1; - looking= 1; - } - else if(efa->e2->f2) { - efa->e4->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e3->f2) { - efa->e1->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e4->f2) { - efa->e2->f2= 1; - efa->f1= 1; - looking= 1; - } - } - } - } - } - - if(previewlines > 0 && select == 0){ -// XXX persp(PERSP_VIEW); -// XXX glPushMatrix(); -// XXX mymultmatrix(obedit->obmat); - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->v4 == NULL) { continue; } - if(efa->h == 0){ - if(efa->e1->f2 == 1){ - if(efa->e1->h == 1 || efa->e3->h == 1 ) - continue; - - v[0][0] = efa->v1; - v[0][1] = efa->v2; - v[1][0] = efa->v4; - v[1][1] = efa->v3; - } else if(efa->e2->f2 == 1){ - if(efa->e2->h == 1 || efa->e4->h == 1) - continue; - v[0][0] = efa->v2; - v[0][1] = efa->v3; - v[1][0] = efa->v1; - v[1][1] = efa->v4; - } else { continue; } - - for(i=1;i<=previewlines;i++){ - co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0]; - co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1]; - co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2]; - - co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0]; - co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1]; - co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2]; - glColor3ub(255, 0, 255); - glBegin(GL_LINES); - glVertex3f(co[0][0],co[0][1],co[0][2]); - glVertex3f(co[1][0],co[1][1],co[1][2]); - glEnd(); - } - } - } - glPopMatrix(); - } else { - - /* (de)select the edges */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f2) EM_select_edge(eed, select); - } - } -} - -void CutEdgeloop(Object *obedit, wmOperator *op, EditMesh *em, int numcuts) -{ -#if 0 - ViewContext vc; // XXX - EditEdge *nearest=NULL, *eed; - float fac; - int keys = 0, holdnum=0, selectmode, dist; - short mvalo[2] = {0, 0}, mval[2] = {0, 0}; - short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0; - short hasHidden = 0; - char msg[128]; - - selectmode = em->selectmode; - - if(em->selectmode & SCE_SELECT_FACE){ - em->selectmode = SCE_SELECT_EDGE; - EM_selectmode_set(em); - } - - - BIF_undo_push("Loopcut Begin"); - while(choosing && !cancel){ -// XXX getmouseco_areawin(mval); - if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) { - mvalo[0] = mval[0]; - mvalo[1] = mval[1]; - dist= 50; - nearest = findnearestedge(&vc, &dist); // returns actual distance in dist -// scrarea_do_windraw(curarea); // after findnearestedge, backbuf! - - sprintf(msg,"Number of Cuts: %d (S)mooth: ",numcuts); - strcat(msg, smooth ? "on":"off"); - -// headerprint(msg); - /* Need to figure preview */ - if(nearest){ - edgering_sel(em, nearest, 0, numcuts); - } -// XXX screen_swapbuffers(); - - /* backbuffer refresh for non-apples (no aux) */ -#ifndef __APPLE__ -// XXX if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) { -// backdrawview3d(0); -// } -#endif - } - else PIL_sleep_ms(10); // idle - - - while(qtest()) - { - val=0; -// XXX event= extern_qread(&val); - if(val && (event == MOUSEX || event == MOUSEY)){ ; } - else if(val && ((event==LEFTMOUSE || event==RETKEY) || (event == MIDDLEMOUSE || event==PADENTER))) - { - if(event == MIDDLEMOUSE){ - cuthalf = 1; - } - if (nearest==NULL) - cancel = 1; - choosing=0; - mvalo[0] = -1; - } - else if(val && (event==ESCKEY || event==RIGHTMOUSE )) - { - choosing=0; - cancel = 1; - mvalo[0] = -1; - } - else if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE)) - { - numcuts++; - mvalo[0] = -1; - } - else if(val && (event==PADMINUS || event==WHEELDOWNMOUSE)) - { - if(numcuts > 1){ - numcuts--; - mvalo[0] = -1; - } - } - else if(val && event==SKEY) - { - if(smooth){smooth=0;} - else { smooth=1; } - mvalo[0] = -1; - } - - else if(val){ - holdnum = -1; - switch(event){ - case PAD9: - case NINEKEY: - holdnum = 9; break; - case PAD8: - case EIGHTKEY: - holdnum = 8;break; - case PAD7: - case SEVENKEY: - holdnum = 7;break; - case PAD6: - case SIXKEY: - holdnum = 6;break; - case PAD5: - case FIVEKEY: - holdnum = 5;break; - case PAD4: - case FOURKEY: - holdnum = 4;break; - case PAD3: - case THREEKEY: - holdnum = 3; break; - case PAD2: - case TWOKEY: - holdnum = 2;break; - case PAD1: - case ONEKEY: - holdnum = 1; break; - case PAD0: - case ZEROKEY: - holdnum = 0;break; - case BACKSPACEKEY: - holdnum = -2;break; - } - if(holdnum >= 0 && numcuts*10 < 130){ - if(keys == 0){ // first level numeric entry - if(holdnum > 0){ - numcuts = holdnum; - keys++; - } - } else if(keys > 0){//highrt level numeric entry - numcuts *= 10; - numcuts += holdnum; - keys++; - } - } else if (holdnum == -2){// backspace - if (keys > 1){ - numcuts /= 10; - keys--; - } else { - numcuts=1; - keys = 0; - } - } - mvalo[0] = -1; - break; - } // End Numeric Entry - } //End while(qtest()) - } // End Choosing - - if(cancel){ - return; - } - /* clean selection */ - for(eed=em->edges.first; eed; eed = eed->next){ - EM_select_edge(eed,0); - } - /* select edge ring */ - edgering_sel(em, nearest, 1, 0); - - /* now cut the loops */ - if(smooth){ - fac= 1.0f; -// XXX if(fbutton(&fac, 0.0f, 5.0f, 10, 10, "Smooth:")==0) return; - fac= 0.292f*fac; - esubdivideflag(obedit, em, SELECT,fac,0,B_SMOOTH,numcuts,SUBDIV_SELECT_LOOPCUT); - } else { - esubdivideflag(obedit, em, SELECT,0,0,0,numcuts,SUBDIV_SELECT_LOOPCUT); - } - /* if this was a single cut, enter edgeslide mode */ - if(numcuts == 1 && hasHidden == 0){ - if(cuthalf) - EdgeSlide(em, op, 1,0.0); - else { - if(EdgeSlide(em, op, 0,0.0) == -1){ - BIF_undo(); - } - } - } - - if(em->selectmode != selectmode){ - em->selectmode = selectmode; - EM_selectmode_set(em); - } - -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - return; -#endif -} - - -/* *************** LOOP SELECT ************* */ -#if 0 -static short edgeFaces(EditMesh *em, EditEdge *e) -{ - EditFace *search=NULL; - short count = 0; - - search = em->faces.first; - while(search){ - if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e)) - count++; - search = search->next; - } - return count; -} -#endif - - - -/* ***************** TRAIL ************************ - -Read a trail of mouse coords and return them as an array of CutCurve structs -len returns number of mouse coords read before commiting with RETKEY -It is up to the caller to free the block when done with it, - -XXX Is only used here, so local inside this file (ton) - */ - -#define TRAIL_POLYLINE 1 /* For future use, They don't do anything yet */ -#define TRAIL_FREEHAND 2 -#define TRAIL_MIXED 3 /* (1|2) */ -#define TRAIL_AUTO 4 -#define TRAIL_MIDPOINTS 8 - -typedef struct CutCurve { - float x; - float y; -} CutCurve; - - -/* ******************************************************************** */ -/* Knife Subdivide Tool. Subdivides edges intersected by a mouse trail - drawn by user. - - Currently mapped to KKey when in MeshEdit mode. - Usage: - Hit Shift K, Select Centers or Exact - Hold LMB down to draw path, hit RETKEY. - ESC cancels as expected. - - Contributed by Robert Wenzlaff (Det. Thorn). - - 2.5 revamp: - - non modal (no menu before cutting) - - exit on mouse release - - polygon/segment drawing can become handled by WM cb later - -*/ - -#define KNIFE_EXACT 1 -#define KNIFE_MIDPOINT 2 -#define KNIFE_MULTICUT 3 - -static EnumPropertyItem knife_items[]= { - {KNIFE_EXACT, "EXACT", 0, "Exact", ""}, - {KNIFE_MIDPOINT, "MIDPOINTS", 0, "Midpoints", ""}, - {KNIFE_MULTICUT, "MULTICUT", 0, "Multicut", ""}, - {0, NULL, 0, NULL, NULL} -}; - -/* seg_intersect() Determines if and where a mouse trail intersects an EditEdge */ - -static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct GHash *gh) -{ -#define MAXSLOPE 100000 - float x11, y11, x12=0, y12=0, x2max, x2min, y2max; - float y2min, dist, lastdist=0, xdiff2, xdiff1; - float m1, b1, m2, b2, x21, x22, y21, y22, xi; - float yi, x1min, x1max, y1max, y1min, perc=0; - float *scr; - float threshold = 0.0; - int i; - - threshold = 0.000001; /*tolerance for vertex intersection*/ - // XXX threshold = scene->toolsettings->select_thresh / 100; - - /* Get screen coords of verts */ - scr = BLI_ghash_lookup(gh, e->v1); - x21=scr[0]; - y21=scr[1]; - - scr = BLI_ghash_lookup(gh, e->v2); - x22=scr[0]; - y22=scr[1]; - - xdiff2=(x22-x21); - if (xdiff2) { - m2=(y22-y21)/xdiff2; - b2= ((x22*y21)-(x21*y22))/xdiff2; - } - else { - m2=MAXSLOPE; /* Verticle slope */ - b2=x22; - } - - /*check for *exact* vertex intersection first*/ - if(mode!=KNIFE_MULTICUT){ - for (i=0; i<len; i++){ - if (i>0){ - x11=x12; - y11=y12; - } - else { - x11=c[i].x; - y11=c[i].y; - } - x12=c[i].x; - y12=c[i].y; - - /*test e->v1*/ - if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){ - e->v1->f1 = 1; - perc = 0; - return(perc); - } - /*test e->v2*/ - else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){ - e->v2->f1 = 1; - perc = 0; - return(perc); - } - } - } - - /*now check for edge interesect (may produce vertex intersection as well)*/ - for (i=0; i<len; i++){ - if (i>0){ - x11=x12; - y11=y12; - } - else { - x11=c[i].x; - y11=c[i].y; - } - x12=c[i].x; - y12=c[i].y; - - /* Perp. Distance from point to line */ - if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */ - /* change in sign. Skip extra math */ - else dist=x22-x12; - - if (i==0) lastdist=dist; - - /* if dist changes sign, and intersect point in edge's Bound Box*/ - if ((lastdist*dist)<=0){ - xdiff1=(x12-x11); /* Equation of line between last 2 points */ - if (xdiff1){ - m1=(y12-y11)/xdiff1; - b1= ((x12*y11)-(x11*y12))/xdiff1; - } - else{ - m1=MAXSLOPE; - b1=x12; - } - x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */ - x2min=MIN2(x21,x22)-0.001; /* due to round off error */ - y2max=MAX2(y21,y22)+0.001; - y2min=MIN2(y21,y22)-0.001; - - /* Found an intersect, calc intersect point */ - if (m1==m2){ /* co-incident lines */ - /* cut at 50% of overlap area*/ - x1max=MAX2(x11, x12); - x1min=MIN2(x11, x12); - xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0; - - y1max=MAX2(y11, y12); - y1min=MIN2(y11, y12); - yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0; - } - else if (m2==MAXSLOPE){ - xi=x22; - yi=m1*x22+b1; - } - else if (m1==MAXSLOPE){ - xi=x12; - yi=m2*x12+b2; - } - else { - xi=(b1-b2)/(m2-m1); - yi=(b1*m2-m1*b2)/(m2-m1); - } - - /* Intersect inside bounding box of edge?*/ - if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){ - /*test for vertex intersect that may be 'close enough'*/ - if(mode!=KNIFE_MULTICUT){ - if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){ - if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){ - e->v1->f1 = 1; - perc = 0; - break; - } - } - if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){ - if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){ - e->v2->f1 = 1; - perc = 0; - break; - } - } - } - if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21); - else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/ - //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */ - - break; - } - } - lastdist=dist; - } - return(perc); -} - - -static float bm_seg_intersect(BMEdge *e, CutCurve *c, int len, char mode, - struct GHash *gh, int *isected) -{ -#define MAXSLOPE 100000 - float x11, y11, x12=0, y12=0, x2max, x2min, y2max; - float y2min, dist, lastdist=0, xdiff2, xdiff1; - float m1, b1, m2, b2, x21, x22, y21, y22, xi; - float yi, x1min, x1max, y1max, y1min, perc=0; - float *scr; - float threshold = 0.0; - int i; - - //threshold = 0.000001; /*tolerance for vertex intersection*/ - // XXX threshold = scene->toolsettings->select_thresh / 100; - - /* Get screen coords of verts */ - scr = BLI_ghash_lookup(gh, e->v1); - x21=scr[0]; - y21=scr[1]; - - scr = BLI_ghash_lookup(gh, e->v2); - x22=scr[0]; - y22=scr[1]; - - xdiff2=(x22-x21); - if (xdiff2) { - m2=(y22-y21)/xdiff2; - b2= ((x22*y21)-(x21*y22))/xdiff2; - } - else { - m2=MAXSLOPE; /* Verticle slope */ - b2=x22; - } - - *isected = 0; - - /*check for *exact* vertex intersection first*/ - if(mode!=KNIFE_MULTICUT){ - for (i=0; i<len; i++){ - if (i>0){ - x11=x12; - y11=y12; - } - else { - x11=c[i].x; - y11=c[i].y; - } - x12=c[i].x; - y12=c[i].y; - - /*test e->v1*/ - if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){ - perc = 0; - *isected = 1; - return(perc); - } - /*test e->v2*/ - else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){ - perc = 0; - *isected = 2; - return(perc); - } - } - } - - /*now check for edge interesect (may produce vertex intersection as well)*/ - for (i=0; i<len; i++){ - if (i>0){ - x11=x12; - y11=y12; - } - else { - x11=c[i].x; - y11=c[i].y; - } - x12=c[i].x; - y12=c[i].y; - - /* Perp. Distance from point to line */ - if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */ - /* change in sign. Skip extra math */ - else dist=x22-x12; - - if (i==0) lastdist=dist; - - /* if dist changes sign, and intersect point in edge's Bound Box*/ - if ((lastdist*dist)<=0){ - xdiff1=(x12-x11); /* Equation of line between last 2 points */ - if (xdiff1){ - m1=(y12-y11)/xdiff1; - b1= ((x12*y11)-(x11*y12))/xdiff1; - } - else{ - m1=MAXSLOPE; - b1=x12; - } - x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */ - x2min=MIN2(x21,x22)-0.001; /* due to round off error */ - y2max=MAX2(y21,y22)+0.001; - y2min=MIN2(y21,y22)-0.001; - - /* Found an intersect, calc intersect point */ - if (m1==m2){ /* co-incident lines */ - /* cut at 50% of overlap area*/ - x1max=MAX2(x11, x12); - x1min=MIN2(x11, x12); - xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0; - - y1max=MAX2(y11, y12); - y1min=MIN2(y11, y12); - yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0; - } - else if (m2==MAXSLOPE){ - xi=x22; - yi=m1*x22+b1; - } - else if (m1==MAXSLOPE){ - xi=x12; - yi=m2*x12+b2; - } - else { - xi=(b1-b2)/(m2-m1); - yi=(b1*m2-m1*b2)/(m2-m1); - } - - /* Intersect inside bounding box of edge?*/ - if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){ - /*test for vertex intersect that may be 'close enough'*/ - if(mode!=KNIFE_MULTICUT){ - if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){ - if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){ - *isected = 1; - perc = 0; - break; - } - } - if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){ - if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){ - *isected = 2; - perc = 0; - break; - } - } - } - if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21); - else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/ - //isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */ - - break; - } - } - lastdist=dist; - } - return(perc); -} - -#define MAX_CUTS 256 - -static int knife_cut_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - BMEditMesh *em= (((Mesh *)obedit->data))->edit_btmesh; - BMesh *bm = em->bm; - ARegion *ar= CTX_wm_region(C); - BMVert *bv; - BMIter iter; - BMEdge *be; - BMOperator bmop; - CutCurve curve[MAX_CUTS]; - struct GHash *gh; - float isect=0.0; - float *scr, co[4]; - int len=0, isected, flag, i; - short numcuts=1, mode= RNA_int_get(op->ptr, "type"); - - /* edit-object needed for matrix, and ar->regiondata for projections to work */ - if (ELEM3(NULL, obedit, ar, ar->regiondata)) - return OPERATOR_CANCELLED; - - if (bm->totvertsel < 2) { - error("No edges are selected to operate on"); - return OPERATOR_CANCELLED;; - } - - /* get the cut curve */ - RNA_BEGIN(op->ptr, itemptr, "path") { - - RNA_float_get_array(&itemptr, "loc", (float *)&curve[len]); - len++; - if(len>= MAX_CUTS) break; - } - RNA_END; - - if(len<2) { - return OPERATOR_CANCELLED; - } - - /*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/ - gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - for(bv=BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);bv;bv=BMIter_Step(&iter)){ - scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates"); - VECCOPY(co, bv->co); - co[3]= 1.0; - mul_m4_v4(obedit->obmat, co); - project_float(ar, co, scr); - BLI_ghash_insert(gh, bv, scr); - } - - BMO_Init_Op(&bmop, "esubd"); - - i = 0; - /*store percentage of edge cut for KNIFE_EXACT here.*/ - for (be=BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be=BMIter_Step(&iter)) { - if( BM_Selected(bm, be) ) { - isect= bm_seg_intersect(be, curve, len, mode, gh, &isected); - - if (isect != 0.0f) { - if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { - BMO_Insert_MapFloat(bm, &bmop, - "edgepercents", - be, isect); - - } - BMO_SetFlag(bm, be, 1); - } else BMO_ClearFlag(bm, be, 1); - } else BMO_ClearFlag(bm, be, 1); - } - - BMO_Flag_To_Slot(bm, &bmop, "edges", 1, BM_EDGE); - - BMO_Set_Int(&bmop, "numcuts", numcuts); - flag = B_KNIFE; - if (mode == KNIFE_MIDPOINT) numcuts = 1; - BMO_Set_Int(&bmop, "flag", flag); - BMO_Set_Float(&bmop, "radius", 0); - - BMO_Exec_Op(bm, &bmop); - BMO_Finish_Op(bm, &bmop); - - BLI_ghash_free(gh, NULL, (GHashValFreeFP)WMEM_freeN); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_knife_cut(wmOperatorType *ot) -{ - PropertyRNA *prop; - - ot->name= "Knife Cut"; - ot->description= "Cut selected edges and faces into parts."; - ot->idname= "MESH_OT_knife_cut"; - - ot->invoke= WM_gesture_lines_invoke; - ot->modal= WM_gesture_lines_modal; - ot->exec= knife_cut_exec; - - ot->poll= EM_view3d_poll; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_enum(ot->srna, "type", knife_items, KNIFE_EXACT, "Type", ""); - prop= RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE); - RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath); - - /* internal */ - RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX); -} - -/* ******************************************************* */ - diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c deleted file mode 100644 index dd70181884a..00000000000 --- a/source/blender/editors/mesh/editmesh_mods.c +++ /dev/null @@ -1,2352 +0,0 @@ -/** - * $Id: - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2004 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/* - -editmesh_mods.c, UI level access, no geometry changes - -*/ - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - - - -#include "DNA_mesh_types.h" -#include "DNA_material_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" -#include "DNA_texture_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_view3d_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_editVert.h" -#include "BLI_rand.h" - -#include "BKE_context.h" -#include "BKE_displist.h" -#include "BKE_depsgraph.h" -#include "BKE_DerivedMesh.h" -#include "BKE_customdata.h" -#include "BKE_global.h" -#include "BKE_mesh.h" -#include "BKE_material.h" -#include "BKE_paint.h" -#include "BKE_texture.h" -#include "BKE_utildefines.h" -#include "BKE_report.h" - -#include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" - -#include "RE_render_ext.h" /* externtex */ - -#include "WM_api.h" -#include "WM_types.h" - -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "ED_mesh.h" -#include "ED_screen.h" -#include "ED_view3d.h" -#include "bmesh.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "mesh_intern.h" - -#include "BLO_sys_types.h" // for intptr_t support - -/* XXX */ -static void waitcursor(int val) {} -static int pupmenu() {return 0;} - -/* ****************************** MIRROR **************** */ - -void EM_cache_x_mirror_vert(struct Object *ob, struct EditMesh *em) -{ - EditVert *eve, *eve_mirror; - - for(eve= em->verts.first; eve; eve= eve->next) { - eve->tmp.v= NULL; - } - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->tmp.v==NULL) { - eve_mirror = editmesh_get_x_mirror_vert(ob, em, eve->co); - if(eve_mirror) { - eve->tmp.v= eve_mirror; - eve_mirror->tmp.v = eve; - } - } - } -} - -void EM_select_mirrored(Object *obedit, EditMesh *em, int extend) -{ - - EditVert *eve; - - EM_cache_x_mirror_vert(obedit, em); - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT && eve->tmp.v) { - eve->tmp.v->f |= SELECT; - - if(extend==FALSE) - eve->f &= ~SELECT; - - /* remove the interference */ - eve->tmp.v->tmp.v= eve->tmp.v= NULL; - } - } -} - -/* ****************************** SELECTION ROUTINES **************** */ - -unsigned int em_solidoffs=0, em_wireoffs=0, em_vertoffs=0; /* set in drawobject.c ... for colorindices */ - -/* facilities for border select and circle select */ -static char *selbuf= NULL; - -/* opengl doesn't support concave... */ -static void draw_triangulated(short mcords[][2], short tot) -{ - ListBase lb={NULL, NULL}; - DispList *dl; - float *fp; - int a; - - /* make displist */ - dl= MEM_callocN(sizeof(DispList), "poly disp"); - dl->type= DL_POLY; - dl->parts= 1; - dl->nr= tot; - dl->verts= fp= MEM_callocN(tot*3*sizeof(float), "poly verts"); - BLI_addtail(&lb, dl); - - for(a=0; a<tot; a++, fp+=3) { - fp[0]= (float)mcords[a][0]; - fp[1]= (float)mcords[a][1]; - } - - /* do the fill */ - filldisplist(&lb, &lb); - - /* do the draw */ - dl= lb.first; /* filldisplist adds in head of list */ - if(dl->type==DL_INDEX3) { - int *index; - - a= dl->parts; - fp= dl->verts; - index= dl->index; - glBegin(GL_TRIANGLES); - while(a--) { - glVertex3fv(fp+3*index[0]); - glVertex3fv(fp+3*index[1]); - glVertex3fv(fp+3*index[2]); - index+= 3; - } - glEnd(); - } - - freedisplist(&lb); -} - - -/* reads rect, and builds selection array for quick lookup */ -/* returns if all is OK */ -int EM_init_backbuf_border(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) -{ - struct ImBuf *buf; - unsigned int *dr; - int a; - - if(vc->obedit==NULL || vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0; - - buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - if(buf==NULL) return 0; - if(em_vertoffs==0) return 0; - - dr = buf->rect; - - /* build selection lookup */ - selbuf= MEM_callocN(em_vertoffs+1, "selbuf"); - - a= (xmax-xmin+1)*(ymax-ymin+1); - while(a--) { - if(*dr>0 && *dr<=em_vertoffs) - selbuf[*dr]= 1; - dr++; - } - IMB_freeImBuf(buf); - return 1; -} - -int EM_check_backbuf(unsigned int index) -{ - if(selbuf==NULL) return 1; - if(index>0 && index<=em_vertoffs) - return selbuf[index]; - return 0; -} - -void EM_free_backbuf(void) -{ - if(selbuf) MEM_freeN(selbuf); - selbuf= NULL; -} - -/* mcords is a polygon mask - - grab backbuffer, - - draw with black in backbuffer, - - grab again and compare - returns 'OK' -*/ -int EM_mask_init_backbuf_border(ViewContext *vc, short mcords[][2], short tot, short xmin, short ymin, short xmax, short ymax) -{ - unsigned int *dr, *drm; - struct ImBuf *buf, *bufmask; - int a; - - /* method in use for face selecting too */ - if(vc->obedit==NULL) { - if(paint_facesel_test(vc->obact)); - else return 0; - } - else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0; - - buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - if(buf==NULL) return 0; - if(em_vertoffs==0) return 0; - - dr = buf->rect; - - /* draw the mask */ - glDisable(GL_DEPTH_TEST); - - glColor3ub(0, 0, 0); - - /* yah, opengl doesn't do concave... tsk! */ - ED_region_pixelspace(vc->ar); - draw_triangulated(mcords, tot); - - glBegin(GL_LINE_LOOP); /* for zero sized masks, lines */ - for(a=0; a<tot; a++) glVertex2s(mcords[a][0], mcords[a][1]); - glEnd(); - - glFinish(); /* to be sure readpixels sees mask */ - - /* grab mask */ - bufmask= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - drm = bufmask->rect; - if(bufmask==NULL) return 0; /* only when mem alloc fails, go crash somewhere else! */ - - /* build selection lookup */ - selbuf= MEM_callocN(em_vertoffs+1, "selbuf"); - - a= (xmax-xmin+1)*(ymax-ymin+1); - while(a--) { - if(*dr>0 && *dr<=em_vertoffs && *drm==0) selbuf[*dr]= 1; - dr++; drm++; - } - IMB_freeImBuf(buf); - IMB_freeImBuf(bufmask); - return 1; - -} - -/* circle shaped sample area */ -int EM_init_backbuf_circle(ViewContext *vc, short xs, short ys, short rads) -{ - struct ImBuf *buf; - unsigned int *dr; - short xmin, ymin, xmax, ymax, xc, yc; - int radsq; - - /* method in use for face selecting too */ - if(vc->obedit==NULL) { - if(paint_facesel_test(vc->obact)); - else return 0; - } - else if(vc->v3d->drawtype<OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT)==0) return 0; - - xmin= xs-rads; xmax= xs+rads; - ymin= ys-rads; ymax= ys+rads; - buf= view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); - if(em_vertoffs==0) return 0; - if(buf==NULL) return 0; - - dr = buf->rect; - - /* build selection lookup */ - selbuf= MEM_callocN(em_vertoffs+1, "selbuf"); - radsq= rads*rads; - for(yc= -rads; yc<=rads; yc++) { - for(xc= -rads; xc<=rads; xc++, dr++) { - if(xc*xc + yc*yc < radsq) { - if(*dr>0 && *dr<=em_vertoffs) selbuf[*dr]= 1; - } - } - } - - IMB_freeImBuf(buf); - return 1; - -} - -static unsigned int findnearestvert__backbufIndextest(void *handle, unsigned int index) -{ - EditMesh *em= (EditMesh *)handle; - EditVert *eve = BLI_findlink(&em->verts, index-1); - - if(eve && (eve->f & SELECT)) return 0; - return 1; -} -/* ******************************************* */ - -int mesh_layers_menu_charlen(CustomData *data, int type) -{ - int i, len = 0; - /* see if there is a duplicate */ - for(i=0; i<data->totlayer; i++) { - if((&data->layers[i])->type == type) { - /* we could count the chars here but we'll just assumeme each - * is 32 chars with some room for the menu text - 40 should be fine */ - len+=40; - } - } - return len; -} - -/* this function adds menu text into an existing string. - * this string's size should be allocated with mesh_layers_menu_charlen */ -void mesh_layers_menu_concat(CustomData *data, int type, char *str) -{ - int i, count = 0; - char *str_pt = str; - CustomDataLayer *layer; - - /* see if there is a duplicate */ - for(i=0; i<data->totlayer; i++) { - layer = &data->layers[i]; - if(layer->type == type) { - str_pt += sprintf(str_pt, "%s%%x%d|", layer->name, count); - count++; - } - } -} - -int mesh_layers_menu(CustomData *data, int type) { - int ret; - char *str_pt, *str; - - str_pt = str = MEM_mallocN(mesh_layers_menu_charlen(data, type) + 18, "layer menu"); - str[0] = '\0'; - - str_pt += sprintf(str_pt, "Layers%%t|"); - - mesh_layers_menu_concat(data, type, str_pt); - - ret = pupmenu(str); - MEM_freeN(str); - return ret; -} - -void EM_mesh_copy_edge(EditMesh *em, short type) -{ - EditSelection *ese; - short change=0; - - EditEdge *eed, *eed_act; - float vec[3], vec_mid[3], eed_len, eed_len_act; - - if (!em) return; - - ese = em->selected.last; - if (!ese) return; - - eed_act = (EditEdge*)ese->data; - - switch (type) { - case 1: /* copy crease */ - for(eed=em->edges.first; eed; eed=eed->next) { - if (eed->f & SELECT && eed != eed_act && eed->crease != eed_act->crease) { - eed->crease = eed_act->crease; - change = 1; - } - } - break; - case 2: /* copy bevel weight */ - for(eed=em->edges.first; eed; eed=eed->next) { - if (eed->f & SELECT && eed != eed_act && eed->bweight != eed_act->bweight) { - eed->bweight = eed_act->bweight; - change = 1; - } - } - break; - - case 3: /* copy length */ - eed_len_act = len_v3v3(eed_act->v1->co, eed_act->v2->co); - for(eed=em->edges.first; eed; eed=eed->next) { - if (eed->f & SELECT && eed != eed_act) { - - eed_len = len_v3v3(eed->v1->co, eed->v2->co); - - if (eed_len == eed_len_act) continue; - /* if this edge is zero length we cont do anything with it*/ - if (eed_len == 0.0f) continue; - if (eed_len_act == 0.0f) { - add_v3_v3v3(vec_mid, eed->v1->co, eed->v2->co); - mul_v3_fl(vec_mid, 0.5); - VECCOPY(eed->v1->co, vec_mid); - VECCOPY(eed->v2->co, vec_mid); - } else { - /* copy the edge length */ - add_v3_v3v3(vec_mid, eed->v1->co, eed->v2->co); - mul_v3_fl(vec_mid, 0.5); - - /* SCALE 1 */ - sub_v3_v3v3(vec, eed->v1->co, vec_mid); - mul_v3_fl(vec, eed_len_act/eed_len); - add_v3_v3v3(eed->v1->co, vec, vec_mid); - - /* SCALE 2 */ - sub_v3_v3v3(vec, eed->v2->co, vec_mid); - mul_v3_fl(vec, eed_len_act/eed_len); - add_v3_v3v3(eed->v2->co, vec, vec_mid); - } - change = 1; - } - } - - if (change) - recalc_editnormals(em); - - break; - } - - if (change) { -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - - } -} - -void EM_mesh_copy_face(EditMesh *em, wmOperator *op, short type) -{ - short change=0; - - EditFace *efa, *efa_act; - MTFace *tf, *tf_act = NULL; - MCol *mcol, *mcol_act = NULL; - if (!em) return; - efa_act = EM_get_actFace(em, 0); - - if (!efa_act) return; - - tf_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MTFACE); - mcol_act = CustomData_em_get(&em->fdata, efa_act->data, CD_MCOL); - - switch (type) { - case 1: /* copy material */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa->mat_nr != efa_act->mat_nr) { - efa->mat_nr = efa_act->mat_nr; - change = 1; - } - } - break; - case 2: /* copy image */ - if (!tf_act) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers."); - return; - } - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (tf_act->tpage) { - tf->tpage = tf_act->tpage; - tf->mode |= TF_TEX; - } else { - tf->tpage = NULL; - tf->mode &= ~TF_TEX; - } - tf->tile= tf_act->tile; - change = 1; - } - } - break; - - case 3: /* copy UV's */ - if (!tf_act) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers."); - return; - } - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - memcpy(tf->uv, tf_act->uv, sizeof(tf->uv)); - change = 1; - } - } - break; - case 4: /* mode's */ - if (!tf_act) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers."); - return; - } - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - tf->mode= tf_act->mode; - change = 1; - } - } - break; - case 5: /* copy transp's */ - if (!tf_act) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no uv/image layers."); - return; - } - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - tf->transp= tf_act->transp; - change = 1; - } - } - break; - - case 6: /* copy vcols's */ - if (!mcol_act) { - BKE_report(op->reports, RPT_ERROR, "Mesh has no color layers."); - return; - } else { - /* guess the 4th color if needs be */ - float val =- 1; - - if (!efa_act->v4) { - /* guess the othe vale, we may need to use it - * - * Modifying the 4th value of the mcol is ok here since its not seen - * on a triangle - * */ - val = ((float)(mcol_act->r + (mcol_act+1)->r + (mcol_act+2)->r)) / 3; CLAMP(val, 0, 255); - (mcol_act+3)->r = (char)val; - - val = ((float)(mcol_act->g + (mcol_act+1)->g + (mcol_act+2)->g)) / 3; CLAMP(val, 0, 255); - (mcol_act+3)->g = (char)val; - - val = ((float)(mcol_act->b + (mcol_act+1)->b + (mcol_act+2)->b)) / 3; CLAMP(val, 0, 255); - (mcol_act+3)->b = (char)val; - } - - - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT && efa != efa_act) { - /* TODO - make copy from tri to quad guess the 4th vert */ - mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - memcpy(mcol, mcol_act, sizeof(MCol)*4); - change = 1; - } - } - } - break; - } - - if (change) { -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - - } -} - - -void EM_mesh_copy_face_layer(EditMesh *em, wmOperator *op, short type) -{ - short change=0; - - EditFace *efa; - MTFace *tf, *tf_from; - MCol *mcol, *mcol_from; - - if (!em) return; - - switch(type) { - case 7: - case 8: - case 9: - if (CustomData_number_of_layers(&em->fdata, CD_MTFACE)<2) { - BKE_report(op->reports, RPT_ERROR, "mesh does not have multiple uv/image layers"); - return; - } else { - int layer_orig_idx, layer_idx; - - layer_idx = mesh_layers_menu(&em->fdata, CD_MTFACE); - if (layer_idx<0) return; - - /* warning, have not updated mesh pointers however this is not needed since we swicth back */ - layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MTFACE); - if (layer_idx==layer_orig_idx) - return; - - /* get the tfaces */ - CustomData_set_layer_active(&em->fdata, CD_MTFACE, (int)layer_idx); - /* store the tfaces in our temp */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - } - } - CustomData_set_layer_active(&em->fdata, CD_MTFACE, layer_orig_idx); - } - break; - - case 10: /* select vcol layers - make sure this stays in sync with above code */ - if (CustomData_number_of_layers(&em->fdata, CD_MCOL)<2) { - BKE_report(op->reports, RPT_ERROR, "mesh does not have multiple color layers"); - return; - } else { - int layer_orig_idx, layer_idx; - - layer_idx = mesh_layers_menu(&em->fdata, CD_MCOL); - if (layer_idx<0) return; - - /* warning, have not updated mesh pointers however this is not needed since we swicth back */ - layer_orig_idx = CustomData_get_active_layer(&em->fdata, CD_MCOL); - if (layer_idx==layer_orig_idx) - return; - - /* get the tfaces */ - CustomData_set_layer_active(&em->fdata, CD_MCOL, (int)layer_idx); - /* store the tfaces in our temp */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - efa->tmp.p = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - } - } - CustomData_set_layer_active(&em->fdata, CD_MCOL, layer_orig_idx); - - } - break; - } - - /* layer copy only - sanity checks done above */ - switch (type) { - case 7: /* copy UV's only */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - memcpy(tf->uv, tf_from->uv, sizeof(tf->uv)); - change = 1; - } - } - break; - case 8: /* copy image settings only */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (tf_from->tpage) { - tf->tpage = tf_from->tpage; - tf->mode |= TF_TEX; - } else { - tf->tpage = NULL; - tf->mode &= ~TF_TEX; - } - tf->tile= tf_from->tile; - change = 1; - } - } - break; - case 9: /* copy all tface info */ - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - tf_from = (MTFace *)efa->tmp.p; /* not active but easier to use this way */ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - memcpy(tf->uv, ((MTFace *)efa->tmp.p)->uv, sizeof(tf->uv)); - tf->tpage = tf_from->tpage; - tf->mode = tf_from->mode; - tf->transp = tf_from->transp; - change = 1; - } - } - break; - case 10: - for(efa=em->faces.first; efa; efa=efa->next) { - if (efa->f & SELECT) { - mcol_from = (MCol *)efa->tmp.p; - mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); - memcpy(mcol, mcol_from, sizeof(MCol)*4); - change = 1; - } - } - break; - } - - if (change) { -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - - } -} - - -/* ctrl+c in mesh editmode */ -void mesh_copy_menu(EditMesh *em, wmOperator *op) -{ - EditSelection *ese; - int ret; - if (!em) return; - - ese = em->selected.last; - - /* Faces can have a NULL ese, so dont return on a NULL ese here */ - - if(ese && ese->type == EDITVERT) { - /* EditVert *ev, *ev_act = (EditVert*)ese->data; - ret= pupmenu(""); */ - } else if(ese && ese->type == EDITEDGE) { - ret= pupmenu("Copy Active Edge to Selected%t|Crease%x1|Bevel Weight%x2|Length%x3"); - if (ret<1) return; - - EM_mesh_copy_edge(em, ret); - - } else if(ese==NULL || ese->type == EDITFACE) { - ret= pupmenu( - "Copy Face Selected%t|" - "Active Material%x1|Active Image%x2|Active UV Coords%x3|" - "Active Mode%x4|Active Transp%x5|Active Vertex Colors%x6|%l|" - - "TexFace UVs from layer%x7|" - "TexFace Images from layer%x8|" - "TexFace All from layer%x9|" - "Vertex Colors from layer%x10"); - if (ret<1) return; - - if (ret<=6) { - EM_mesh_copy_face(em, op, ret); - } else { - EM_mesh_copy_face_layer(em, op, ret); - } - } -} - -/* **************** LOOP SELECTS *************** */ - -#if 0 -/* selects quads in loop direction of indicated edge */ -/* only flush over edges with valence <= 2 */ -void faceloop_select(EditMesh *em, EditEdge *startedge, int select) -{ - EditEdge *eed; - EditFace *efa; - int looking= 1; - - /* in eed->f1 we put the valence (amount of faces in edge) */ - /* in eed->f2 we put tagged flag as correct loop */ - /* in efa->f1 we put tagged flag as correct to select */ - - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; - eed->f2= 0; - } - for(efa= em->faces.first; efa; efa= efa->next) { - efa->f1= 0; - if(efa->h==0) { - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - } - - /* tag startedge OK*/ - startedge->f2= 1; - - while(looking) { - looking= 0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0 && efa->e4 && efa->f1==0) { /* not done quad */ - if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */ - - /* if edge tagged, select opposing edge and mark face ok */ - if(efa->e1->f2) { - efa->e3->f2= 1; - efa->f1= 1; - looking= 1; - } - else if(efa->e2->f2) { - efa->e4->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e3->f2) { - efa->e1->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e4->f2) { - efa->e2->f2= 1; - efa->f1= 1; - looking= 1; - } - } - } - } - } - - /* (de)select the faces */ - if(select!=2) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->f1) EM_select_face(efa, select); - } - } -} -#endif - - -/* helper for edgeloop_select, checks for eed->f2 tag in faces */ -static int edge_not_in_tagged_face(EditMesh *em, EditEdge *eed) -{ - EditFace *efa; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0) { - if(efa->e1==eed || efa->e2==eed || efa->e3==eed || efa->e4==eed) { /* edge is in face */ - if(efa->e1->f2 || efa->e2->f2 || efa->e3->f2 || (efa->e4 && efa->e4->f2)) { /* face is tagged */ - return 0; - } - } - } - } - return 1; -} - -/* selects or deselects edges that: -- if edges has 2 faces: - - has vertices with valence of 4 - - not shares face with previous edge -- if edge has 1 face: - - has vertices with valence 4 - - not shares face with previous edge - - but also only 1 face -- if edge no face: - - has vertices with valence 2 -*/ -static void edgeloop_select(EditMesh *em, EditEdge *starteed, int select) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - int looking= 1; - - /* in f1 we put the valence (amount of edges in a vertex, or faces in edge) */ - /* in eed->f2 and efa->f1 we put tagged flag as correct loop */ - for(eve= em->verts.first; eve; eve= eve->next) { - eve->f1= 0; - eve->f2= 0; - } - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; - eed->f2= 0; - if((eed->h & 1)==0) { /* fgon edges add to valence too */ - eed->v1->f1++; eed->v2->f1++; - } - } - for(efa= em->faces.first; efa; efa= efa->next) { - efa->f1= 0; - if(efa->h==0) { - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - } - - /* looped edges & vertices get tagged f2 */ - starteed->f2= 1; - if(starteed->v1->f1<5) starteed->v1->f2= 1; - if(starteed->v2->f1<5) starteed->v2->f2= 1; - /* sorry, first edge isnt even ok */ - if(starteed->v1->f2==0 && starteed->v2->f2==0) looking= 0; - - while(looking) { - looking= 0; - - /* find correct valence edges which are not tagged yet, but connect to tagged one */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h==0 && eed->f2==0) { /* edge not hidden, not tagged */ - if( (eed->v1->f1<5 && eed->v1->f2) || (eed->v2->f1<5 && eed->v2->f2)) { /* valence of vertex OK, and is tagged */ - /* new edge is not allowed to be in face with tagged edge */ - if(edge_not_in_tagged_face(em, eed)) { - if(eed->f1==starteed->f1) { /* same amount of faces */ - looking= 1; - eed->f2= 1; - if(eed->v2->f1<5) eed->v2->f2= 1; - if(eed->v1->f1<5) eed->v1->f2= 1; - } - } - } - } - } - } - /* and we do the select */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f2) EM_select_edge(eed, select); - } -} - -/* - Almostly exactly the same code as faceloop select -*/ -static void edgering_select(EditMesh *em, EditEdge *startedge, int select) -{ - EditEdge *eed; - EditFace *efa; - int looking= 1; - - /* in eed->f1 we put the valence (amount of faces in edge) */ - /* in eed->f2 we put tagged flag as correct loop */ - /* in efa->f1 we put tagged flag as correct to select */ - - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; - eed->f2= 0; - } - for(efa= em->faces.first; efa; efa= efa->next) { - efa->f1= 0; - if(efa->h==0) { - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - } - - /* tag startedge OK */ - startedge->f2= 1; - - while(looking) { - looking= 0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e4 && efa->f1==0 && !efa->h) { /* not done quad */ - if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { /* valence ok */ - - /* if edge tagged, select opposing edge and mark face ok */ - if(efa->e1->f2) { - efa->e3->f2= 1; - efa->f1= 1; - looking= 1; - } - else if(efa->e2->f2) { - efa->e4->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e3->f2) { - efa->e1->f2= 1; - efa->f1= 1; - looking= 1; - } - if(efa->e4->f2) { - efa->e2->f2= 1; - efa->f1= 1; - looking= 1; - } - } - } - } - } - - /* (de)select the edges */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f2) EM_select_edge(eed, select); - } -} - -static int loop_multiselect(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - EditEdge *eed; - EditEdge **edarray; - int edindex, edfirstcount; - int looptype= RNA_boolean_get(op->ptr, "ring"); - - /* sets em->totedgesel */ - EM_nedges_selected(em); - - edarray = MEM_mallocN(sizeof(EditEdge*)*em->totedgesel,"edge array"); - edindex = 0; - edfirstcount = em->totedgesel; - - for(eed=em->edges.first; eed; eed=eed->next){ - if(eed->f&SELECT){ - edarray[edindex] = eed; - edindex += 1; - } - } - - if(looptype){ - for(edindex = 0; edindex < edfirstcount; edindex +=1){ - eed = edarray[edindex]; - edgering_select(em, eed,SELECT); - } - EM_selectmode_flush(em); - } - else{ - for(edindex = 0; edindex < edfirstcount; edindex +=1){ - eed = edarray[edindex]; - edgeloop_select(em, eed,SELECT); - } - EM_selectmode_flush(em); - } - MEM_freeN(edarray); -// if (EM_texFaceCheck()) - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -/* ************************* */ -/* ************************* */ - -/* swap is 0 or 1, if 1 it hides not selected */ -void EM_hide_mesh(EditMesh *em, int swap) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - int a; - - if(em==NULL) return; - - /* hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */ - /* - vertex hidden, always means edge is hidden too - - edge hidden, always means face is hidden too - - face hidden, only set face hide - - then only flush back down what's absolute hidden - */ - if(em->selectmode & SCE_SELECT_VERTEX) { - for(eve= em->verts.first; eve; eve= eve->next) { - if((eve->f & SELECT)!=swap) { - eve->f &= ~SELECT; - eve->h= 1; - } - } - - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->v1->h || eed->v2->h) { - eed->h |= 1; - eed->f &= ~SELECT; - } - } - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) { - efa->h= 1; - efa->f &= ~SELECT; - } - } - } - else if(em->selectmode & SCE_SELECT_EDGE) { - - for(eed= em->edges.first; eed; eed= eed->next) { - if((eed->f & SELECT)!=swap) { - eed->h |= 1; - EM_select_edge(eed, 0); - } - } - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->e1->h & 1 || efa->e2->h & 1 || efa->e3->h & 1 || (efa->e4 && efa->e4->h & 1)) { - efa->h= 1; - efa->f &= ~SELECT; - } - } - } - else { - - for(efa= em->faces.first; efa; efa= efa->next) { - if((efa->f & SELECT)!=swap) { - efa->h= 1; - EM_select_face(efa, 0); - } - } - } - - /* flush down, only whats 100% hidden */ - for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0; - for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0; - - if(em->selectmode & SCE_SELECT_FACE) { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h) a= 1; else a= 2; - efa->e1->f1 |= a; - efa->e2->f1 |= a; - efa->e3->f1 |= a; - if(efa->e4) efa->e4->f1 |= a; - /* When edges are not delt with in their own loop, we need to explicitly re-selct select edges that are joined to unselected faces */ - if (swap && (em->selectmode == SCE_SELECT_FACE) && (efa->f & SELECT)) { - EM_select_face(efa, 1); - } - } - } - - if(em->selectmode >= SCE_SELECT_EDGE) { - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f1==1) eed->h |= 1; - if(eed->h & 1) a= 1; else a= 2; - eed->v1->f1 |= a; - eed->v2->f1 |= a; - } - } - - if(em->selectmode >= SCE_SELECT_VERTEX) { - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f1==1) eve->h= 1; - } - } - - em->totedgesel= em->totfacesel= em->totvertsel= 0; -// if(EM_texFaceCheck()) - - // DAG_id_flush_update(obedit->data, OB_RECALC_DATA); -} - -void EM_reveal_mesh(EditMesh *em) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - if(em==NULL) return; - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->h) { - eve->h= 0; - eve->f |= SELECT; - } - } - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h & 1) { - eed->h &= ~1; - if(em->selectmode & SCE_SELECT_VERTEX); - else EM_select_edge(eed, 1); - } - } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h) { - efa->h= 0; - if(em->selectmode & (SCE_SELECT_EDGE|SCE_SELECT_VERTEX)); - else EM_select_face(efa, 1); - } - } - - EM_fgon_flags(em); /* redo flags and indices for fgons */ - EM_selectmode_flush(em); - -// if (EM_texFaceCheck()) -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); -} - -int select_by_number_vertices_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - EditFace *efa; - int numverts= RNA_enum_get(op->ptr, "type"); - - /* Selects trias/qiads or isolated verts, and edges that do not have 2 neighboring - * faces - */ - - /* for loose vertices/edges, we first select all, loop below will deselect */ - if(numverts==5) { - EM_set_flag_all(em, SELECT); - } - else if(em->selectmode!=SCE_SELECT_FACE) { - BKE_report(op->reports, RPT_ERROR, "Only works in face selection mode"); - return OPERATOR_CANCELLED; - } - - for(efa= em->faces.first; efa; efa= efa->next) { - if (efa->e4) { - EM_select_face(efa, (numverts==4) ); - } - else { - EM_select_face(efa, (numverts==3) ); - } - } - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_select_by_number_vertices(wmOperatorType *ot) -{ - static const EnumPropertyItem type_items[]= { - {3, "TRIANGLES", 0, "Triangles", NULL}, - {4, "QUADS", 0, "Triangles", NULL}, - {5, "OTHER", 0, "Other", NULL}, - {0, NULL, 0, NULL, NULL}}; - - /* identifiers */ - ot->name= "Select by Number of Vertices"; - ot->description= "Select vertices or faces by vertex count."; - ot->idname= "MESH_OT_select_by_number_vertices"; - - /* api callbacks */ - ot->exec= select_by_number_vertices_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_enum(ot->srna, "type", type_items, 3, "Type", "Type of elements to select."); -} - - -int select_mirror_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - int extend= RNA_boolean_get(op->ptr, "extend"); - - EM_select_mirrored(obedit, em, extend); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_select_mirror(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Mirror"; - ot->description= "Select mesh items at mirrored locations."; - ot->idname= "MESH_OT_select_mirror"; - - /* api callbacks */ - ot->exec= select_mirror_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the existing selection"); -} - -static int select_sharp_edges_exec(bContext *C, wmOperator *op) -{ - /* Find edges that have exactly two neighboring faces, - * check the angle between those faces, and if angle is - * small enough, select the edge - */ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - EditEdge *eed; - EditFace *efa; - EditFace **efa1; - EditFace **efa2; - intptr_t edgecount = 0, i = 0; - float sharpness, fsharpness; - - /* 'standard' behaviour - check if selected, then apply relevant selection */ - - if(em->selectmode==SCE_SELECT_FACE) { - BKE_report(op->reports, RPT_ERROR, "Doesn't work in face selection mode"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - sharpness= RNA_float_get(op->ptr, "sharpness"); - fsharpness = ((180.0 - sharpness) * M_PI) / 180.0; - - /* count edges, use tmp.l */ - eed= em->edges.first; - while(eed) { - edgecount++; - eed->tmp.l = i; - eed= eed->next; - ++i; - } - - /* for each edge, we want a pointer to two adjacent faces */ - efa1 = MEM_callocN(edgecount*sizeof(EditFace *), - "pairs of edit face pointers"); - efa2 = MEM_callocN(edgecount*sizeof(EditFace *), - "pairs of edit face pointers"); - -#define face_table_edge(eed) { \ - i = eed->tmp.l; \ - if (i != -1) { \ - if (efa1[i]) { \ - if (efa2[i]) { \ - /* invalidate, edge has more than two neighbors */ \ - eed->tmp.l = -1; \ - } \ - else { \ - efa2[i] = efa; \ - } \ - } \ - else { \ - efa1[i] = efa; \ - } \ - } \ - } - - /* find the adjacent faces of each edge, we want only two */ - efa= em->faces.first; - while(efa) { - face_table_edge(efa->e1); - face_table_edge(efa->e2); - face_table_edge(efa->e3); - if (efa->e4) { - face_table_edge(efa->e4); - } - efa= efa->next; - } - -#undef face_table_edge - - eed = em->edges.first; - while(eed) { - i = eed->tmp.l; - if (i != -1) { - /* edge has two or less neighboring faces */ - if ( (efa1[i]) && (efa2[i]) ) { - /* edge has exactly two neighboring faces, check angle */ - float angle; - angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] + - efa1[i]->n[1]*efa2[i]->n[1] + - efa1[i]->n[2]*efa2[i]->n[2]); - if (fabs(angle) >= fsharpness) - EM_select_edge(eed, 1); - } - } - - eed= eed->next; - } - - MEM_freeN(efa1); - MEM_freeN(efa2); - -// if (EM_texFaceCheck()) - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); //TODO is this needed ? - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_edges_select_sharp(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Sharp Edges"; - ot->description= "Marked selected edges as sharp."; - ot->idname= "MESH_OT_edges_select_sharp"; - - /* api callbacks */ - ot->exec= select_sharp_edges_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_float(ot->srna, "sharpness", 0.01f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f); -} - - -static void select_linked_flat_faces(EditMesh *em, wmOperator *op, float sharpness) -{ - /* Find faces that are linked to selected faces that are - * relatively flat (angle between faces is higher than - * specified angle) - */ - EditEdge *eed; - EditFace *efa; - EditFace **efa1; - EditFace **efa2; - intptr_t edgecount = 0, i, faceselcount=0, faceselcountold=0; - float fsharpness; - - if(em->selectmode!=SCE_SELECT_FACE) { - BKE_report(op->reports, RPT_ERROR, "Only works in face selection mode"); - return; - } - - fsharpness = ((180.0 - sharpness) * M_PI) / 180.0; - - i=0; - /* count edges, use tmp.l */ - eed= em->edges.first; - while(eed) { - edgecount++; - eed->tmp.l = i; - eed= eed->next; - ++i; - } - - /* for each edge, we want a pointer to two adjacent faces */ - efa1 = MEM_callocN(edgecount*sizeof(EditFace *), - "pairs of edit face pointers"); - efa2 = MEM_callocN(edgecount*sizeof(EditFace *), - "pairs of edit face pointers"); - -#define face_table_edge(eed) { \ - i = eed->tmp.l; \ - if (i != -1) { \ - if (efa1[i]) { \ - if (efa2[i]) { \ - /* invalidate, edge has more than two neighbors */ \ - eed->tmp.l = -1; \ - } \ - else { \ - efa2[i] = efa; \ - } \ - } \ - else { \ - efa1[i] = efa; \ - } \ - } \ - } - - /* find the adjacent faces of each edge, we want only two */ - efa= em->faces.first; - while(efa) { - face_table_edge(efa->e1); - face_table_edge(efa->e2); - face_table_edge(efa->e3); - if (efa->e4) { - face_table_edge(efa->e4); - } - - /* while were at it, count the selected faces */ - if (efa->f & SELECT) ++faceselcount; - - efa= efa->next; - } - -#undef face_table_edge - - eed= em->edges.first; - while(eed) { - i = eed->tmp.l; - if (i != -1) { - /* edge has two or less neighboring faces */ - if ( (efa1[i]) && (efa2[i]) ) { - /* edge has exactly two neighboring faces, check angle */ - float angle; - angle = saacos(efa1[i]->n[0]*efa2[i]->n[0] + - efa1[i]->n[1]*efa2[i]->n[1] + - efa1[i]->n[2]*efa2[i]->n[2]); - /* invalidate: edge too sharp */ - if (fabs(angle) >= fsharpness) - eed->tmp.l = -1; - } - else { - /* invalidate: less than two neighbors */ - eed->tmp.l = -1; - } - } - - eed= eed->next; - } - -#define select_flat_neighbor(eed) { \ - i = eed->tmp.l; \ - if (i!=-1) { \ - if (! (efa1[i]->f & SELECT) ) { \ - EM_select_face(efa1[i], 1); \ - ++faceselcount; \ - } \ - if (! (efa2[i]->f & SELECT) ) { \ - EM_select_face(efa2[i], 1); \ - ++faceselcount; \ - } \ - } \ - } - - while (faceselcount != faceselcountold) { - faceselcountold = faceselcount; - - efa= em->faces.first; - while(efa) { - if (efa->f & SELECT) { - select_flat_neighbor(efa->e1); - select_flat_neighbor(efa->e2); - select_flat_neighbor(efa->e3); - if (efa->e4) { - select_flat_neighbor(efa->e4); - } - } - efa= efa->next; - } - } - -#undef select_flat_neighbor - - MEM_freeN(efa1); - MEM_freeN(efa2); - -// if (EM_texFaceCheck()) - -} - -static int select_linked_flat_faces_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - select_linked_flat_faces(em, op, RNA_float_get(op->ptr, "sharpness")); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_faces_select_linked_flat(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Linked Flat Faces"; - ot->description= "Select linked faces by angle."; - ot->idname= "MESH_OT_faces_select_linked_flat"; - - /* api callbacks */ - ot->exec= select_linked_flat_faces_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_float(ot->srna, "sharpness", 0.0f, 0.0f, FLT_MAX, "sharpness", "", 0.0f, 180.0f); -} - -void select_non_manifold(EditMesh *em, wmOperator *op ) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - /* Selects isolated verts, and edges that do not have 2 neighboring - * faces - */ - - if(em->selectmode==SCE_SELECT_FACE) { - BKE_report(op->reports, RPT_ERROR, "Doesn't work in face selection mode"); - return; - } - - eve= em->verts.first; - while(eve) { - /* this will count how many edges are connected - * to this vert */ - eve->f1= 0; - eve= eve->next; - } - - eed= em->edges.first; - while(eed) { - /* this will count how many faces are connected to - * this edge */ - eed->f1= 0; - /* increase edge count for verts */ - ++eed->v1->f1; - ++eed->v2->f1; - eed= eed->next; - } - - efa= em->faces.first; - while(efa) { - /* increase face count for edges */ - ++efa->e1->f1; - ++efa->e2->f1; - ++efa->e3->f1; - if (efa->e4) - ++efa->e4->f1; - efa= efa->next; - } - - /* select verts that are attached to an edge that does not - * have 2 neighboring faces */ - eed= em->edges.first; - while(eed) { - if (eed->h==0 && eed->f1 != 2) { - EM_select_edge(eed, 1); - } - eed= eed->next; - } - - /* select isolated verts */ - if(em->selectmode & SCE_SELECT_VERTEX) { - eve= em->verts.first; - while(eve) { - if (eve->f1 == 0) { - if (!eve->h) eve->f |= SELECT; - } - eve= eve->next; - } - } - -// if (EM_texFaceCheck()) - -} - -static int select_non_manifold_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - select_non_manifold(em, op); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_select_non_manifold(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Non Manifold"; - ot->description= "Select all non-manifold vertices or edges."; - ot->idname= "MESH_OT_select_non_manifold"; - - /* api callbacks */ - ot->exec= select_non_manifold_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int bmesh_test_exec(bContext *C, wmOperator *op) -{ - return OPERATOR_CANCELLED; -} -/* ******************** (de)select all operator **************** */ - -void EM_toggle_select_all(EditMesh *em) /* exported for UV */ -{ - if(EM_nvertices_selected(em)) - EM_clear_flag_all(em, SELECT); - else - EM_set_flag_all(em, SELECT); -} - -void EM_select_all(EditMesh *em) -{ - EM_set_flag_all(em, SELECT); -} - -void MESH_OT_bmesh_test(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "bmesh test op"; - ot->idname= "MESH_OT_bmesh_test"; - - /* api callbacks */ - ot->exec= bmesh_test_exec; - ot->poll= ED_operator_editmesh; - - WM_operator_properties_select_all(ot); -} - -/* ******************** **************** */ -void EM_select_more(EditMesh *em) -{ - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) eve->f1= 1; - else eve->f1 = 0; - } - - /* set f1 flags in vertices to select 'more' */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h==0) { - if (eed->v1->f & SELECT) - eed->v2->f1 = 1; - if (eed->v2->f & SELECT) - eed->v1->f1 = 1; - } - } - - /* new selected edges, but not in facemode */ - if(em->selectmode <= SCE_SELECT_EDGE) { - - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h==0) { - if(eed->v1->f1 && eed->v2->f1) EM_select_edge(eed, 1); - } - } - } - /* new selected faces */ - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0) { - if(efa->v1->f1 && efa->v2->f1 && efa->v3->f1 && (efa->v4==NULL || efa->v4->f1)) - EM_select_face(efa, 1); - } - } -} - -void EM_select_less(EditMesh *em) -{ - EditEdge *eed; - EditFace *efa; - - if(em->selectmode <= SCE_SELECT_EDGE) { - /* eed->f1 == 1: edge with a selected and deselected vert */ - - for(eed= em->edges.first; eed; eed= eed->next) { - eed->f1= 0; - if(eed->h==0) { - - if ( !(eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) - eed->f1= 1; - if ( (eed->v1->f & SELECT) && !(eed->v2->f & SELECT) ) - eed->f1= 1; - } - } - - /* deselect edges with flag set */ - for(eed= em->edges.first; eed; eed= eed->next) { - if (eed->h==0 && eed->f1 == 1) { - EM_select_edge(eed, 0); - } - } - EM_deselect_flush(em); - - } - else { - /* deselect faces with 1 or more deselect edges */ - /* eed->f1 == mixed selection edge */ - for(eed= em->edges.first; eed; eed= eed->next) eed->f1= 0; - - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0) { - if(efa->f & SELECT) { - efa->e1->f1 |= 1; - efa->e2->f1 |= 1; - efa->e3->f1 |= 1; - if(efa->e4) efa->e4->f1 |= 1; - } - else { - efa->e1->f1 |= 2; - efa->e2->f1 |= 2; - efa->e3->f1 |= 2; - if(efa->e4) efa->e4->f1 |= 2; - } - } - } - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0) { - if(efa->e1->f1==3 || efa->e2->f1==3 || efa->e3->f1==3 || (efa->e4 && efa->e4->f1==3)) { - EM_select_face(efa, 0); - } - } - } - EM_selectmode_flush(em); - - } -} - -static void selectrandom_mesh(EditMesh *em, float randfac) /* randomly selects a user-set % of vertices/edges/faces */ -{ -#if 0 - EditVert *eve; - EditEdge *eed; - EditFace *efa; - - BLI_srand( BLI_rand() ); /* random seed */ - - if(em->selectmode & SCE_SELECT_VERTEX) { - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->h==0) { - if (BLI_frand() < randfac) - eve->f |= SELECT; - } - } - EM_selectmode_flush(em); - } - else if(em->selectmode & SCE_SELECT_EDGE) { - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->h==0) { - if (BLI_frand() < randfac) - EM_select_edge(eed, 1); - } - } - EM_selectmode_flush(em); - } - else { - for(efa= em->faces.first; efa; efa= efa->next) { - if(efa->h==0) { - if (BLI_frand() < randfac) - EM_select_face(efa, 1); - } - } - - EM_selectmode_flush(em); - } -// if (EM_texFaceCheck()) -#endif -} - -static int mesh_select_random_exec(bContext *C, wmOperator *op) -{ -#if 0 - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(((Mesh *)obedit->data)); - - if(!RNA_boolean_get(op->ptr, "extend")) - EM_deselect_all(em); - - selectrandom_mesh(em, RNA_float_get(op->ptr, "percent")/100.0f); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); -#endif - return OPERATOR_FINISHED; -} - -void MESH_OT_select_random(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Select Random"; - ot->description= "Randomly select vertices."; - ot->idname= "MESH_OT_select_random"; - - /* api callbacks */ - ot->exec= mesh_select_random_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly.", 0.f, 100.0f); - RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first."); -} - -void EM_select_by_material(EditMesh *em, int index) -{ - EditFace *efa; - - for (efa=em->faces.first; efa; efa= efa->next) { - if (efa->mat_nr==index) { - EM_select_face(efa, 1); - } - } - - EM_selectmode_flush(em); -} - -void EM_deselect_by_material(EditMesh *em, int index) -{ - EditFace *efa; - - for (efa=em->faces.first; efa; efa= efa->next) { - if (efa->mat_nr==index) { - EM_select_face(efa, 0); - } - } - - EM_selectmode_flush(em); -} - -/* **************** NORMALS ************** */ -void EM_recalc_normal_direction(EditMesh *em, int inside, int select) /* makes faces righthand turning */ -{ - EditEdge *eed, *ed1, *ed2, *ed3, *ed4; - EditFace *efa, *startvl; - float maxx, nor[3], cent[3]; - int totsel, found, foundone, direct, turn, tria_nr; - - /* based at a select-connected to witness loose objects */ - - /* count per edge the amount of faces */ - - /* find the ultimate left, front, upper face (not manhattan dist!!) */ - /* also evaluate both triangle cases in quad, since these can be non-flat */ - - /* put normal to the outside, and set the first direction flags in edges */ - - /* then check the object, and set directions / direction-flags: but only for edges with 1 or 2 faces */ - /* this is in fact the 'select connected' */ - - /* in case (selected) faces were not done: start over with 'find the ultimate ...' */ - - waitcursor(1); - - eed= em->edges.first; - while(eed) { - eed->f2= 0; /* edge direction */ - eed->f1= 0; /* counter */ - eed= eed->next; - } - - /* count faces and edges */ - totsel= 0; - efa= em->faces.first; - while(efa) { - if(select==0 || (efa->f & SELECT) ) { - efa->f1= 1; - totsel++; - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->v4) efa->e4->f1++; - } - else efa->f1= 0; - - efa= efa->next; - } - - while(totsel>0) { - /* from the outside to the inside */ - - efa= em->faces.first; - startvl= NULL; - maxx= -1.0e10; - tria_nr= 0; - - while(efa) { - if(efa->f1) { - cent_tri_v3(cent, efa->v1->co, efa->v2->co, efa->v3->co); - cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2]; - - if(cent[0]>maxx) { - maxx= cent[0]; - startvl= efa; - tria_nr= 0; - } - if(efa->v4) { - cent_tri_v3(cent, efa->v1->co, efa->v3->co, efa->v4->co); - cent[0]= cent[0]*cent[0] + cent[1]*cent[1] + cent[2]*cent[2]; - - if(cent[0]>maxx) { - maxx= cent[0]; - startvl= efa; - tria_nr= 1; - } - } - } - efa= efa->next; - } - - if (startvl==NULL) - startvl= em->faces.first; - - /* set first face correct: calc normal */ - - if(tria_nr==1) { - normal_tri_v3( nor,startvl->v1->co, startvl->v3->co, startvl->v4->co); - cent_tri_v3(cent, startvl->v1->co, startvl->v3->co, startvl->v4->co); - } else { - normal_tri_v3( nor,startvl->v1->co, startvl->v2->co, startvl->v3->co); - cent_tri_v3(cent, startvl->v1->co, startvl->v2->co, startvl->v3->co); - } - /* first normal is oriented this way or the other */ - if(inside) { - if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] > 0.0) flipface(em, startvl); - } - else { - if(cent[0]*nor[0]+cent[1]*nor[1]+cent[2]*nor[2] < 0.0) flipface(em, startvl); - } - - eed= startvl->e1; - if(eed->v1==startvl->v1) eed->f2= 1; - else eed->f2= 2; - - eed= startvl->e2; - if(eed->v1==startvl->v2) eed->f2= 1; - else eed->f2= 2; - - eed= startvl->e3; - if(eed->v1==startvl->v3) eed->f2= 1; - else eed->f2= 2; - - eed= startvl->e4; - if(eed) { - if(eed->v1==startvl->v4) eed->f2= 1; - else eed->f2= 2; - } - - startvl->f1= 0; - totsel--; - - /* test normals */ - found= 1; - direct= 1; - while(found) { - found= 0; - if(direct) efa= em->faces.first; - else efa= em->faces.last; - while(efa) { - if(efa->f1) { - turn= 0; - foundone= 0; - - ed1= efa->e1; - ed2= efa->e2; - ed3= efa->e3; - ed4= efa->e4; - - if(ed1->f2) { - if(ed1->v1==efa->v1 && ed1->f2==1) turn= 1; - if(ed1->v2==efa->v1 && ed1->f2==2) turn= 1; - foundone= 1; - } - else if(ed2->f2) { - if(ed2->v1==efa->v2 && ed2->f2==1) turn= 1; - if(ed2->v2==efa->v2 && ed2->f2==2) turn= 1; - foundone= 1; - } - else if(ed3->f2) { - if(ed3->v1==efa->v3 && ed3->f2==1) turn= 1; - if(ed3->v2==efa->v3 && ed3->f2==2) turn= 1; - foundone= 1; - } - else if(ed4 && ed4->f2) { - if(ed4->v1==efa->v4 && ed4->f2==1) turn= 1; - if(ed4->v2==efa->v4 && ed4->f2==2) turn= 1; - foundone= 1; - } - - if(foundone) { - found= 1; - totsel--; - efa->f1= 0; - - if(turn) { - if(ed1->v1==efa->v1) ed1->f2= 2; - else ed1->f2= 1; - if(ed2->v1==efa->v2) ed2->f2= 2; - else ed2->f2= 1; - if(ed3->v1==efa->v3) ed3->f2= 2; - else ed3->f2= 1; - if(ed4) { - if(ed4->v1==efa->v4) ed4->f2= 2; - else ed4->f2= 1; - } - - flipface(em, efa); - - } - else { - if(ed1->v1== efa->v1) ed1->f2= 1; - else ed1->f2= 2; - if(ed2->v1==efa->v2) ed2->f2= 1; - else ed2->f2= 2; - if(ed3->v1==efa->v3) ed3->f2= 1; - else ed3->f2= 2; - if(ed4) { - if(ed4->v1==efa->v4) ed4->f2= 1; - else ed4->f2= 2; - } - } - } - } - if(direct) efa= efa->next; - else efa= efa->prev; - } - direct= 1-direct; - } - } - - recalc_editnormals(em); - -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - - waitcursor(0); -} - -/* ********** ALIGN WITH VIEW **************** */ -static void editmesh_calc_selvert_center(EditMesh *em, float cent_r[3]) -{ - EditVert *eve; - int nsel= 0; - - cent_r[0]= cent_r[1]= cent_r[0]= 0.0; - - for (eve= em->verts.first; eve; eve= eve->next) { - if (eve->f & SELECT) { - cent_r[0]+= eve->co[0]; - cent_r[1]+= eve->co[1]; - cent_r[2]+= eve->co[2]; - nsel++; - } - } - - if (nsel) { - cent_r[0]/= nsel; - cent_r[1]/= nsel; - cent_r[2]/= nsel; - } -} - -static int mface_is_selected(MFace *mf) -{ - return (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL)); -} - - /* XXX, code for both these functions should be abstract, - * then unified, then written for other things (like objects, - * which would use same as vertices method), then added - * to interface! Hoera! - zr - */ -void faceselect_align_view_to_selected(View3D *v3d, RegionView3D *rv3d, Mesh *me, wmOperator *op, int axis) -{ - float norm[3]; - int i, totselected = 0; - - norm[0]= norm[1]= norm[2]= 0.0; - for (i=0; i<me->totface; i++) { - MFace *mf= ((MFace*) me->mface) + i; - - if (mface_is_selected(mf)) { - float *v1, *v2, *v3, fno[3]; - - v1= me->mvert[mf->v1].co; - v2= me->mvert[mf->v2].co; - v3= me->mvert[mf->v3].co; - if (mf->v4) { - float *v4= me->mvert[mf->v4].co; - normal_quad_v3( fno,v1, v2, v3, v4); - } else { - normal_tri_v3( fno,v1, v2, v3); - } - - norm[0]+= fno[0]; - norm[1]+= fno[1]; - norm[2]+= fno[2]; - - totselected++; - } - } - - if (totselected == 0) - BKE_report(op->reports, RPT_ERROR, "No faces selected."); - else - view3d_align_axis_to_vector(v3d, rv3d, axis, norm); -} - -/* helper for below, to survive non-uniform scaled objects */ -static void face_getnormal_obspace(Object *obedit, EditFace *efa, float *fno) -{ - float vec[4][3]; - - VECCOPY(vec[0], efa->v1->co); - mul_mat3_m4_v3(obedit->obmat, vec[0]); - VECCOPY(vec[1], efa->v2->co); - mul_mat3_m4_v3(obedit->obmat, vec[1]); - VECCOPY(vec[2], efa->v3->co); - mul_mat3_m4_v3(obedit->obmat, vec[2]); - if(efa->v4) { - VECCOPY(vec[3], efa->v4->co); - mul_mat3_m4_v3(obedit->obmat, vec[3]); - - normal_quad_v3( fno,vec[0], vec[1], vec[2], vec[3]); - } - else normal_tri_v3( fno,vec[0], vec[1], vec[2]); -} - - -void editmesh_align_view_to_selected(Object *obedit, EditMesh *em, wmOperator *op, View3D *v3d, RegionView3D *rv3d, int axis) -{ - int nselverts= EM_nvertices_selected(em); - float norm[3]={0.0, 0.0, 0.0}; /* used for storing the mesh normal */ - - if (nselverts==0) { - BKE_report(op->reports, RPT_ERROR, "No faces or vertices selected."); - } - else if (EM_nfaces_selected(em)) { - EditFace *efa; - for (efa= em->faces.first; efa; efa= efa->next) { - if (faceselectedAND(efa, SELECT)) { - float fno[3]; - - face_getnormal_obspace(obedit, efa, fno); - norm[0]+= fno[0]; - norm[1]+= fno[1]; - norm[2]+= fno[2]; - } - } - - view3d_align_axis_to_vector(v3d, rv3d, axis, norm); - } - else if (nselverts>2) { - float cent[3]; - EditVert *eve, *leve= NULL; - - editmesh_calc_selvert_center(em, cent); - for (eve= em->verts.first; eve; eve= eve->next) { - if (eve->f & SELECT) { - if (leve) { - float tno[3]; - normal_tri_v3( tno,cent, leve->co, eve->co); - - /* XXX, fixme, should be flipped intp a - * consistent direction. -zr - */ - norm[0]+= tno[0]; - norm[1]+= tno[1]; - norm[2]+= tno[2]; - } - leve= eve; - } - } - - mul_mat3_m4_v3(obedit->obmat, norm); - view3d_align_axis_to_vector(v3d, rv3d, axis, norm); - } - else if (nselverts==2) { /* Align view to edge (or 2 verts) */ - EditVert *eve, *leve= NULL; - - for (eve= em->verts.first; eve; eve= eve->next) { - if (eve->f & SELECT) { - if (leve) { - norm[0]= leve->co[0] - eve->co[0]; - norm[1]= leve->co[1] - eve->co[1]; - norm[2]= leve->co[2] - eve->co[2]; - break; /* we know there are only 2 verts so no need to keep looking */ - } - leve= eve; - } - } - mul_mat3_m4_v3(obedit->obmat, norm); - view3d_align_axis_to_vector(v3d, rv3d, axis, norm); - } - else if (nselverts==1) { /* Align view to vert normal */ - EditVert *eve; - - for (eve= em->verts.first; eve; eve= eve->next) { - if (eve->f & SELECT) { - norm[0]= eve->no[0]; - norm[1]= eve->no[1]; - norm[2]= eve->no[2]; - break; /* we know this is the only selected vert, so no need to keep looking */ - } - } - mul_mat3_m4_v3(obedit->obmat, norm); - view3d_align_axis_to_vector(v3d, rv3d, axis, norm); - } -} - -/* **************** VERTEX DEFORMS *************** */ -void vertexnoise(Object *obedit, EditMesh *em) -{ - Material *ma; - Tex *tex; - EditVert *eve; - float b2, ofs, vec[3]; - - if(em==NULL) return; - - ma= give_current_material(obedit, obedit->actcol); - if(ma==0 || ma->mtex[0]==0 || ma->mtex[0]->tex==0) { - return; - } - tex= ma->mtex[0]->tex; - - ofs= tex->turbul/200.0; - - eve= (struct EditVert *)em->verts.first; - while(eve) { - if(eve->f & SELECT) { - - if(tex->type==TEX_STUCCI) { - - b2= BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]); - if(tex->stype) ofs*=(b2*b2); - vec[0]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0]+ofs, eve->co[1], eve->co[2])); - vec[1]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1]+ofs, eve->co[2])); - vec[2]= 0.2*(b2-BLI_hnoise(tex->noisesize, eve->co[0], eve->co[1], eve->co[2]+ofs)); - - add_v3_v3v3(eve->co, eve->co, vec); - } - else { - float tin, dum; - externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum); - eve->co[2]+= 0.05*tin; - } - } - eve= eve->next; - } - - recalc_editnormals(em); -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - -} - -void flipface(EditMesh *em, EditFace *efa) -{ - if(efa->v4) { - SWAP(EditVert *, efa->v2, efa->v4); - SWAP(EditEdge *, efa->e1, efa->e4); - SWAP(EditEdge *, efa->e2, efa->e3); - EM_data_interp_from_faces(em, efa, NULL, efa, 0, 3, 2, 1); - } - else { - SWAP(EditVert *, efa->v2, efa->v3); - SWAP(EditEdge *, efa->e1, efa->e3); - efa->e2->dir= 1-efa->e2->dir; - EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 1, 3); - } - - if(efa->v4) normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co); - else normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co); -} diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c deleted file mode 100644 index 70e1ba0f54f..00000000000 --- a/source/blender/editors/mesh/editmesh_tools.c +++ /dev/null @@ -1,4552 +0,0 @@ - /* $Id: - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2004 by Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Johnny Matthews, Geoffrey Bantle. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/* - -editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise in mods.c - -*/ - -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include <float.h> - -#include "MEM_guardedalloc.h" -#include "PIL_time.h" - -#include "BLO_sys_types.h" // for intptr_t support - -#include "DNA_mesh_types.h" -#include "DNA_material_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_view3d_types.h" -#include "DNA_key_types.h" -#include "DNA_windowmanager_types.h" - -#include "RNA_types.h" -#include "RNA_define.h" -#include "RNA_access.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_editVert.h" -#include "BLI_rand.h" -#include "BLI_ghash.h" -#include "BLI_linklist.h" -#include "BLI_heap.h" - -#include "BKE_context.h" -#include "BKE_customdata.h" -#include "BKE_depsgraph.h" -#include "BKE_global.h" -#include "BKE_key.h" -#include "BKE_library.h" -#include "BKE_mesh.h" -#include "BKE_object.h" -#include "BKE_utildefines.h" -#include "BKE_bmesh.h" -#include "BKE_report.h" -#include "BKE_tessmesh.h" - - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "ED_mesh.h" -#include "ED_screen.h" -#include "ED_transform.h" -#include "ED_util.h" -#include "ED_view3d.h" - -#include "UI_interface.h" - -#include "mesh_intern.h" -#include "bmesh.h" - -/* XXX */ -static void waitcursor(int val) {} -static int pupmenu() {return 0;} -#define add_numbut(a, b, c, d, e, f, g) {} - -/* XXX */ - -/* local prototypes ---------------*/ -static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa); -int EdgeLoopDelete(EditMesh *em, wmOperator *op); - -/********* qsort routines *********/ - - -typedef struct xvertsort { - float x; - EditVert *v1; -} xvertsort; - -static int vergxco(const void *v1, const void *v2) -{ - const xvertsort *x1=v1, *x2=v2; - - if( x1->x > x2->x ) return 1; - else if( x1->x < x2->x) return -1; - return 0; -} - -struct facesort { - uintptr_t x; - struct EditFace *efa; -}; - - -static int vergface(const void *v1, const void *v2) -{ - const struct facesort *x1=v1, *x2=v2; - - if( x1->x > x2->x ) return 1; - else if( x1->x < x2->x) return -1; - return 0; -} - - -/* *********************************** */ - -void convert_to_triface(EditMesh *em, int direction) -{ - EditFace *efa, *efan, *next; - float fac; - - efa= em->faces.last; - while(efa) { - next= efa->prev; - if(efa->v4) { - if(efa->f & SELECT) { - /* choose shortest diagonal for split */ - fac= len_v3v3(efa->v1->co, efa->v3->co) - len_v3v3(efa->v2->co, efa->v4->co); - /* this makes sure exact squares get split different in both cases */ - if( (direction==0 && fac<FLT_EPSILON) || (direction && fac>0.0f) ) { - efan= EM_face_from_faces(em, efa, NULL, 0, 1, 2, -1); - if(efa->f & SELECT) EM_select_face(efan, 1); - efan= EM_face_from_faces(em, efa, NULL, 0, 2, 3, -1); - if(efa->f & SELECT) EM_select_face(efan, 1); - } - else { - efan= EM_face_from_faces(em, efa, NULL, 0, 1, 3, -1); - if(efa->f & SELECT) EM_select_face(efan, 1); - efan= EM_face_from_faces(em, efa, NULL, 1, 2, 3, -1); - if(efa->f & SELECT) EM_select_face(efan, 1); - } - - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - } - efa= next; - } - - EM_fgon_flags(em); // redo flags and indices for fgons - - -} - -int removedoublesflag(EditMesh *em, short flag, short automerge, float limit) /* return amount */ -{ - /* - flag - Test with vert->flags - automerge - Alternative operation, merge unselected into selected. - Used for "Auto Weld" mode. warning. - limit - Quick manhattan distance between verts. - */ - - /* all verts with (flag & 'flag') are being evaluated */ - EditVert *eve, *v1, *nextve; - EditEdge *eed, *e1, *nexted; - EditFace *efa, *nextvl; - xvertsort *sortblock, *sb, *sb1; - struct facesort *vlsortblock, *vsb, *vsb1; - int a, b, test, amount; - - - /* flag 128 is cleared, count */ - - /* Normal non weld operation */ - eve= em->verts.first; - amount= 0; - while(eve) { - eve->f &= ~128; - if(eve->h==0 && (automerge || (eve->f & flag))) amount++; - eve= eve->next; - } - if(amount==0) return 0; - - /* allocate memory and qsort */ - sb= sortblock= MEM_mallocN(sizeof(xvertsort)*amount,"sortremovedoub"); - eve= em->verts.first; - while(eve) { - if(eve->h==0 && (automerge || (eve->f & flag))) { - sb->x= eve->co[0]+eve->co[1]+eve->co[2]; - sb->v1= eve; - sb++; - } - eve= eve->next; - } - qsort(sortblock, amount, sizeof(xvertsort), vergxco); - - - /* test for doubles */ - sb= sortblock; - if (automerge) { - for(a=0; a<amount; a++, sb++) { - eve= sb->v1; - if( (eve->f & 128)==0 ) { - sb1= sb+1; - for(b=a+1; b<amount && (eve->f & 128)==0; b++, sb1++) { - if(sb1->x - sb->x > limit) break; - - /* when automarge, only allow unselected->selected */ - v1= sb1->v1; - if( (v1->f & 128)==0 ) { - if ((eve->f & flag)==0 && (v1->f & flag)==1) { - if( (float)fabs(v1->co[0]-eve->co[0])<=limit && - (float)fabs(v1->co[1]-eve->co[1])<=limit && - (float)fabs(v1->co[2]-eve->co[2])<=limit) - { /* unique bit */ - eve->f|= 128; - eve->tmp.v = v1; - } - } else if( (eve->f & flag)==1 && (v1->f & flag)==0 ) { - if( (float)fabs(v1->co[0]-eve->co[0])<=limit && - (float)fabs(v1->co[1]-eve->co[1])<=limit && - (float)fabs(v1->co[2]-eve->co[2])<=limit) - { /* unique bit */ - v1->f|= 128; - v1->tmp.v = eve; - } - } - } - } - } - } - } else { - for(a=0; a<amount; a++, sb++) { - eve= sb->v1; - if( (eve->f & 128)==0 ) { - sb1= sb+1; - for(b=a+1; b<amount; b++, sb1++) { - /* first test: simpel dist */ - if(sb1->x - sb->x > limit) break; - v1= sb1->v1; - - /* second test: is vertex allowed */ - if( (v1->f & 128)==0 ) { - if( (float)fabs(v1->co[0]-eve->co[0])<=limit && - (float)fabs(v1->co[1]-eve->co[1])<=limit && - (float)fabs(v1->co[2]-eve->co[2])<=limit) - { - v1->f|= 128; - v1->tmp.v = eve; - } - } - } - } - } - } - MEM_freeN(sortblock); - - if (!automerge) - for(eve = em->verts.first; eve; eve=eve->next) - if((eve->f & flag) && (eve->f & 128)) - EM_data_interp_from_verts(em, eve, eve->tmp.v, eve->tmp.v, 0.5f); - - /* test edges and insert again */ - eed= em->edges.first; - while(eed) { - eed->f2= 0; - eed= eed->next; - } - eed= em->edges.last; - while(eed) { - nexted= eed->prev; - - if(eed->f2==0) { - if( (eed->v1->f & 128) || (eed->v2->f & 128) ) { - remedge(em, eed); - - if(eed->v1->f & 128) eed->v1 = eed->v1->tmp.v; - if(eed->v2->f & 128) eed->v2 = eed->v2->tmp.v; - e1= addedgelist(em, eed->v1, eed->v2, eed); - - if(e1) { - e1->f2= 1; - if(eed->f & SELECT) - e1->f |= SELECT; - } - if(e1!=eed) free_editedge(em, eed); - } - } - eed= nexted; - } - - /* first count amount of test faces */ - efa= (struct EditFace *)em->faces.first; - amount= 0; - while(efa) { - efa->f1= 0; - if(efa->v1->f & 128) efa->f1= 1; - else if(efa->v2->f & 128) efa->f1= 1; - else if(efa->v3->f & 128) efa->f1= 1; - else if(efa->v4 && (efa->v4->f & 128)) efa->f1= 1; - - if(efa->f1==1) amount++; - efa= efa->next; - } - - /* test faces for double vertices, and if needed remove them */ - efa= (struct EditFace *)em->faces.first; - while(efa) { - nextvl= efa->next; - if(efa->f1==1) { - - if(efa->v1->f & 128) efa->v1= efa->v1->tmp.v; - if(efa->v2->f & 128) efa->v2= efa->v2->tmp.v; - if(efa->v3->f & 128) efa->v3= efa->v3->tmp.v; - if(efa->v4 && (efa->v4->f & 128)) efa->v4= efa->v4->tmp.v; - - test= 0; - if(efa->v1==efa->v2) test+=1; - if(efa->v2==efa->v3) test+=2; - if(efa->v3==efa->v1) test+=4; - if(efa->v4==efa->v1) test+=8; - if(efa->v3==efa->v4) test+=16; - if(efa->v2==efa->v4) test+=32; - - if(test) { - if(efa->v4) { - if(test==1 || test==2) { - efa->v2= efa->v3; - efa->v3= efa->v4; - efa->v4= 0; - - EM_data_interp_from_faces(em, efa, NULL, efa, 0, 2, 3, 3); - - test= 0; - } - else if(test==8 || test==16) { - efa->v4= 0; - test= 0; - } - else { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - amount--; - } - } - else { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - amount--; - } - } - - if(test==0) { - /* set edge pointers */ - efa->e1= findedgelist(em, efa->v1, efa->v2); - efa->e2= findedgelist(em, efa->v2, efa->v3); - if(efa->v4==0) { - efa->e3= findedgelist(em, efa->v3, efa->v1); - efa->e4= 0; - } - else { - efa->e3= findedgelist(em, efa->v3, efa->v4); - efa->e4= findedgelist(em, efa->v4, efa->v1); - } - } - } - efa= nextvl; - } - - /* double faces: sort block */ - /* count again, now all selected faces */ - amount= 0; - efa= em->faces.first; - while(efa) { - efa->f1= 0; - if(faceselectedOR(efa, 1)) { - efa->f1= 1; - amount++; - } - efa= efa->next; - } - - if(amount) { - /* double faces: sort block */ - vsb= vlsortblock= MEM_mallocN(sizeof(struct facesort)*amount, "sortremovedoub"); - efa= em->faces.first; - while(efa) { - if(efa->f1 & 1) { - if(efa->v4) vsb->x= (uintptr_t) MIN4( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3, (uintptr_t)efa->v4); - else vsb->x= (uintptr_t) MIN3( (uintptr_t)efa->v1, (uintptr_t)efa->v2, (uintptr_t)efa->v3); - - vsb->efa= efa; - vsb++; - } - efa= efa->next; - } - - qsort(vlsortblock, amount, sizeof(struct facesort), vergface); - - vsb= vlsortblock; - for(a=0; a<amount; a++) { - efa= vsb->efa; - if( (efa->f1 & 128)==0 ) { - vsb1= vsb+1; - - for(b=a+1; b<amount; b++) { - - /* first test: same pointer? */ - if(vsb->x != vsb1->x) break; - - /* second test: is test permitted? */ - efa= vsb1->efa; - if( (efa->f1 & 128)==0 ) { - if( compareface(efa, vsb->efa)) efa->f1 |= 128; - - } - vsb1++; - } - } - vsb++; - } - - MEM_freeN(vlsortblock); - - /* remove double faces */ - efa= (struct EditFace *)em->faces.first; - while(efa) { - nextvl= efa->next; - if(efa->f1 & 128) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - efa= nextvl; - } - } - - /* remove double vertices */ - a= 0; - eve= (struct EditVert *)em->verts.first; - while(eve) { - nextve= eve->next; - if(automerge || eve->f & flag) { - if(eve->f & 128) { - a++; - BLI_remlink(&em->verts, eve); - free_editvert(em, eve); - } - } - eve= nextve; - } - - return a; /* amount */ -} - -// XXX is this needed? -/* called from buttons */ -static void xsortvert_flag__doSetX(void *userData, EditVert *eve, int x, int y, int index) -{ - xvertsort *sortblock = userData; - - sortblock[index].x = x; -} - -/* all verts with (flag & 'flag') are sorted */ -void xsortvert_flag(bContext *C, int flag) -{ -#if 0 //BMESH_TODO - ViewContext vc; - EditVert *eve; - xvertsort *sortblock; - ListBase tbase; - int i, amount; - - em_setup_viewcontext(C, &vc); - - amount = BLI_countlist(&vc.em->verts); - sortblock = MEM_callocN(sizeof(xvertsort)*amount,"xsort"); - for (i=0,eve= vc.em->verts.first; eve; i++,eve=eve->next) - if(eve->f & flag) - sortblock[i].v1 = eve; - - mesh_foreachScreenVert(&vc, xsortvert_flag__doSetX, sortblock, 0); - qsort(sortblock, amount, sizeof(xvertsort), vergxco); - - /* make temporal listbase */ - tbase.first= tbase.last= 0; - for (i=0; i<amount; i++) { - eve = sortblock[i].v1; - - if (eve) { - BLI_remlink(&vc.em->verts, eve); - BLI_addtail(&tbase, eve); - } - } - - addlisttolist(&vc.em->verts, &tbase); - - MEM_freeN(sortblock); -#endif -} - -/* called from buttons */ -void hashvert_flag(EditMesh *em, int flag) -{ - /* switch vertex order using hash table */ - EditVert *eve; - struct xvertsort *sortblock, *sb, onth, *newsort; - ListBase tbase; - int amount, a, b; - - /* count */ - eve= em->verts.first; - amount= 0; - while(eve) { - if(eve->f & flag) amount++; - eve= eve->next; - } - if(amount==0) return; - - /* allocate memory */ - sb= sortblock= (struct xvertsort *)MEM_mallocN(sizeof(struct xvertsort)*amount,"sortremovedoub"); - eve= em->verts.first; - while(eve) { - if(eve->f & flag) { - sb->v1= eve; - sb++; - } - eve= eve->next; - } - - BLI_srand(1); - - sb= sortblock; - for(a=0; a<amount; a++, sb++) { - b= (int)(amount*BLI_drand()); - if(b>=0 && b<amount) { - newsort= sortblock+b; - onth= *sb; - *sb= *newsort; - *newsort= onth; - } - } - - /* make temporal listbase */ - tbase.first= tbase.last= 0; - sb= sortblock; - while(amount--) { - eve= sb->v1; - BLI_remlink(&em->verts, eve); - BLI_addtail(&tbase, eve); - sb++; - } - - addlisttolist(&em->verts, &tbase); - - MEM_freeN(sortblock); - -} - -/* generic extern called extruder */ -void extrude_mesh(Scene *scene, Object *obedit, EditMesh *em, wmOperator *op) -{ - float nor[3]= {0.0, 0.0, 0.0}; - short nr, transmode= 0; - - /* extrude depends on totvertsel etc */ - EM_stats_update(em); - - if(em->selectmode & SCE_SELECT_VERTEX) { - if(em->totvertsel==0) nr= 0; - else if(em->totvertsel==1) nr= 4; - else if(em->totedgesel==0) nr= 4; - else if(em->totfacesel==0) - nr= 3; // pupmenu("Extrude %t|Only Edges%x3|Only Vertices%x4"); - else if(em->totfacesel==1) - nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3|Only Vertices%x4"); - else - nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3|Only Vertices%x4"); - } - else if(em->selectmode & SCE_SELECT_EDGE) { - if (em->totedgesel==0) nr = 0; - - nr = 1; - /*else if (em->totedgesel==1) nr = 3; - else if(em->totfacesel==0) nr = 3; - else if(em->totfacesel==1) - nr= 1; // pupmenu("Extrude %t|Region %x1|Only Edges%x3"); - else - nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2|Only Edges%x3"); - */ - } - else { - if (em->totfacesel == 0) nr = 0; - else if (em->totfacesel == 1) nr = 1; - else - nr= 1; // pupmenu("Extrude %t|Region %x1||Individual Faces %x2"); - } - - if(nr<1) return; - - if(nr==1) transmode= extrudeflag(obedit, em, SELECT, nor, 0); - else if(nr==4) transmode= extrudeflag_verts_indiv(em, SELECT, nor); - else if(nr==3) transmode= extrudeflag_edges_indiv(em, SELECT, nor); - else transmode= extrudeflag_face_indiv(em, SELECT, nor); - - if(transmode==0) { - BKE_report(op->reports, RPT_ERROR, "Not a valid selection for extrude"); - } - else { - EM_fgon_flags(em); - - /* We need to force immediate calculation here because - * transform may use derived objects (which are now stale). - * - * This shouldn't be necessary, derived queries should be - * automatically building this data if invalid. Or something. - */ -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - object_handle_update(scene, obedit); - - /* individual faces? */ -// BIF_TransformSetUndo("Extrude"); - if(nr==2) { -// initTransform(TFM_SHRINKFATTEN, CTX_NO_PET|CTX_NO_MIRROR); -// Transform(); - } - else { -// initTransform(TFM_TRANSLATION, CTX_NO_PET|CTX_NO_MIRROR); - if(transmode=='n') { - mul_m4_v3(obedit->obmat, nor); - sub_v3_v3v3(nor, nor, obedit->obmat[3]); -// BIF_setSingleAxisConstraint(nor, "along normal"); - } -// Transform(); - } - } - -} - -#if 0 -//need to see if this really had new stuff I should merge over -// XXX should be a menu item -static int mesh_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - Scene *scene= CTX_data_scene(C); - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - extrude_mesh(scene, obedit, em, op); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -/* extrude without transform */ -static int mesh_extrude_exec(bContext *C, wmOperator *op) -{ - Scene *scene= CTX_data_scene(C); - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh(obedit->data); - - extrude_mesh(scene, obedit, em, op); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - - -void MESH_OT_extrude(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Extrude"; - ot->idname= "MESH_OT_extrude"; - - /* api callbacks */ - ot->invoke= mesh_extrude_invoke; - ot->exec= mesh_extrude_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* to give to transform */ - Properties_Proportional(ot); - Properties_Constraints(ot); - RNA_def_boolean(ot->srna, "mirror", 0, "Mirror Editing", ""); -} -#endif - -static int split_mesh(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - WM_cursor_wait(1); - - /* make duplicate first */ - adduplicateflag(em, SELECT); - /* old faces have flag 128 set, delete them */ - delfaceflag(em, 128); - recalc_editnormals(em); - - WM_cursor_wait(0); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_split(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Split"; - ot->idname= "MESH_OT_split"; - - /* api callbacks */ - ot->exec= split_mesh; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -#if 0 -//this also showed up in a merge, need to check if it -//needs changes ported over to new extrude code too -static int extrude_repeat_mesh(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - RegionView3D *rv3d = ED_view3d_context_rv3d(C); - - int steps = RNA_int_get(op->ptr,"steps"); - - float offs = RNA_float_get(op->ptr,"offset"); - - float dvec[3], tmat[3][3], bmat[3][3], nor[3]= {0.0, 0.0, 0.0}; - short a; - - /* dvec */ - dvec[0]= rv3d->persinv[2][0]; - dvec[1]= rv3d->persinv[2][1]; - dvec[2]= rv3d->persinv[2][2]; - normalize_v3(dvec); - dvec[0]*= offs; - dvec[1]*= offs; - dvec[2]*= offs; - - /* base correction */ - copy_m3_m4(bmat, obedit->obmat); - invert_m3_m3(tmat, bmat); - mul_m3_v3(tmat, dvec); - - for(a=0; a<steps; a++) { - extrudeflag(obedit, em, SELECT, nor, 0); - translateflag(em, SELECT, dvec); - } - - recalc_editnormals(em); - - EM_fgon_flags(em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_extrude_repeat(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Extrude Repeat Mesh"; - ot->idname= "MESH_OT_extrude_repeat"; - - /* api callbacks */ - ot->exec= extrude_repeat_mesh; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_float(ot->srna, "offset", 2.0f, 0.0f, 100.0f, "Offset", "", 0.0f, FLT_MAX); - RNA_def_int(ot->srna, "steps", 10, 0, 180, "Steps", "", 0, INT_MAX); -} -#endif -/* ************************** spin operator ******************** */ - - -static int spin_mesh(bContext *C, wmOperator *op, float *dvec, int steps, float degr, int dupli ) -{ - Object *obedit= CTX_data_edit_object(C); - ToolSettings *ts= CTX_data_tool_settings(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - EditVert *eve,*nextve; - float nor[3]= {0.0f, 0.0f, 0.0f}; - float si, n[3], q[4], cmat[3][3], imat[3][3], tmat[3][3]; - float cent[3], bmat[3][3]; - float phi; - short a, ok= 1; - - RNA_float_get_array(op->ptr, "center", cent); - - /* imat and center and size */ - copy_m3_m4(bmat, obedit->obmat); - invert_m3_m3(imat,bmat); - - cent[0]-= obedit->obmat[3][0]; - cent[1]-= obedit->obmat[3][1]; - cent[2]-= obedit->obmat[3][2]; - mul_m3_v3(imat, cent); - - phi= degr*M_PI/360.0; - phi/= steps; - if(ts->editbutflag & B_CLOCKWISE) phi= -phi; - - RNA_float_get_array(op->ptr, "axis", n); - normalize_v3(n); - - q[0]= (float)cos(phi); - si= (float)sin(phi); - q[1]= n[0]*si; - q[2]= n[1]*si; - q[3]= n[2]*si; - quat_to_mat3( cmat,q); - - mul_m3_m3m3(tmat,cmat,bmat); - mul_m3_m3m3(bmat,imat,tmat); - - if(dupli==0) - if(ts->editbutflag & B_KEEPORIG) - adduplicateflag(em, 1); - - for(a=0; a<steps; a++) { - if(dupli==0) ok= extrudeflag(obedit, em, SELECT, nor, 0); - else adduplicateflag(em, SELECT); - - if(ok==0) - break; - - rotateflag(em, SELECT, cent, bmat); - if(dvec) { - mul_m3_v3(bmat,dvec); - translateflag(em, SELECT, dvec); - } - } - - if(ok==0) { - /* no vertices or only loose ones selected, remove duplicates */ - eve= em->verts.first; - while(eve) { - nextve= eve->next; - if(eve->f & SELECT) { - BLI_remlink(&em->verts,eve); - free_editvert(em, eve); - } - eve= nextve; - } - } - else { - recalc_editnormals(em); - - EM_fgon_flags(em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - } - - BKE_mesh_end_editmesh(obedit->data, em); - return ok; -} - -static int spin_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - int ok; - - ok= spin_mesh(C, op, NULL, RNA_int_get(op->ptr,"steps"), RNA_float_get(op->ptr,"degrees"), RNA_boolean_get(op->ptr,"dupli")); - if(ok==0) { - BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected"); - return OPERATOR_CANCELLED; - } - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -/* get center and axis, in global coords */ -static int spin_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d= ED_view3d_context_rv3d(C); - - RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d)); - RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[2]); - - return spin_mesh_exec(C, op); -} - -void MESH_OT_spin(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Spin"; - ot->idname= "MESH_OT_spin"; - - /* api callbacks */ - ot->invoke= spin_mesh_invoke; - ot->exec= spin_mesh_exec; - ot->poll= EM_view3d_poll; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /* props */ - RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, INT_MAX); - RNA_def_boolean(ot->srna, "dupli", 0, "Dupli", "Make Duplicates"); - RNA_def_float(ot->srna, "degrees", 90.0f, -FLT_MAX, FLT_MAX, "Degrees", "Degrees", -360.0f, 360.0f); - - RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); - RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); - -} - -static int screw_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - EditVert *eve,*v1=0,*v2=0; - EditEdge *eed; - float dvec[3], nor[3]; - int steps, turns; - - turns= RNA_int_get(op->ptr, "turns"); - steps= RNA_int_get(op->ptr, "steps"); - - /* clear flags */ - for(eve= em->verts.first; eve; eve= eve->next) - eve->f1= 0; - - /* edges set flags in verts */ - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->v1->f & SELECT) { - if(eed->v2->f & SELECT) { - /* watch: f1 is a byte */ - if(eed->v1->f1<2) eed->v1->f1++; - if(eed->v2->f1<2) eed->v2->f1++; - } - } - } - /* find two vertices with eve->f1==1, more or less is wrong */ - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f1==1) { - if(v1==NULL) v1= eve; - else if(v2==NULL) v2= eve; - else { - v1= NULL; - break; - } - } - } - if(v1==NULL || v2==NULL) { - BKE_report(op->reports, RPT_ERROR, "You have to select a string of connected vertices too"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } - - /* calculate dvec */ - dvec[0]= ( v1->co[0]- v2->co[0] )/steps; - dvec[1]= ( v1->co[1]- v2->co[1] )/steps; - dvec[2]= ( v1->co[2]- v2->co[2] )/steps; - - VECCOPY(nor, obedit->obmat[2]); - - if(nor[0]*dvec[0]+nor[1]*dvec[1]+nor[2]*dvec[2]>0.000) { - dvec[0]= -dvec[0]; - dvec[1]= -dvec[1]; - dvec[2]= -dvec[2]; - } - - if(spin_mesh(C, op, dvec, turns*steps, 360.0f*turns, 0)) { - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; - } - else { - BKE_report(op->reports, RPT_ERROR, "No valid vertices are selected"); - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_CANCELLED; - } -} - -/* get center and axis, in global coords */ -static int screw_mesh_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d= ED_view3d_context_rv3d(C); - - RNA_float_set_array(op->ptr, "center", give_cursor(scene, v3d)); - RNA_float_set_array(op->ptr, "axis", rv3d->viewinv[1]); - - return screw_mesh_exec(C, op); -} - -void MESH_OT_screw(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Screw"; - ot->idname= "MESH_OT_screw"; - - /* api callbacks */ - ot->invoke= screw_mesh_invoke; - ot->exec= screw_mesh_exec; - ot->poll= EM_view3d_poll; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - - /*props */ - RNA_def_int(ot->srna, "steps", 9, 0, INT_MAX, "Steps", "Steps", 0, 256); - RNA_def_int(ot->srna, "turns", 1, 0, INT_MAX, "Turns", "Turns", 0, 256); - - RNA_def_float_vector(ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "Center in global view space", -FLT_MAX, FLT_MAX); - RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -FLT_MAX, FLT_MAX); -} - -static void erase_edges(EditMesh *em, ListBase *l) -{ - EditEdge *ed, *nexted; - - ed = (EditEdge *) l->first; - while(ed) { - nexted= ed->next; - if( (ed->v1->f & SELECT) || (ed->v2->f & SELECT) ) { - remedge(em, ed); - free_editedge(em, ed); - } - ed= nexted; - } -} - -static void erase_faces(EditMesh *em, ListBase *l) -{ - EditFace *f, *nextf; - - f = (EditFace *) l->first; - - while(f) { - nextf= f->next; - if( faceselectedOR(f, SELECT) ) { - BLI_remlink(l, f); - free_editface(em, f); - } - f = nextf; - } -} - -static void erase_vertices(EditMesh *em, ListBase *l) -{ - EditVert *v, *nextv; - - v = (EditVert *) l->first; - while(v) { - nextv= v->next; - if(v->f & 1) { - BLI_remlink(l, v); - free_editvert(em, v); - } - v = nextv; - } -} - -/*GB*/ -/*-------------------------------------------------------------------------------*/ -/*--------------------------- Edge Based Subdivide ------------------------------*/ - -#define EDGENEW 2 -#define FACENEW 2 -#define EDGEINNER 4 -#define EDGEOLD 8 - -/*used by faceloop cut to select only edges valid for edge slide*/ -#define DOUBLEOPFILL 16 - -/* calculates offset for co, based on fractal, sphere or smooth settings */ -static void alter_co(float *co, EditEdge *edge, float smooth, float fractal, int beauty, float perc) -{ - float vec1[3], fac; - - if(beauty & B_SMOOTH) { - /* we calculate an offset vector vec1[], to be added to *co */ - float len, fac, nor[3], nor1[3], nor2[3]; - - sub_v3_v3v3(nor, edge->v1->co, edge->v2->co); - len= 0.5f*normalize_v3(nor); - - VECCOPY(nor1, edge->v1->no); - VECCOPY(nor2, edge->v2->no); - - /* cosine angle */ - fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ; - - vec1[0]= fac*nor1[0]; - vec1[1]= fac*nor1[1]; - vec1[2]= fac*nor1[2]; - - /* cosine angle */ - fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ; - - vec1[0]+= fac*nor2[0]; - vec1[1]+= fac*nor2[1]; - vec1[2]+= fac*nor2[2]; - - /* falloff for multi subdivide */ - smooth *= sqrt(fabs(1.0f - 2.0f*fabs(0.5f-perc))); - - vec1[0]*= smooth*len; - vec1[1]*= smooth*len; - vec1[2]*= smooth*len; - - co[0] += vec1[0]; - co[1] += vec1[1]; - co[2] += vec1[2]; - } - /*else if(beauty & B_SPHERE) { // subdivide sphere - normalize_v3(co); - co[0]*= smooth; - co[1]*= smooth; - co[2]*= smooth; - } - - if(beauty & B_FRACTAL) { - fac= fractal*len_v3v3(edge->v1->co, edge->v2->co); - vec1[0]= fac*(float)(0.5-BLI_drand()); - vec1[1]= fac*(float)(0.5-BLI_drand()); - vec1[2]= fac*(float)(0.5-BLI_drand()); - add_v3_v3v3(co, co, vec1); - }*/ -} - -/* assumes in the edge is the correct interpolated vertices already */ -/* percent defines the interpolation, smooth, fractal and beauty are for special options */ -/* results in new vertex with correct coordinate, vertex normal and weight group info */ -static EditVert *subdivide_edge_addvert(EditMesh *em, EditEdge *edge, float smooth, float fractal, int beauty, float percent) -{ - EditVert *ev; - float co[3]; - - co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent + edge->v1->co[0]; - co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent + edge->v1->co[1]; - co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent + edge->v1->co[2]; - - /* offset for smooth or sphere or fractal */ - alter_co(co, edge, smooth, fractal, beauty, percent); - - /* clip if needed by mirror modifier */ - if (edge->v1->f2) { - if ( edge->v1->f2 & edge->v2->f2 & 1) { - co[0]= 0.0f; - } - if ( edge->v1->f2 & edge->v2->f2 & 2) { - co[1]= 0.0f; - } - if ( edge->v1->f2 & edge->v2->f2 & 4) { - co[2]= 0.0f; - } - } - - ev = addvertlist(em, co, NULL); - - /* vert data (vgroups, ..) */ - EM_data_interp_from_verts(em, edge->v1, edge->v2, ev, percent); - - /* normal */ - ev->no[0] = (edge->v2->no[0]-edge->v1->no[0])*percent + edge->v1->no[0]; - ev->no[1] = (edge->v2->no[1]-edge->v1->no[1])*percent + edge->v1->no[1]; - ev->no[2] = (edge->v2->no[2]-edge->v1->no[2])*percent + edge->v1->no[2]; - normalize_v3(ev->no); - - return ev; -} - -static void flipvertarray(EditVert** arr, short size) -{ - EditVert *hold; - int i; - - for(i=0; i<size/2; i++) { - hold = arr[i]; - arr[i] = arr[size-i-1]; - arr[size-i-1] = hold; - } -} - -static void facecopy(EditMesh *em, EditFace *source, EditFace *target) -{ - float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co; - float *v4 = source->v4? source->v4->co: NULL; - float w[4][4]; - - CustomData_em_copy_data(&em->fdata, &em->fdata, source->data, &target->data); - - target->mat_nr = source->mat_nr; - target->flag = source->flag; - target->h = source->h; - - interp_weights_face_v3( w[0],v1, v2, v3, v4, target->v1->co); - interp_weights_face_v3( w[1],v1, v2, v3, v4, target->v2->co); - interp_weights_face_v3( w[2],v1, v2, v3, v4, target->v3->co); - if (target->v4) - interp_weights_face_v3( w[3],v1, v2, v3, v4, target->v4->co); - - CustomData_em_interp(&em->fdata, &source->data, NULL, (float*)w, 1, target->data); -} - -static void fill_quad_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype) -{ - EditEdge *cedge=NULL; - EditVert *v[4], **verts; - EditFace *hold; - short start=0, end, left, right, vertsize,i; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - v[3] = efa->v4; - - if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;} - else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;} - else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;} - else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;} - - // Point verts to the array of new verts for cedge - verts = BLI_ghash_lookup(gh, cedge); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);} - end = (start+1)%4; - left = (start+2)%4; - right = (start+3)%4; - - /* - We should have something like this now - - end start - 3 2 1 0 - |---*---*---| - | | - | | - | | - ------------- - left right - - where start,end,left, right are indexes of EditFace->v1, etc (stored in v) - and 0,1,2... are the indexes of the new verts stored in verts - - We will fill this case like this or this depending on even or odd cuts - - |---*---*---| |---*---| - | / \ | | / \ | - | / \ | | / \ | - |/ \| |/ \| - ------------- --------- - */ - - // Make center face - if(vertsize % 2 == 0) { - hold = addfacelist(em, verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL); - hold->e2->f2 |= EDGEINNER; - hold->e4->f2 |= EDGEINNER; - }else{ - hold = addfacelist(em, verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL); - hold->e1->f2 |= EDGEINNER; - hold->e3->f2 |= EDGEINNER; - } - facecopy(em, efa,hold); - - // Make side faces - for(i=0;i<(vertsize-1)/2;i++) { - hold = addfacelist(em, verts[i],verts[i+1],v[right],NULL,NULL,NULL); - facecopy(em, efa,hold); - if(i+1 != (vertsize-1)/2) { - if(seltype == SUBDIV_SELECT_INNER) { - hold->e2->f2 |= EDGEINNER; - } - } - hold = addfacelist(em, verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL); - facecopy(em, efa,hold); - if(i+1 != (vertsize-1)/2) { - if(seltype == SUBDIV_SELECT_INNER) { - hold->e3->f2 |= EDGEINNER; - } - } - } -} - -static void fill_tri_single(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, int seltype) -{ - EditEdge *cedge=NULL; - EditVert *v[3], **verts; - EditFace *hold; - short start=0, end, op, vertsize,i; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - - if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;} - else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;} - else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;} - - // Point verts to the array of new verts for cedge - verts = BLI_ghash_lookup(gh, cedge); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0] != v[start]) {flipvertarray(verts,numcuts+2);} - end = (start+1)%3; - op = (start+2)%3; - - /* - We should have something like this now - - end start - 3 2 1 0 - |---*---*---| - \ | - \ | - \ | - \ | - \ | - \ | - |op - - where start,end,op are indexes of EditFace->v1, etc (stored in v) - and 0,1,2... are the indexes of the new verts stored in verts - - We will fill this case like this or this depending on even or odd cuts - - 3 2 1 0 - |---*---*---| - \ \ \ | - \ \ \ | - \ \ \ | - \ \ \| - \ \\| - \ | - |op - */ - - // Make side faces - for(i=0;i<(vertsize-1);i++) { - hold = addfacelist(em, verts[i],verts[i+1],v[op],NULL,NULL,NULL); - if(i+1 != vertsize-1) { - if(seltype == SUBDIV_SELECT_INNER) { - hold->e2->f2 |= EDGEINNER; - } - } - facecopy(em, efa,hold); - } -} - -static void fill_quad_double_op(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) -{ - EditEdge *cedge[2]={NULL, NULL}; - EditVert *v[4], **verts[2]; - EditFace *hold; - short start=0, end, left, right, vertsize,i; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - v[3] = efa->v4; - - if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;} - else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;} - - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, cedge[0]); - verts[1] = BLI_ghash_lookup(gh, cedge[1]); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} - end = (start+1)%4; - left = (start+2)%4; - right = (start+3)%4; - if(verts[1][0] != v[left]) {flipvertarray(verts[1],numcuts+2);} - /* - We should have something like this now - - end start - 3 2 1 0 - |---*---*---| - | | - | | - | | - |---*---*---| - 0 1 2 3 - left right - - We will fill this case like this or this depending on even or odd cuts - - |---*---*---| - | | | | - | | | | - | | | | - |---*---*---| - */ - - // Make side faces - for(i=0;i<vertsize-1;i++) { - hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL); - if(i < vertsize-2) { - hold->e2->f2 |= EDGEINNER; - hold->e2->f2 |= DOUBLEOPFILL; - } - facecopy(em, efa,hold); - } -} - -static void fill_quad_double_adj_path(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) -{ - EditEdge *cedge[2]={NULL, NULL}; - EditVert *v[4], **verts[2]; - EditFace *hold; - short start=0, start2=0, vertsize,i; - int ctrl= 0; // XXX - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - v[3] = efa->v4; - - if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;} - if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;} - if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;} - if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;} - - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, cedge[0]); - verts[1] = BLI_ghash_lookup(gh, cedge[1]); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} - if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);} - /* - We should have something like this now - - end start - 3 2 1 0 - start2 0|---*---*---| - | | - 1* | - | | - 2* | - | | - end2 3|-----------| - - We will fill this case like this or this depending on even or odd cuts - |---*---*---| - | / / / | - * / / | - | / / | - * / | - | / | - |-----------| - */ - - // Make outside tris - hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL); - /* when ctrl is depressed, only want verts on the cutline selected */ - if (ctrl) - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa,hold); - hold = addfacelist(em, verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL); - /* when ctrl is depressed, only want verts on the cutline selected */ - if (ctrl) - hold->e1->f2 |= EDGEINNER; - facecopy(em, efa,hold); - //if(scene->toolsettings->editbutflag & B_AUTOFGON) { - // hold->e1->h |= EM_FGON; - //} - // Make side faces - - for(i=0;i<numcuts;i++) { - hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - } - //EM_fgon_flags(em); - -} - -static void fill_quad_double_adj_fan(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) -{ - EditEdge *cedge[2]={NULL, NULL}; - EditVert *v[4], *op=NULL, **verts[2]; - EditFace *hold; - short start=0, start2=0, vertsize,i; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - v[3] = efa->v4; - - if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;} - if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;} - if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;} - if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;} - - - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, cedge[0]); - verts[1] = BLI_ghash_lookup(gh, cedge[1]); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} - if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);} - /* - We should have something like this now - - end start - 3 2 1 0 - start2 0|---*---*---| - | | - 1* | - | | - 2* | - | | - end2 3|-----------|op - - We will fill this case like this or this (warning horrible ascii art follows) - |---*---*---| - | \ \ \ | - *---\ \ \ | - | \ \ \ \| - *---- \ \ \ | - | --- \\\| - |-----------| - */ - - for(i=0;i<=numcuts;i++) { - hold = addfacelist(em, op,verts[1][numcuts-i],verts[1][numcuts-i+1],NULL,NULL,NULL); - hold->e1->f2 |= EDGEINNER; - facecopy(em, efa,hold); - - hold = addfacelist(em, op,verts[0][i],verts[0][i+1],NULL,NULL,NULL); - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa,hold); - } -} - -static void fill_quad_double_adj_inner(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) -{ - EditEdge *cedge[2]={NULL, NULL}; - EditVert *v[4], *op=NULL, **verts[2],**inner; - EditFace *hold; - short start=0, start2=0, vertsize,i; - float co[3]; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - v[3] = efa->v4; - - if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1; op = efa->v4;} - if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2; op = efa->v1;} - if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3; op = efa->v2;} - if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0; op = efa->v3;} - - - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, cedge[0]); - verts[1] = BLI_ghash_lookup(gh, cedge[1]); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} - if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);} - /* - We should have something like this now - - end start - 3 2 1 0 - start2 0|---*---*---| - | | - 1* | - | | - 2* | - | | - end2 3|-----------|op - - We will fill this case like this or this (warning horrible ascii art follows) - |---*-----*---| - | * / | - * \ / | - | * | - | / \ | - * \ | - | \ | - |-------------| - */ - - // Add Inner Vert(s) - inner = MEM_mallocN(sizeof(EditVert*)*numcuts,"New inner verts"); - - for(i=0;i<numcuts;i++) { - co[0] = (verts[0][numcuts-i]->co[0] + verts[1][i+1]->co[0] ) / 2 ; - co[1] = (verts[0][numcuts-i]->co[1] + verts[1][i+1]->co[1] ) / 2 ; - co[2] = (verts[0][numcuts-i]->co[2] + verts[1][i+1]->co[2] ) / 2 ; - inner[i] = addvertlist(em, co, NULL); - inner[i]->f2 |= EDGEINNER; - - EM_data_interp_from_verts(em, verts[0][numcuts-i], verts[1][i+1], inner[i], 0.5f); - } - - // Add Corner Quad - hold = addfacelist(em, verts[0][numcuts+1],verts[1][1],inner[0],verts[0][numcuts],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa,hold); - // Add Bottom Quads - hold = addfacelist(em, verts[0][0],verts[0][1],inner[numcuts-1],op,NULL,NULL); - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - - hold = addfacelist(em, op,inner[numcuts-1],verts[1][numcuts],verts[1][numcuts+1],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - - //if(scene->toolsettings->editbutflag & B_AUTOFGON) { - // hold->e1->h |= EM_FGON; - //} - // Add Fill Quads (if # cuts > 1) - - for(i=0;i<numcuts-1;i++) { - hold = addfacelist(em, inner[i],verts[1][i+1],verts[1][i+2],inner[i+1],NULL,NULL); - hold->e1->f2 |= EDGEINNER; - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa,hold); - - hold = addfacelist(em, inner[i],inner[i+1],verts[0][numcuts-1-i],verts[0][numcuts-i],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - hold->e4->f2 |= EDGEINNER; - facecopy(em, efa,hold); - - //if(scene->toolsettings->editbutflag & B_AUTOFGON) { - // hold->e1->h |= EM_FGON; - //} - } - - //EM_fgon_flags(em); - - MEM_freeN(inner); -} - -static void fill_tri_double(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) -{ - EditEdge *cedge[2]={NULL, NULL}; - EditVert *v[3], **verts[2]; - EditFace *hold; - short start=0, start2=0, vertsize,i; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - - if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;} - if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;} - if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;} - - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, cedge[0]); - verts[1] = BLI_ghash_lookup(gh, cedge[1]); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} - if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);} - /* - We should have something like this now - - end start - 3 2 1 0 - start2 0|---*---*---| - | / - 1* / - | / - 2* / - | / - end2 3| - - We will fill this case like this or this depending on even or odd cuts - |---*---*---| - | / / / - * / / - | / / - * / - | / - | - */ - - // Make outside tri - hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL); - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa,hold); - // Make side faces - - for(i=0;i<numcuts;i++) { - hold = addfacelist(em, verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - } -} - -static void fill_quad_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts) -{ - EditEdge *cedge[3]={0}; - EditVert *v[4], **verts[3]; - EditFace *hold; - short start=0, start2=0, start3=0, vertsize, i, repeats; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - v[3] = efa->v4; - - if(!(efa->e1->f & SELECT)) { - cedge[0] = efa->e2; - cedge[1] = efa->e3; - cedge[2] = efa->e4; - start = 1;start2 = 2;start3 = 3; - } - if(!(efa->e2->f & SELECT)) { - cedge[0] = efa->e3; - cedge[1] = efa->e4; - cedge[2] = efa->e1; - start = 2;start2 = 3;start3 = 0; - } - if(!(efa->e3->f & SELECT)) { - cedge[0] = efa->e4; - cedge[1] = efa->e1; - cedge[2] = efa->e2; - start = 3;start2 = 0;start3 = 1; - } - if(!(efa->e4->f & SELECT)) { - cedge[0] = efa->e1; - cedge[1] = efa->e2; - cedge[2] = efa->e3; - start = 0;start2 = 1;start3 = 2; - } - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, cedge[0]); - verts[1] = BLI_ghash_lookup(gh, cedge[1]); - verts[2] = BLI_ghash_lookup(gh, cedge[2]); - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);} - if(verts[1][0] != v[start2]) {flipvertarray(verts[1],numcuts+2);} - if(verts[2][0] != v[start3]) {flipvertarray(verts[2],numcuts+2);} - /* - We should have something like this now - - start2 - 3 2 1 0 - start3 0|---*---*---|3 - | | - 1* *2 - | | - 2* *1 - | | - 3|-----------|0 start - - We will fill this case like this or this depending on even or odd cuts - there are a couple of differences. For odd cuts, there is a tri in the - middle as well as 1 quad at the bottom (not including the extra quads - for odd cuts > 1 - - For even cuts, there is a quad in the middle and 2 quads on the bottom - - they are numbered here for clarity - - 1 outer tris and bottom quads - 2 inner tri or quad - 3 repeating quads - - |---*---*---*---| - |1/ / \ \ 1| - |/ 3 / \ 3 \| - * / 2 \ * - | / \ | - |/ \ | - *---------------* - | 3 | - | | - *---------------* - | | - | 1 | - | | - |---------------| - - |---*---*---*---*---| - | 1/ / \ \ 1| - | / / \ \ | - |/ 3 / \ 3 \| - * / \ * - | / \ | - | / 2 \ | - |/ \| - *-------------------* - | | - | 3 | - | | - *-------------------* - | | - | 1 | - | | - *-------------------* - | | - | 1 | - | | - |-------------------| - - */ - - // Make outside tris - hold = addfacelist(em, verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL); - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa,hold); - hold = addfacelist(em, verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL); - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa,hold); - // Make bottom quad - hold = addfacelist(em, verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - //If it is even cuts, add the 2nd lower quad - if(numcuts % 2 == 0) { - hold = addfacelist(em, verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - // Also Make inner quad - hold = addfacelist(em, verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL); - hold->e3->f2 |= EDGEINNER; - //if(scene->toolsettings->editbutflag & B_AUTOFGON) { - // hold->e3->h |= EM_FGON; - //} - facecopy(em, efa,hold); - repeats = (numcuts / 2) -1; - } else { - // Make inner tri - hold = addfacelist(em, verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL); - hold->e2->f2 |= EDGEINNER; - //if(scene->toolsettings->editbutflag & B_AUTOFGON) { - // hold->e2->h |= EM_FGON; - //} - facecopy(em, efa,hold); - repeats = ((numcuts+1) / 2)-1; - } - - // cuts for 1 and 2 do not have the repeating quads - if(numcuts < 3) {repeats = 0;} - for(i=0;i<repeats;i++) { - //Make side repeating Quads - hold = addfacelist(em, verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL); - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - hold = addfacelist(em, verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL); - hold->e4->f2 |= EDGEINNER; - facecopy(em, efa,hold); - } - // Do repeating bottom quads - for(i=0;i<repeats;i++) { - if(numcuts % 2 == 1) { - hold = addfacelist(em, verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL); - } else { - hold = addfacelist(em, verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL); - } - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa,hold); - } - //EM_fgon_flags(em); -} - -static void fill_quad_quadruple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float smooth, float fractal, int beauty) -{ - EditVert **verts[4], ***innerverts; - EditFace *hold; - EditEdge temp; - short vertsize, i, j; - - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, efa->e1); - verts[1] = BLI_ghash_lookup(gh, efa->e2); - verts[2] = BLI_ghash_lookup(gh, efa->e3); - verts[3] = BLI_ghash_lookup(gh, efa->e4); - - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);} - if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);} - if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);} - if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);} - /* - We should have something like this now - 1 - - 3 2 1 0 - 0|---*---*---|0 - | | - 1* *1 - 2 | | 4 - 2* *2 - | | - 3|---*---*---|3 - 3 2 1 0 - - 3 - // we will fill a 2 dim array of editvert*s to make filling easier - // the innervert order is shown - - 0 0---1---2---3 - | | | | - 1 0---1---2---3 - | | | | - 2 0---1---2---3 - | | | | - 3 0---1---2---3 - - */ - innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array"); - for(i=0;i<numcuts+2;i++) { - innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array"); - } - - // first row is e1 last row is e3 - for(i=0;i<numcuts+2;i++) { - innerverts[0][i] = verts[0][(numcuts+1)-i]; - innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i]; - } - - for(i=1;i<=numcuts;i++) { - /* we create a fake edge for the next loop */ - temp.v2 = innerverts[i][0] = verts[1][i]; - temp.v1 = innerverts[i][numcuts+1] = verts[3][i]; - - for(j=1;j<=numcuts;j++) { - float percent= (float)j/(float)(numcuts+1); - - innerverts[i][(numcuts+1)-j]= subdivide_edge_addvert(em, &temp, smooth, fractal, beauty, percent); - } - } - // Fill with faces - for(i=0;i<numcuts+1;i++) { - for(j=0;j<numcuts+1;j++) { - hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL); - hold->e1->f2 = EDGENEW; - hold->e2->f2 = EDGENEW; - hold->e3->f2 = EDGENEW; - hold->e4->f2 = EDGENEW; - - if(i != 0) { hold->e1->f2 |= EDGEINNER; } - if(j != 0) { hold->e2->f2 |= EDGEINNER; } - if(i != numcuts) { hold->e3->f2 |= EDGEINNER; } - if(j != numcuts) { hold->e4->f2 |= EDGEINNER; } - - facecopy(em, efa,hold); - } - } - // Clean up our dynamic multi-dim array - for(i=0;i<numcuts+2;i++) { - MEM_freeN(innerverts[i]); - } - MEM_freeN(innerverts); -} - -static void fill_tri_triple(EditMesh *em, EditFace *efa, struct GHash *gh, int numcuts, float smooth, float fractal, int beauty) -{ - EditVert **verts[3], ***innerverts; - short vertsize, i, j; - EditFace *hold; - EditEdge temp; - - // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1] - verts[0] = BLI_ghash_lookup(gh, efa->e1); - verts[1] = BLI_ghash_lookup(gh, efa->e2); - verts[2] = BLI_ghash_lookup(gh, efa->e3); - - //This is the index size of the verts array - vertsize = numcuts+2; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);} - if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);} - if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);} - /* - We should have something like this now - 3 - - 3 2 1 0 - 0|---*---*---|3 - | / - 1 1* *2 - | / - 2* *1 2 - | / - 3|/ - 0 - - we will fill a 2 dim array of editvert*s to make filling easier - - 3 - - 0 0---1---2---3---4 - | / | / |/ | / - 1 0---1----2---3 - 1 | / | / | / - 2 0----1---2 2 - | / | / - |/ |/ - 3 0---1 - | / - |/ - 4 0 - - */ - - innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array"); - for(i=0;i<numcuts+2;i++) { - innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array"); - } - //top row is e3 backwards - for(i=0;i<numcuts+2;i++) { - innerverts[0][i] = verts[2][(numcuts+1)-i]; - } - - for(i=1;i<=numcuts+1;i++) { - //fake edge, first vert is from e1, last is from e2 - temp.v1= innerverts[i][0] = verts[0][i]; - temp.v2= innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i]; - - for(j=1;j<(numcuts+1)-i;j++) { - float percent= (float)j/(float)((numcuts+1)-i); - - innerverts[i][((numcuts+1)-i)-j]= subdivide_edge_addvert(em, &temp, smooth, fractal, beauty, 1-percent); - } - } - - // Now fill the verts with happy little tris :) - for(i=0;i<=numcuts+1;i++) { - for(j=0;j<(numcuts+1)-i;j++) { - //We always do the first tri - hold = addfacelist(em, innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - if(i != 0) { hold->e1->f2 |= EDGEINNER; } - if(j != 0) { hold->e2->f2 |= EDGEINNER; } - if(j+1 != (numcuts+1)-i) {hold->e3->f2 |= EDGEINNER;} - - facecopy(em, efa,hold); - //if there are more to come, we do the 2nd - if(j+1 <= numcuts-i) { - hold = addfacelist(em, innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL); - facecopy(em, efa,hold); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - } - } - } - - // Clean up our dynamic multi-dim array - for(i=0;i<numcuts+2;i++) { - MEM_freeN(innerverts[i]); - } - MEM_freeN(innerverts); -} - -//Next two fill types are for exact only and are provided to allow for knifing through vertices -//This means there is no multicut! -static void fill_quad_doublevert(EditMesh *em, EditFace *efa, int v1, int v2) -{ - EditFace *hold; - /* - Depending on which two vertices have been knifed through (v1 and v2), we - triangulate like the patterns below. - X-------| |-------X - | \ | | / | - | \ | | / | - | \ | | / | - --------X X-------- - */ - - if(v1 == 1 && v2 == 3){ - hold= addfacelist(em, efa->v1, efa->v2, efa->v3, 0, efa, NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa, hold); - - hold= addfacelist(em, efa->v1, efa->v3, efa->v4, 0, efa, NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e1->f2 |= EDGEINNER; - facecopy(em, efa, hold); - } - else{ - hold= addfacelist(em, efa->v1, efa->v2, efa->v4, 0, efa, NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e2->f2 |= EDGEINNER; - facecopy(em, efa, hold); - - hold= addfacelist(em, efa->v2, efa->v3, efa->v4, 0, efa, NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa, hold); - } -} - -static void fill_quad_singlevert(EditMesh *em, EditFace *efa, struct GHash *gh) -{ - EditEdge *cedge=NULL; - EditVert *v[4], **verts; - EditFace *hold; - short start=0, end, left, right, vertsize; - - v[0] = efa->v1; - v[1] = efa->v2; - v[2] = efa->v3; - v[3] = efa->v4; - - if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;} - else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;} - else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;} - else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;} - - // Point verts to the array of new verts for cedge - verts = BLI_ghash_lookup(gh, cedge); - //This is the index size of the verts array - vertsize = 3; - - // Is the original v1 the same as the first vert on the selected edge? - // if not, the edge is running the opposite direction in this face so flip - // the array to the correct direction - - if(verts[0] != v[start]) {flipvertarray(verts,3);} - end = (start+1)%4; - left = (start+2)%4; - right = (start+3)%4; - -/* - We should have something like this now - - end start - 2 1 0 - |-----*-----| - | | - | | - | | - ------------- - left right - - where start,end,left, right are indexes of EditFace->v1, etc (stored in v) - and 0,1,2 are the indexes of the new verts stored in verts. We fill like - this, depending on whether its vertex 'left' or vertex 'right' thats - been knifed through... - - |---*---| |---*---| - | / | | \ | - | / | | \ | - |/ | | \| - X-------- --------X -*/ - - if(v[left]->f1){ - //triangle is composed of cutvert, end and left - hold = addfacelist(em, verts[1],v[end],v[left],NULL, NULL,NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e3->f2 |= EDGEINNER; - facecopy(em, efa, hold); - - //quad is composed of cutvert, left, right and start - hold = addfacelist(em, verts[1],v[left],v[right],v[start], NULL, NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e4->f2 |= EDGENEW; - hold->e1->f2 |= EDGEINNER; - facecopy(em, efa, hold); - } - else if(v[right]->f1){ - //triangle is composed of cutvert, right and start - hold = addfacelist(em, verts[1],v[right],v[start], NULL, NULL, NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e1->f2 |= EDGEINNER; - facecopy(em, efa, hold); - //quad is composed of cutvert, end, left, right - hold = addfacelist(em, verts[1],v[end], v[left], v[right], NULL, NULL); - hold->e1->f2 |= EDGENEW; - hold->e2->f2 |= EDGENEW; - hold->e3->f2 |= EDGENEW; - hold->e4->f2 |= EDGENEW; - hold->e4->f2 |= EDGEINNER; - facecopy(em, efa, hold); - } - -} - -// This function takes an example edge, the current point to create and -// the total # of points to create, then creates the point and return the -// editvert pointer to it. -static EditVert *subdivideedgenum(EditMesh *em, EditEdge *edge, int curpoint, int totpoint, float smooth, float fractal, int beauty) -{ - EditVert *ev; - float percent; - - if (beauty & (B_PERCENTSUBD) && totpoint == 1) - //percent=(float)(edge->tmp.l)/32768.0f; - percent= edge->tmp.fp; - else - percent= (float)curpoint/(float)(totpoint+1); - - ev= subdivide_edge_addvert(em, edge, smooth, fractal, beauty, percent); - ev->f = edge->v1->f; - - return ev; -} - -void esubdivideflag(Object *obedit, EditMesh *em, int flag, float smooth, float fractal, int beauty, int numcuts, int seltype) -{ - EditFace *ef; - EditEdge *eed, *cedge, *sort[4]; - EditVert *eve, **templist; - struct GHash *gh; - float length[4], v1mat[3], v2mat[3], v3mat[3], v4mat[3]; - int i, j, edgecount, touchcount, facetype,hold; - ModifierData *md= obedit->modifiers.first; - int ctrl= 0; // XXX - - //Set faces f1 to 0 cause we need it later - for(ef=em->faces.first;ef;ef = ef->next) ef->f1 = 0; - for(eve=em->verts.first; eve; eve=eve->next) { - if(!(beauty & B_KNIFE)) /* knife sets this flag for vertex cuts */ - eve->f1 = 0; - eve->f2 = 0; - } - - for (; md; md=md->next) { - if (md->type==eModifierType_Mirror) { - MirrorModifierData *mmd = (MirrorModifierData*) md; - - if(mmd->flag & MOD_MIR_CLIPPING) { - for (eve= em->verts.first; eve; eve= eve->next) { - eve->f2= 0; - switch(mmd->axis){ - case 0: - if (fabs(eve->co[0]) < mmd->tolerance) - eve->f2 |= 1; - break; - case 1: - if (fabs(eve->co[1]) < mmd->tolerance) - eve->f2 |= 2; - break; - case 2: - if (fabs(eve->co[2]) < mmd->tolerance) - eve->f2 |= 4; - break; - } - } - } - } - } - - //Flush vertex flags upward to the edges - for(eed = em->edges.first;eed;eed = eed->next) { - //if(eed->f & flag && eed->v1->f == eed->v2->f) { - // eed->f |= eed->v1->f; - // } - eed->f2 = 0; - if(eed->f & flag) { - eed->f2 |= EDGEOLD; - } - } - - // We store an array of verts for each edge that is subdivided, - // we put this array as a value in a ghash which is keyed by the EditEdge* - - // Now for beauty subdivide deselect edges based on length - if(beauty & B_BEAUTY) { - for(ef = em->faces.first;ef;ef = ef->next) { - if(!ef->v4) { - continue; - } - if(ef->f & SELECT) { - VECCOPY(v1mat, ef->v1->co); - VECCOPY(v2mat, ef->v2->co); - VECCOPY(v3mat, ef->v3->co); - VECCOPY(v4mat, ef->v4->co); - mul_mat3_m4_v3(obedit->obmat, v1mat); - mul_mat3_m4_v3(obedit->obmat, v2mat); - mul_mat3_m4_v3(obedit->obmat, v3mat); - mul_mat3_m4_v3(obedit->obmat, v4mat); - - length[0] = len_v3v3(v1mat, v2mat); - length[1] = len_v3v3(v2mat, v3mat); - length[2] = len_v3v3(v3mat, v4mat); - length[3] = len_v3v3(v4mat, v1mat); - sort[0] = ef->e1; - sort[1] = ef->e2; - sort[2] = ef->e3; - sort[3] = ef->e4; - - - // Beauty Short Edges - if(beauty & B_BEAUTY_SHORT) { - for(j=0;j<2;j++) { - hold = -1; - for(i=0;i<4;i++) { - if(length[i] < 0) { - continue; - } else if(hold == -1) { - hold = i; - } else { - if(length[hold] < length[i]) { - hold = i; - } - } - } - if (hold > -1) { - sort[hold]->f &= ~SELECT; - sort[hold]->f2 |= EDGENEW; - length[hold] = -1; - } - } - } - - // Beauty Long Edges - else { - for(j=0;j<2;j++) { - hold = -1; - for(i=0;i<4;i++) { - if(length[i] < 0) { - continue; - } else if(hold == -1) { - hold = i; - } else { - if(length[hold] > length[i]) { - hold = i; - } - } - } - if (hold > -1) { - sort[hold]->f &= ~SELECT; - sort[hold]->f2 |= EDGENEW; - length[hold] = -1; - } - } - } - } - } - } - - gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - - // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut - if(beauty & B_KNIFE) { - for(eed= em->edges.first;eed;eed=eed->next) { - if( eed->tmp.fp == 0 ) { - EM_select_edge(eed,0); - } - } - } - // So for each edge, if it is selected, we allocate an array of size cuts+2 - // so we can have a place for the v1, the new verts and v2 - for(eed=em->edges.first;eed;eed = eed->next) { - if(eed->f & flag) { - templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist"); - templist[0] = eed->v1; - for(i=0;i<numcuts;i++) { - // This function creates the new vert and returns it back - // to the array - templist[i+1] = subdivideedgenum(em, eed, i+1, numcuts, smooth, fractal, beauty); - //while we are here, we can copy edge info from the original edge - cedge = addedgelist(em, templist[i],templist[i+1],eed); - // Also set the edge f2 to EDGENEW so that we can use this info later - cedge->f2 = EDGENEW; - } - templist[i+1] = eed->v2; - //Do the last edge too - cedge = addedgelist(em, templist[i],templist[i+1],eed); - cedge->f2 = EDGENEW; - // Now that the edge is subdivided, we can put its verts in the ghash - BLI_ghash_insert(gh, eed, templist); - } - } - -// DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - // Now for each face in the mesh we need to figure out How many edges were cut - // and which filling method to use for that face - for(ef = em->faces.first;ef;ef = ef->next) { - edgecount = 0; - facetype = 3; - if(ef->e1->f & flag) {edgecount++;} - if(ef->e2->f & flag) {edgecount++;} - if(ef->e3->f & flag) {edgecount++;} - if(ef->v4) { - facetype = 4; - if(ef->e4->f & flag) {edgecount++;} - } - if(facetype == 4) { - switch(edgecount) { - case 0: - if(beauty & B_KNIFE && numcuts == 1){ - /*Test for when knifing through two opposite verts but no edges*/ - touchcount = 0; - if(ef->v1->f1) touchcount++; - if(ef->v2->f1) touchcount++; - if(ef->v3->f1) touchcount++; - if(ef->v4->f1) touchcount++; - if(touchcount == 2){ - if(ef->v1->f1 && ef->v3->f1){ - ef->f1 = SELECT; - fill_quad_doublevert(em, ef, 1, 3); - } - else if(ef->v2->f1 && ef->v4->f1){ - ef->f1 = SELECT; - fill_quad_doublevert(em, ef, 2, 4); - } - } - } - break; - - case 1: - if(beauty & B_KNIFE && numcuts == 1){ - /*Test for when knifing through an edge and one vert*/ - touchcount = 0; - if(ef->v1->f1) touchcount++; - if(ef->v2->f1) touchcount++; - if(ef->v3->f1) touchcount++; - if(ef->v4->f1) touchcount++; - - if(touchcount == 1){ - if( (ef->e1->f & flag && ( !ef->e1->v1->f1 && !ef->e1->v2->f1 )) || - (ef->e2->f & flag && ( !ef->e2->v1->f1 && !ef->e2->v2->f1 )) || - (ef->e3->f & flag && ( !ef->e3->v1->f1 && !ef->e3->v2->f1 )) || - (ef->e4->f & flag && ( !ef->e4->v1->f1 && !ef->e4->v2->f1 )) ){ - - ef->f1 = SELECT; - fill_quad_singlevert(em, ef, gh); - } - else{ - ef->f1 = SELECT; - fill_quad_single(em, ef, gh, numcuts, seltype); - } - } - else{ - ef->f1 = SELECT; - fill_quad_single(em, ef, gh, numcuts, seltype); - } - } - else{ - ef->f1 = SELECT; - fill_quad_single(em, ef, gh, numcuts, seltype); - } - break; - case 2: ef->f1 = SELECT; - // if there are 2, we check if edge 1 and 3 are either both on or off that way - // we can tell if the selected pair is Adjacent or Opposite of each other - if((ef->e1->f & flag && ef->e3->f & flag) || - (ef->e2->f & flag && ef->e4->f & flag)) { - fill_quad_double_op(em, ef, gh, numcuts); - }else{ - switch(0) { // XXX scene->toolsettings->cornertype) { - case 0: fill_quad_double_adj_path(em, ef, gh, numcuts); break; - case 1: fill_quad_double_adj_inner(em, ef, gh, numcuts); break; - case 2: fill_quad_double_adj_fan(em, ef, gh, numcuts); break; - } - - } - break; - case 3: ef->f1 = SELECT; - fill_quad_triple(em, ef, gh, numcuts); - break; - case 4: ef->f1 = SELECT; - fill_quad_quadruple(em, ef, gh, numcuts, smooth, fractal, beauty); - break; - } - } else { - switch(edgecount) { - case 0: break; - case 1: ef->f1 = SELECT; - fill_tri_single(em, ef, gh, numcuts, seltype); - break; - case 2: ef->f1 = SELECT; - fill_tri_double(em, ef, gh, numcuts); - break; - case 3: ef->f1 = SELECT; - fill_tri_triple(em, ef, gh, numcuts, smooth, fractal, beauty); - break; - } - } - } - - // Delete Old Edges and Faces - for(eed = em->edges.first;eed;eed = eed->next) { - if(BLI_ghash_haskey(gh,eed)) { - eed->f1 = SELECT; - } else { - eed->f1 = 0; - } - } - free_tagged_edges_faces(em, em->edges.first, em->faces.first); - - if(seltype == SUBDIV_SELECT_ORIG && !ctrl) { - /* bugfix: vertex could get flagged as "not-selected" - // solution: clear flags before, not at the same time as setting SELECT flag -dg - */ - for(eed = em->edges.first;eed;eed = eed->next) { - if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) { - eed->f &= !flag; - EM_select_edge(eed,0); - } - } - for(eed = em->edges.first;eed;eed = eed->next) { - if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { - eed->f |= flag; - EM_select_edge(eed,1); - } - } - } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| ctrl) { - for(eed = em->edges.first;eed;eed = eed->next) { - if(eed->f2 & EDGEINNER) { - eed->f |= flag; - EM_select_edge(eed,1); - if(eed->v1->f & EDGEINNER) eed->v1->f |= SELECT; - if(eed->v2->f & EDGEINNER) eed->v2->f |= SELECT; - }else{ - eed->f &= !flag; - EM_select_edge(eed,0); - } - } - } else if(seltype == SUBDIV_SELECT_LOOPCUT){ - for(eed = em->edges.first;eed;eed = eed->next) { - if(eed->f2 & DOUBLEOPFILL){ - eed->f |= flag; - EM_select_edge(eed,1); - }else{ - eed->f &= !flag; - EM_select_edge(eed,0); - } - } - } - if(em->selectmode & SCE_SELECT_VERTEX) { - for(eed = em->edges.first;eed;eed = eed->next) { - if(eed->f & SELECT) { - eed->v1->f |= SELECT; - eed->v2->f |= SELECT; - } - } - } - - //fix hide flags for edges. First pass, hide edges of hidden faces - for(ef=em->faces.first; ef; ef=ef->next){ - if(ef->h){ - ef->e1->h |= 1; - ef->e2->h |= 1; - ef->e3->h |= 1; - if(ef->e4) ef->e4->h |= 1; - } - } - //second pass: unhide edges of visible faces adjacent to hidden faces - for(ef=em->faces.first; ef; ef=ef->next){ - if(ef->h == 0){ - ef->e1->h &= ~1; - ef->e2->h &= ~1; - ef->e3->h &= ~1; - if(ef->e4) ef->e4->h &= ~1; - } - } - - // Free the ghash and call MEM_freeN on all the value entries to return - // that memory - BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN); - - EM_selectmode_flush(em); - for(ef=em->faces.first;ef;ef = ef->next) { - if(ef->e4) { - if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && - (ef->e3->f & SELECT && ef->e4->f & SELECT) ) { - ef->f |= SELECT; - } - } else { - if( (ef->e1->f & SELECT && ef->e2->f & SELECT) && ef->e3->f & SELECT) { - ef->f |= SELECT; - } - } - } - - recalc_editnormals(em); -} - -static int count_selected_edges(EditEdge *ed) -{ - int totedge = 0; - while(ed) { - ed->tmp.p = 0; - if( ed->f & SELECT ) totedge++; - ed= ed->next; - } - return totedge; -} - -/* hurms, as if this makes code readable! It's pointerpointer hiding... (ton) */ -typedef EditFace *EVPtr; -typedef EVPtr EVPTuple[2]; - -/** builds EVPTuple array efaa of face tuples (in fact pointers to EditFaces) - sharing one edge. - arguments: selected edge list, face list. - Edges will also be tagged accordingly (see eed->f2) */ - -static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa) -{ - EditEdge *e1, *e2, *e3; - EVPtr *evp; - int i = 0; - - /* run through edges, if selected, set pointer edge-> facearray */ - while(eed) { - eed->f2= 0; - eed->f1= 0; - if( eed->f & SELECT ) { - eed->tmp.p = (EditVert *) (&efaa[i]); - i++; - } - else eed->tmp.p = NULL; - - eed= eed->next; - } - - - /* find edges pointing to 2 faces by procedure: - - - run through faces and their edges, increase - face counter e->f1 for each face - */ - - while(efa) { - efa->f1= 0; - if(efa->v4==0 && (efa->f & SELECT)) { /* if selected triangle */ - e1= efa->e1; - e2= efa->e2; - e3= efa->e3; - if(e1->f2<3 && e1->tmp.p) { - if(e1->f2<2) { - evp= (EVPtr *) e1->tmp.p; - evp[(int)e1->f2] = efa; - } - e1->f2+= 1; - } - if(e2->f2<3 && e2->tmp.p) { - if(e2->f2<2) { - evp= (EVPtr *) e2->tmp.p; - evp[(int)e2->f2]= efa; - } - e2->f2+= 1; - } - if(e3->f2<3 && e3->tmp.p) { - if(e3->f2<2) { - evp= (EVPtr *) e3->tmp.p; - evp[(int)e3->f2]= efa; - } - e3->f2+= 1; - } - } - else { - /* set to 3 to make sure these are not flipped or joined */ - efa->e1->f2= 3; - efa->e2->f2= 3; - efa->e3->f2= 3; - if (efa->e4) efa->e4->f2= 3; - } - - efa= efa->next; - } - return i; -} - - -/* returns vertices of two adjacent triangles forming a quad - - can be righthand or lefthand - - 4-----3 - |\ | - | \ 2 | <- efa1 - | \ | - efa-> | 1 \ | - | \| - 1-----2 - -*/ -#define VTEST(face, num, other) \ - (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3) - -static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex) -{ - if VTEST(efa, 1, efa1) { - *v1= efa->v1; - *v2= efa->v2; - vindex[0]= 0; - vindex[1]= 1; - } - else if VTEST(efa, 2, efa1) { - *v1= efa->v2; - *v2= efa->v3; - vindex[0]= 1; - vindex[1]= 2; - } - else if VTEST(efa, 3, efa1) { - *v1= efa->v3; - *v2= efa->v1; - vindex[0]= 2; - vindex[1]= 0; - } - - if VTEST(efa1, 1, efa) { - *v3= efa1->v1; - *v4= efa1->v2; - vindex[2]= 0; - vindex[3]= 1; - } - else if VTEST(efa1, 2, efa) { - *v3= efa1->v2; - *v4= efa1->v3; - vindex[2]= 1; - vindex[3]= 2; - } - else if VTEST(efa1, 3, efa) { - *v3= efa1->v3; - *v4= efa1->v1; - vindex[2]= 2; - vindex[3]= 0; - } - else - *v3= *v4= NULL; -} - -/* Helper functions for edge/quad edit features*/ -static void untag_edges(EditFace *f) -{ - f->e1->f1 = 0; - f->e2->f1 = 0; - f->e3->f1 = 0; - if (f->e4) f->e4->f1 = 0; -} - -/** remove and free list of tagged edges and faces */ -static void free_tagged_edges_faces(EditMesh *em, EditEdge *eed, EditFace *efa) -{ - EditEdge *nexted; - EditFace *nextvl; - - while(efa) { - nextvl= efa->next; - if(efa->f1) { - BLI_remlink(&em->faces, efa); - free_editface(em, efa); - } - else - /* avoid deleting edges that are still in use */ - untag_edges(efa); - efa= nextvl; - } - - while(eed) { - nexted= eed->next; - if(eed->f1) { - remedge(em, eed); - free_editedge(em, eed); - } - eed= nexted; - } -} - - -/* ******************** BEGIN TRIANGLE TO QUAD ************************************* */ -static float measure_facepair(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, float limit) -{ - - /*gives a 'weight' to a pair of triangles that join an edge to decide how good a join they would make*/ - /*Note: this is more complicated than it needs to be and should be cleaned up...*/ - float measure = 0.0, noA1[3], noA2[3], noB1[3], noB2[3], normalADiff, normalBDiff, - edgeVec1[3], edgeVec2[3], edgeVec3[3], edgeVec4[3], diff, - minarea, maxarea, areaA, areaB; - - /*First Test: Normal difference*/ - normal_tri_v3( noA1,v1->co, v2->co, v3->co); - normal_tri_v3( noA2,v1->co, v3->co, v4->co); - - if(noA1[0] == noA2[0] && noA1[1] == noA2[1] && noA1[2] == noA2[2]) normalADiff = 0.0; - else normalADiff = angle_v2v2(noA1, noA2); - //if(!normalADiff) normalADiff = 179; - normal_tri_v3( noB1,v2->co, v3->co, v4->co); - normal_tri_v3( noB2,v4->co, v1->co, v2->co); - - if(noB1[0] == noB2[0] && noB1[1] == noB2[1] && noB1[2] == noB2[2]) normalBDiff = 0.0; - else normalBDiff = angle_v2v2(noB1, noB2); - //if(!normalBDiff) normalBDiff = 179; - - measure += (normalADiff/360) + (normalBDiff/360); - if(measure > limit) return measure; - - /*Second test: Colinearity*/ - sub_v3_v3v3(edgeVec1, v1->co, v2->co); - sub_v3_v3v3(edgeVec2, v2->co, v3->co); - sub_v3_v3v3(edgeVec3, v3->co, v4->co); - sub_v3_v3v3(edgeVec4, v4->co, v1->co); - - diff = 0.0; - - diff = ( - fabs(angle_v2v2(edgeVec1, edgeVec2) - 90) + - fabs(angle_v2v2(edgeVec2, edgeVec3) - 90) + - fabs(angle_v2v2(edgeVec3, edgeVec4) - 90) + - fabs(angle_v2v2(edgeVec4, edgeVec1) - 90)) / 360; - if(!diff) return 0.0; - - measure += diff; - if(measure > limit) return measure; - - /*Third test: Concavity*/ - areaA = area_tri_v3(v1->co, v2->co, v3->co) + area_tri_v3(v1->co, v3->co, v4->co); - areaB = area_tri_v3(v2->co, v3->co, v4->co) + area_tri_v3(v4->co, v1->co, v2->co); - - if(areaA <= areaB) minarea = areaA; - else minarea = areaB; - - if(areaA >= areaB) maxarea = areaA; - else maxarea = areaB; - - if(!maxarea) measure += 1; - else measure += (1 - (minarea / maxarea)); - - return measure; -} - -#define T2QUV_LIMIT 0.005 -#define T2QCOL_LIMIT 3 -static int compareFaceAttribs(EditMesh *em, EditFace *f1, EditFace *f2, EditEdge *eed) -{ - /*Test to see if the per-face attributes for the joining edge match within limit*/ - MTFace *tf1, *tf2; - unsigned int *col1, *col2; - short i,attrok=0, flag = 0, /* XXX scene->toolsettings->editbutflag,*/ fe1[2], fe2[2]; - - tf1 = CustomData_em_get(&em->fdata, f1->data, CD_MTFACE); - tf2 = CustomData_em_get(&em->fdata, f2->data, CD_MTFACE); - - col1 = CustomData_em_get(&em->fdata, f1->data, CD_MCOL); - col2 = CustomData_em_get(&em->fdata, f2->data, CD_MCOL); - - /*store indices for faceedges*/ - f1->v1->f1 = 0; - f1->v2->f1 = 1; - f1->v3->f1 = 2; - - fe1[0] = eed->v1->f1; - fe1[1] = eed->v2->f1; - - f2->v1->f1 = 0; - f2->v2->f1 = 1; - f2->v3->f1 = 2; - - fe2[0] = eed->v1->f1; - fe2[1] = eed->v2->f1; - - /*compare faceedges for each face attribute. Additional per face attributes can be added later*/ - /*do UVs*/ - if(flag & B_JOINTRIA_UV){ - - if(tf1 == NULL || tf2 == NULL) attrok |= B_JOINTRIA_UV; - else if(tf1->tpage != tf2->tpage); /*do nothing*/ - else{ - for(i = 0; i < 2; i++){ - if(tf1->uv[fe1[i]][0] + T2QUV_LIMIT > tf2->uv[fe2[i]][0] && tf1->uv[fe1[i]][0] - T2QUV_LIMIT < tf2->uv[fe2[i]][0] && - tf1->uv[fe1[i]][1] + T2QUV_LIMIT > tf2->uv[fe2[i]][1] && tf1->uv[fe1[i]][1] - T2QUV_LIMIT < tf2->uv[fe2[i]][1]) attrok |= B_JOINTRIA_UV; - } - } - } - - /*do VCOLs*/ - if(flag & B_JOINTRIA_VCOL){ - if(!col1 || !col2) attrok |= B_JOINTRIA_VCOL; - else{ - char *f1vcol, *f2vcol; - for(i = 0; i < 2; i++){ - f1vcol = (char *)&(col1[fe1[i]]); - f2vcol = (char *)&(col2[fe2[i]]); - - /*compare f1vcol with f2vcol*/ - if( f1vcol[1] + T2QCOL_LIMIT > f2vcol[1] && f1vcol[1] - T2QCOL_LIMIT < f2vcol[1] && - f1vcol[2] + T2QCOL_LIMIT > f2vcol[2] && f1vcol[2] - T2QCOL_LIMIT < f2vcol[2] && - f1vcol[3] + T2QCOL_LIMIT > f2vcol[3] && f1vcol[3] - T2QCOL_LIMIT < f2vcol[3]) attrok |= B_JOINTRIA_VCOL; - } - } - } - - if( ((attrok & B_JOINTRIA_UV) == (flag & B_JOINTRIA_UV)) && ((attrok & B_JOINTRIA_VCOL) == (flag & B_JOINTRIA_VCOL)) ) return 1; - return 0; -} - -static int fplcmp(const void *v1, const void *v2) -{ - const EditEdge *e1= *((EditEdge**)v1), *e2=*((EditEdge**)v2); - - if( e1->crease > e2->crease) return 1; - else if( e1->crease < e2->crease) return -1; - - return 0; -} - -/*Bitflags for edges.*/ -#define T2QDELETE 1 -#define T2QCOMPLEX 2 -#define T2QJOIN 4 -void join_triangles(EditMesh *em) -{ - EditVert *v1, *v2, *v3, *v4, *eve; - EditEdge *eed, **edsortblock = NULL, **edb = NULL; - EditFace *efa; - EVPTuple *efaar = NULL; - EVPtr *efaa = NULL; - float *creases = NULL; - float measure; /*Used to set tolerance*/ - float limit = 0.8f; // XXX scene->toolsettings->jointrilimit; - int i, ok, totedge=0, totseledge=0, complexedges, vindex[4]; - - /*if we take a long time on very dense meshes we want waitcursor to display*/ - waitcursor(1); - - totseledge = count_selected_edges(em->edges.first); - if(totseledge==0) return; - - /*abusing crease value to store weights for edge pairs. Nasty*/ - for(eed=em->edges.first; eed; eed=eed->next) totedge++; - if(totedge) creases = MEM_callocN(sizeof(float) * totedge, "Join Triangles Crease Array"); - for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++){ - creases[i] = eed->crease; - eed->crease = 0.0; - } - - /*clear temp flags*/ - for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = eve->f2 = 0; - for(eed=em->edges.first; eed; eed=eed->next) eed->f2 = eed->f1 = 0; - for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = efa->tmp.l = 0; - - /*For every selected 2 manifold edge, create pointers to its two faces.*/ - efaar= (EVPTuple *) MEM_callocN(totseledge * sizeof(EVPTuple), "Tri2Quad"); - ok = collect_quadedges(efaar, em->edges.first, em->faces.first); - complexedges = 0; - - if(ok){ - - - /*clear tmp.l flag and store number of faces that are selected and coincident to current face here.*/ - for(eed=em->edges.first; eed; eed=eed->next){ - /* eed->f2 is 2 only if this edge is part of exactly two - triangles, and both are selected, and it has EVPTuple assigned */ - if(eed->f2 == 2){ - efaa= (EVPtr *) eed->tmp.p; - efaa[0]->tmp.l++; - efaa[1]->tmp.l++; - } - } - - for(eed=em->edges.first; eed; eed=eed->next){ - if(eed->f2 == 2){ - efaa= (EVPtr *) eed->tmp.p; - v1 = v2 = v3 = v4 = NULL; - givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); - if(v1 && v2 && v3 && v4){ - /*test if simple island first. This mimics 2.42 behaviour and the tests are less restrictive.*/ - if(efaa[0]->tmp.l == 1 && efaa[1]->tmp.l == 1){ - eed->f1 |= T2QJOIN; - efaa[0]->f1 = 1; //mark for join - efaa[1]->f1 = 1; //mark for join - } - else{ - - /* The face pair is part of a 'complex' island, so the rules for dealing with it are more involved. - Depending on what options the user has chosen, this face pair can be 'thrown out' based upon the following criteria: - - 1: the two faces do not share the same material - 2: the edge joining the two faces is marked as sharp. - 3: the two faces UV's do not make a good match - 4: the two faces Vertex colors do not make a good match - - If the face pair passes all the applicable tests, it is then given a 'weight' with the measure_facepair() function. - This measures things like concavity, colinearity ect. If this weight is below the threshold set by the user - the edge joining them is marked as being 'complex' and will be compared against other possible pairs which contain one of the - same faces in the current pair later. - - This technique is based upon an algorithm that Campbell Barton developed for his Tri2Quad script that was previously part of - the python scripts bundled with Blender releases. - */ - -// XXX if(scene->toolsettings->editbutflag & B_JOINTRIA_SHARP && eed->sharp); /*do nothing*/ -// else if(scene->toolsettings->editbutflag & B_JOINTRIA_MAT && efaa[0]->mat_nr != efaa[1]->mat_nr); /*do nothing*/ -// else if(((scene->toolsettings->editbutflag & B_JOINTRIA_UV) || (scene->toolsettings->editbutflag & B_JOINTRIA_VCOL)) && - compareFaceAttribs(em, efaa[0], efaa[1], eed); // XXX == 0); /*do nothing*/ -// else{ - measure = measure_facepair(v1, v2, v3, v4, limit); - if(measure < limit){ - complexedges++; - eed->f1 |= T2QCOMPLEX; - eed->crease = measure; /*we dont mark edges for join yet*/ - } -// } - } - } - } - } - - /*Quicksort the complex edges according to their weighting*/ - if(complexedges){ - edsortblock = edb = MEM_callocN(sizeof(EditEdge*) * complexedges, "Face Pairs quicksort Array"); - for(eed = em->edges.first; eed; eed=eed->next){ - if(eed->f1 & T2QCOMPLEX){ - *edb = eed; - edb++; - } - } - qsort(edsortblock, complexedges, sizeof(EditEdge*), fplcmp); - /*now go through and mark the edges who get the highest weighting*/ - for(edb=edsortblock, i=0; i < complexedges; edb++, i++){ - efaa = (EVPtr *)((*edb)->tmp.p); /*suspect!*/ - if( !efaa[0]->f1 && !efaa[1]->f1){ - efaa[0]->f1 = 1; //mark for join - efaa[1]->f1 = 1; //mark for join - (*edb)->f1 |= T2QJOIN; - } - } - } - - /*finally go through all edges marked for join (simple and complex) and create new faces*/ - for(eed=em->edges.first; eed; eed=eed->next){ - if(eed->f1 & T2QJOIN){ - efaa= (EVPtr *)eed->tmp.p; - v1 = v2 = v3 = v4 = NULL; - givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); - if((v1 && v2 && v3 && v4) && (exist_face(em, v1, v2, v3, v4)==0)){ /*exist_face is very slow! Needs to be adressed.*/ - /*flag for delete*/ - eed->f1 |= T2QDELETE; - /*create new quad and select*/ - efa = EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], vindex[1], 4+vindex[2], 4+vindex[3]); - EM_select_face(efa,1); - } - else{ - efaa[0]->f1 = 0; - efaa[1]->f1 = 0; - } - } - } - } - - /*free data and cleanup*/ - if(creases){ - for(eed=em->edges.first, i = 0; eed; eed=eed->next, i++) eed->crease = creases[i]; - MEM_freeN(creases); - } - for(eed=em->edges.first; eed; eed=eed->next){ - if(eed->f1 & T2QDELETE) eed->f1 = 1; - else eed->f1 = 0; - } - free_tagged_edges_faces(em, em->edges.first, em->faces.first); - if(efaar) MEM_freeN(efaar); - if(edsortblock) MEM_freeN(edsortblock); - - EM_selectmode_flush(em); - -} -/* ******************** END TRIANGLE TO QUAD ************************************* */ - -#define FACE_MARKCLEAR(f) (f->f1 = 1) - -/* quick hack, basically a copy of beauty_fill */ -void edge_flip(EditMesh *em) -{ - EditVert *v1, *v2, *v3, *v4; - EditEdge *eed, *nexted; - EditFace *efa, *w; - //void **efaar, **efaa; - EVPTuple *efaar; - EVPtr *efaa; - int totedge, ok, vindex[4]; - - /* - all selected edges with two faces - * - find the faces: store them in edges (using datablock) - * - per edge: - test convex - * - test edge: flip? - - if true: remedge, addedge, all edges at the edge get new face pointers - */ - - EM_selectmode_flush(em); // makes sure in selectmode 'face' the edges of selected faces are selected too - - totedge = count_selected_edges(em->edges.first); - if(totedge==0) return; - - /* temporary array for : edge -> face[1], face[2] */ - efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "edgeflip"); - - ok = collect_quadedges(efaar, em->edges.first, em->faces.first); - - eed= em->edges.first; - while(eed) { - nexted= eed->next; - - if(eed->f2==2) { /* points to 2 faces */ - - efaa= (EVPtr *) eed->tmp.p; - - /* don't do it if flagged */ - - ok= 1; - efa= efaa[0]; - if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; - efa= efaa[1]; - if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; - - if(ok) { - /* test convex */ - givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); - -/* - 4-----3 4-----3 - |\ | | /| - | \ 1 | | 1 / | - | \ | -> | / | - | 0 \ | | / 0 | - | \| |/ | - 1-----2 1-----2 -*/ - /* make new faces */ - if (v1 && v2 && v3) { - if( convex(v1->co, v2->co, v3->co, v4->co) ) { - if(exist_face(em, v1, v2, v3, v4)==0) { - /* outch this may break seams */ - w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], - vindex[1], 4+vindex[2], -1); - - EM_select_face(w, 1); - - /* outch this may break seams */ - w= EM_face_from_faces(em, efaa[0], efaa[1], vindex[0], - 4+vindex[2], 4+vindex[3], -1); - - EM_select_face(w, 1); - } - /* tag as to-be-removed */ - FACE_MARKCLEAR(efaa[1]); - FACE_MARKCLEAR(efaa[0]); - eed->f1 = 1; - - } /* endif test convex */ - } - } - } - eed= nexted; - } - - /* clear tagged edges and faces: */ - free_tagged_edges_faces(em, em->edges.first, em->faces.first); - - MEM_freeN(efaar); -} - - -#define AXIS_X 1 -#define AXIS_Y 2 - -static const EnumPropertyItem axis_items[]= { - {AXIS_X, "X", 0, "X", ""}, - {AXIS_Y, "Y", 0, "Y", ""}, - {0, NULL, 0, NULL, NULL}, -}; - -/******************* BEVEL CODE STARTS HERE ********************/ - - /* XXX old bevel not ported yet */ - -void bevel_menu(EditMesh *em) -{ - BME_Mesh *bm; - BME_TransData_Head *td; -// TransInfo *t; - int options, res, gbm_free = 0; - -// t = BIF_GetTransInfo(); - if (!G.editBMesh) { - G.editBMesh = MEM_callocN(sizeof(*(G.editBMesh)),"bevel_menu() G.editBMesh"); - gbm_free = 1; - } - - G.editBMesh->options = BME_BEVEL_RUNNING | BME_BEVEL_SELECT; - G.editBMesh->res = 1; - - while(G.editBMesh->options & BME_BEVEL_RUNNING) { - options = G.editBMesh->options; - res = G.editBMesh->res; - bm = BME_editmesh_to_bmesh(em); -// BIF_undo_push("Pre-Bevel"); - free_editMesh(em); - BME_bevel(bm,0.1f,res,options,0,0,&td); - BME_bmesh_to_editmesh(bm, td, em); - EM_selectmode_flush(em); - G.editBMesh->bm = bm; - G.editBMesh->td = td; -// initTransform(TFM_BEVEL,CTX_BMESH); -// Transform(); - BME_free_transdata(td); - BME_free_mesh(bm); -// if (t->state != TRANS_CONFIRM) { -// BIF_undo(); -// } - if (options == G.editBMesh->options) { - G.editBMesh->options &= ~BME_BEVEL_RUNNING; - } - } - - if (gbm_free) { - MEM_freeN(G.editBMesh); - G.editBMesh = NULL; - } -} - - -/* *********** END BEVEL *********/ - -/* this utility function checks to see if 2 edit edges share a face, -returns 1 if they do -returns 0 if they do not, or if the function is passed the same edge 2 times -*/ -short sharesFace(EditMesh *em, EditEdge* e1, EditEdge* e2) -{ - EditFace *search=NULL; - - search = em->faces.first; - if (e1 == e2){ - return 0 ; - } - while(search){ - if( - ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) && - ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2)) - ) { - return 1; - } - search = search->next; - } - return 0; -} - -/* -------------------- More tools ------------------ */ -#if 0 -void mesh_set_face_flags(EditMesh *em, short mode) -{ - EditFace *efa; - MTFace *tface; - short m_tex=0, m_shared=0, - m_light=0, m_invis=0, m_collision=0, - m_twoside=0, m_obcolor=0, m_halo=0, - m_billboard=0, m_shadow=0, m_text=0, - m_sort=0; - short flag = 0, change = 0; - -// XXX if (!EM_texFaceCheck()) { -// error("not a mesh with uv/image layers"); -// return; -// } - - add_numbut(0, TOG|SHO, "Texture", 0, 0, &m_tex, NULL); - add_numbut(2, TOG|SHO, "Light", 0, 0, &m_light, NULL); - add_numbut(3, TOG|SHO, "Invisible", 0, 0, &m_invis, NULL); - add_numbut(4, TOG|SHO, "Collision", 0, 0, &m_collision, NULL); - add_numbut(5, TOG|SHO, "Shared", 0, 0, &m_shared, NULL); - add_numbut(6, TOG|SHO, "Twoside", 0, 0, &m_twoside, NULL); - add_numbut(7, TOG|SHO, "ObColor", 0, 0, &m_obcolor, NULL); - add_numbut(8, TOG|SHO, "Halo", 0, 0, &m_halo, NULL); - add_numbut(9, TOG|SHO, "Billboard", 0, 0, &m_billboard, NULL); - add_numbut(10, TOG|SHO, "Shadow", 0, 0, &m_shadow, NULL); - add_numbut(11, TOG|SHO, "Text", 0, 0, &m_text, NULL); - add_numbut(12, TOG|SHO, "Sort", 0, 0, &m_sort, NULL); - - if (!do_clever_numbuts((mode ? "Set Flags" : "Clear Flags"), 13, REDRAW)) - return; - - /* these 2 cant both be on */ - if (mode) /* are we seeting*/ - if (m_halo) - m_billboard = 0; - - if (m_tex) flag |= TF_TEX; - if (m_shared) flag |= TF_SHAREDCOL; - if (m_light) flag |= TF_LIGHT; - if (m_invis) flag |= TF_INVISIBLE; - if (m_collision) flag |= TF_DYNAMIC; - if (m_twoside) flag |= TF_TWOSIDE; - if (m_obcolor) flag |= TF_OBCOL; - if (m_halo) flag |= TF_BILLBOARD; - if (m_billboard) flag |= TF_BILLBOARD2; - if (m_shadow) flag |= TF_SHADOW; - if (m_text) flag |= TF_BMFONT; - if (m_sort) flag |= TF_ALPHASORT; - - if (flag==0) - return; - - efa= em->faces.first; - while(efa) { - if(efa->f & SELECT) { - tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (mode) tface->mode |= flag; - else tface->mode &= ~flag; - change = 1; - } - efa= efa->next; - } - -} -#endif - -/************************ Merge Operator *************************/ - -/* Collection Routines|Currently used by the improved merge code*/ -/* buildEdge_collection() creates a list of lists*/ -/* these lists are filled with edges that are topologically connected.*/ -/* This whole tool needs to be redone, its rather poorly implemented...*/ - -typedef struct Collection{ - struct Collection *next, *prev; - int index; - ListBase collectionbase; -} Collection; - -typedef struct CollectedEdge{ - struct CollectedEdge *next, *prev; - EditEdge *eed; -} CollectedEdge; - -#define MERGELIMIT 0.000001 - -static void build_edgecollection(EditMesh *em, ListBase *allcollections) -{ - EditEdge *eed; - Collection *edgecollection, *newcollection; - CollectedEdge *newedge; - - int currtag = 1; - short ebalanced = 0; - short collectionfound = 0; - - for (eed=em->edges.first; eed; eed = eed->next){ - eed->tmp.l = 0; - eed->v1->tmp.l = 0; - eed->v2->tmp.l = 0; - } - - /*1st pass*/ - for(eed=em->edges.first; eed; eed=eed->next){ - if(eed->f&SELECT){ - eed->v1->tmp.l = currtag; - eed->v2->tmp.l = currtag; - currtag +=1; - } - } - - /*2nd pass - Brute force. Loop through selected faces until there are no 'unbalanced' edges left (those with both vertices 'tmp.l' tag matching */ - while(ebalanced == 0){ - ebalanced = 1; - for(eed=em->edges.first; eed; eed = eed->next){ - if(eed->f&SELECT){ - if(eed->v1->tmp.l != eed->v2->tmp.l) /*unbalanced*/{ - if(eed->v1->tmp.l > eed->v2->tmp.l && eed->v2->tmp.l !=0) eed->v1->tmp.l = eed->v2->tmp.l; - else if(eed->v1 != 0) eed->v2->tmp.l = eed->v1->tmp.l; - ebalanced = 0; - } - } - } - } - - /*3rd pass, set all the edge flags (unnessecary?)*/ - for(eed=em->edges.first; eed; eed = eed->next){ - if(eed->f&SELECT) eed->tmp.l = eed->v1->tmp.l; - } - - for(eed=em->edges.first; eed; eed=eed->next){ - if(eed->f&SELECT){ - if(allcollections->first){ - for(edgecollection = allcollections->first; edgecollection; edgecollection=edgecollection->next){ - if(edgecollection->index == eed->tmp.l){ - newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge"); - newedge->eed = eed; - BLI_addtail(&(edgecollection->collectionbase), newedge); - collectionfound = 1; - break; - } - else collectionfound = 0; - } - } - if(allcollections->first == NULL || collectionfound == 0){ - newcollection = MEM_mallocN(sizeof(Collection), "element collection"); - newcollection->index = eed->tmp.l; - newcollection->collectionbase.first = 0; - newcollection->collectionbase.last = 0; - - newedge = MEM_mallocN(sizeof(CollectedEdge), "collected edge"); - newedge->eed = eed; - - BLI_addtail(&(newcollection->collectionbase), newedge); - BLI_addtail(allcollections, newcollection); - } - } - - } -} - -static void freecollections(ListBase *allcollections) -{ - struct Collection *curcollection; - - for(curcollection = allcollections->first; curcollection; curcollection = curcollection->next) - BLI_freelistN(&(curcollection->collectionbase)); - BLI_freelistN(allcollections); -} - -/*Begin UV Edge Collapse Code - Like Edge subdivide, Edge Collapse should handle UV's intelligently, but since UV's are a per-face attribute, normal edge collapse will fail - in areas such as the boundries of 'UV islands'. So for each edge collection we need to build a set of 'welded' UV vertices and edges for it. - The welded UV edges can then be sorted and collapsed. -*/ -typedef struct wUV{ - struct wUV *next, *prev; - ListBase nodes; - float u, v; /*cached copy of UV coordinates pointed to by nodes*/ - EditVert *eve; - int f; -} wUV; - -typedef struct wUVNode{ - struct wUVNode *next, *prev; - float *u; /*pointer to original tface data*/ - float *v; /*pointer to original tface data*/ -} wUVNode; - -typedef struct wUVEdge{ - struct wUVEdge *next, *prev; - float v1uv[2], v2uv[2]; /*nasty.*/ - struct wUV *v1, *v2; /*oriented same as editedge*/ - EditEdge *eed; - int f; -} wUVEdge; - -typedef struct wUVEdgeCollect{ /*used for grouping*/ - struct wUVEdgeCollect *next, *prev; - wUVEdge *uved; - int id; -} wUVEdgeCollect; - -static void append_weldedUV(EditMesh *em, EditFace *efa, EditVert *eve, int tfindex, ListBase *uvverts) -{ - wUV *curwvert, *newwvert; - wUVNode *newnode; - int found; - MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - found = 0; - - for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){ - if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){ - newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node"); - newnode->u = &(tf->uv[tfindex][0]); - newnode->v = &(tf->uv[tfindex][1]); - BLI_addtail(&(curwvert->nodes), newnode); - found = 1; - break; - } - } - - if(!found){ - newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node"); - newnode->u = &(tf->uv[tfindex][0]); - newnode->v = &(tf->uv[tfindex][1]); - - newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert"); - newwvert->u = *(newnode->u); - newwvert->v = *(newnode->v); - newwvert->eve = eve; - - BLI_addtail(&(newwvert->nodes), newnode); - BLI_addtail(uvverts, newwvert); - - } -} - -static void build_weldedUVs(EditMesh *em, ListBase *uvverts) -{ - EditFace *efa; - for(efa=em->faces.first; efa; efa=efa->next){ - if(efa->v1->f1) append_weldedUV(em, efa, efa->v1, 0, uvverts); - if(efa->v2->f1) append_weldedUV(em, efa, efa->v2, 1, uvverts); - if(efa->v3->f1) append_weldedUV(em, efa, efa->v3, 2, uvverts); - if(efa->v4 && efa->v4->f1) append_weldedUV(em, efa, efa->v4, 3, uvverts); - } -} - -static void append_weldedUVEdge(EditMesh *em, EditFace *efa, EditEdge *eed, ListBase *uvedges) -{ - wUVEdge *curwedge, *newwedge; - int v1tfindex, v2tfindex, found; - MTFace *tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - found = 0; - - if(eed->v1 == efa->v1) v1tfindex = 0; - else if(eed->v1 == efa->v2) v1tfindex = 1; - else if(eed->v1 == efa->v3) v1tfindex = 2; - else /* if(eed->v1 == efa->v4) */ v1tfindex = 3; - - if(eed->v2 == efa->v1) v2tfindex = 0; - else if(eed->v2 == efa->v2) v2tfindex = 1; - else if(eed->v2 == efa->v3) v2tfindex = 2; - else /* if(eed->v2 == efa->v4) */ v2tfindex = 3; - - for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){ - if(curwedge->eed == eed && curwedge->v1uv[0] == tf->uv[v1tfindex][0] && curwedge->v1uv[1] == tf->uv[v1tfindex][1] && curwedge->v2uv[0] == tf->uv[v2tfindex][0] && curwedge->v2uv[1] == tf->uv[v2tfindex][1]){ - found = 1; - break; //do nothing, we don't need another welded uv edge - } - } - - if(!found){ - newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge"); - newwedge->v1uv[0] = tf->uv[v1tfindex][0]; - newwedge->v1uv[1] = tf->uv[v1tfindex][1]; - newwedge->v2uv[0] = tf->uv[v2tfindex][0]; - newwedge->v2uv[1] = tf->uv[v2tfindex][1]; - newwedge->eed = eed; - - BLI_addtail(uvedges, newwedge); - } -} - -static void build_weldedUVEdges(EditMesh *em, ListBase *uvedges, ListBase *uvverts) -{ - wUV *curwvert; - wUVEdge *curwedge; - EditFace *efa; - - for(efa=em->faces.first; efa; efa=efa->next){ - if(efa->e1->f1) append_weldedUVEdge(em, efa, efa->e1, uvedges); - if(efa->e2->f1) append_weldedUVEdge(em, efa, efa->e2, uvedges); - if(efa->e3->f1) append_weldedUVEdge(em, efa, efa->e3, uvedges); - if(efa->e4 && efa->e4->f1) append_weldedUVEdge(em, efa, efa->e4, uvedges); - } - - - //link vertices: for each uvedge, search uvverts to populate v1 and v2 pointers - for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){ - for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){ - if(curwedge->eed->v1 == curwvert->eve && curwedge->v1uv[0] == curwvert->u && curwedge->v1uv[1] == curwvert->v){ - curwedge->v1 = curwvert; - break; - } - } - for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){ - if(curwedge->eed->v2 == curwvert->eve && curwedge->v2uv[0] == curwvert->u && curwedge->v2uv[1] == curwvert->v){ - curwedge->v2 = curwvert; - break; - } - } - } -} - -static void free_weldedUVs(ListBase *uvverts) -{ - wUV *curwvert; - for(curwvert = uvverts->first; curwvert; curwvert=curwvert->next) BLI_freelistN(&(curwvert->nodes)); - BLI_freelistN(uvverts); -} - -static void collapse_edgeuvs(EditMesh *em) -{ - ListBase uvedges, uvverts, allcollections; - wUVEdge *curwedge; - wUVNode *curwnode; - wUVEdgeCollect *collectedwuve, *newcollectedwuve; - Collection *wuvecollection, *newcollection; - int curtag, balanced, collectionfound= 0, vcount; - float avg[2]; - - if (!EM_texFaceCheck(em)) - return; - - uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL; - - build_weldedUVs(em, &uvverts); - build_weldedUVEdges(em, &uvedges, &uvverts); - - curtag = 0; - - for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){ - curwedge->v1->f = curtag; - curwedge->v2->f = curtag; - curtag +=1; - } - - balanced = 0; - while(!balanced){ - balanced = 1; - for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){ - if(curwedge->v1->f != curwedge->v2->f){ - if(curwedge->v1->f > curwedge->v2->f) curwedge->v1->f = curwedge->v2->f; - else curwedge->v2->f = curwedge->v1->f; - balanced = 0; - } - } - } - - for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next) curwedge->f = curwedge->v1->f; - - - for(curwedge=uvedges.first; curwedge; curwedge=curwedge->next){ - if(allcollections.first){ - for(wuvecollection = allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){ - if(wuvecollection->index == curwedge->f){ - newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge"); - newcollectedwuve->uved = curwedge; - BLI_addtail(&(wuvecollection->collectionbase), newcollectedwuve); - collectionfound = 1; - break; - } - - else collectionfound = 0; - } - } - if(allcollections.first == NULL || collectionfound == 0){ - newcollection = MEM_callocN(sizeof(Collection), "element collection"); - newcollection->index = curwedge->f; - newcollection->collectionbase.first = 0; - newcollection->collectionbase.last = 0; - - newcollectedwuve = MEM_callocN(sizeof(wUVEdgeCollect), "Collected Welded UV Edge"); - newcollectedwuve->uved = curwedge; - - BLI_addtail(&(newcollection->collectionbase), newcollectedwuve); - BLI_addtail(&allcollections, newcollection); - } - } - - for(wuvecollection=allcollections.first; wuvecollection; wuvecollection=wuvecollection->next){ - - vcount = avg[0] = avg[1] = 0; - - for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){ - avg[0] += collectedwuve->uved->v1uv[0]; - avg[1] += collectedwuve->uved->v1uv[1]; - - avg[0] += collectedwuve->uved->v2uv[0]; - avg[1] += collectedwuve->uved->v2uv[1]; - - vcount +=2; - - } - - avg[0] /= vcount; avg[1] /= vcount; - - for(collectedwuve= wuvecollection->collectionbase.first; collectedwuve; collectedwuve = collectedwuve->next){ - for(curwnode=collectedwuve->uved->v1->nodes.first; curwnode; curwnode=curwnode->next){ - *(curwnode->u) = avg[0]; - *(curwnode->v) = avg[1]; - } - for(curwnode=collectedwuve->uved->v2->nodes.first; curwnode; curwnode=curwnode->next){ - *(curwnode->u) = avg[0]; - *(curwnode->v) = avg[1]; - } - } - } - - free_weldedUVs(&uvverts); - BLI_freelistN(&uvedges); - freecollections(&allcollections); -} - -/*End UV Edge collapse code*/ - -static void collapseuvs(EditMesh *em, EditVert *mergevert) -{ - EditFace *efa; - MTFace *tf; - int uvcount; - float uvav[2]; - - if (!EM_texFaceCheck(em)) - return; - - uvcount = 0; - uvav[0] = 0; - uvav[1] = 0; - - for(efa = em->faces.first; efa; efa=efa->next){ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(efa->v1->f1 && ELEM(mergevert, NULL, efa->v1)) { - uvav[0] += tf->uv[0][0]; - uvav[1] += tf->uv[0][1]; - uvcount += 1; - } - if(efa->v2->f1 && ELEM(mergevert, NULL, efa->v2)){ - uvav[0] += tf->uv[1][0]; - uvav[1] += tf->uv[1][1]; - uvcount += 1; - } - if(efa->v3->f1 && ELEM(mergevert, NULL, efa->v3)){ - uvav[0] += tf->uv[2][0]; - uvav[1] += tf->uv[2][1]; - uvcount += 1; - } - if(efa->v4 && efa->v4->f1 && ELEM(mergevert, NULL, efa->v4)){ - uvav[0] += tf->uv[3][0]; - uvav[1] += tf->uv[3][1]; - uvcount += 1; - } - } - - if(uvcount > 0) { - uvav[0] /= uvcount; - uvav[1] /= uvcount; - - for(efa = em->faces.first; efa; efa=efa->next){ - tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - - if(efa->v1->f1){ - tf->uv[0][0] = uvav[0]; - tf->uv[0][1] = uvav[1]; - } - if(efa->v2->f1){ - tf->uv[1][0] = uvav[0]; - tf->uv[1][1] = uvav[1]; - } - if(efa->v3->f1){ - tf->uv[2][0] = uvav[0]; - tf->uv[2][1] = uvav[1]; - } - if(efa->v4 && efa->v4->f1){ - tf->uv[3][0] = uvav[0]; - tf->uv[3][1] = uvav[1]; - } - } - } -} - -int collapseEdges(EditMesh *em) -{ - EditVert *eve; - EditEdge *eed; - - ListBase allcollections; - CollectedEdge *curredge; - Collection *edgecollection; - - int totedges, groupcount, mergecount,vcount; - float avgcount[3]; - - allcollections.first = 0; - allcollections.last = 0; - - mergecount = 0; - - build_edgecollection(em, &allcollections); - groupcount = BLI_countlist(&allcollections); - - - for(edgecollection = allcollections.first; edgecollection; edgecollection = edgecollection->next){ - totedges = BLI_countlist(&(edgecollection->collectionbase)); - mergecount += totedges; - avgcount[0] = 0; avgcount[1] = 0; avgcount[2] = 0; - - vcount = 0; - - for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ - avgcount[0] += ((EditEdge*)curredge->eed)->v1->co[0]; - avgcount[1] += ((EditEdge*)curredge->eed)->v1->co[1]; - avgcount[2] += ((EditEdge*)curredge->eed)->v1->co[2]; - - avgcount[0] += ((EditEdge*)curredge->eed)->v2->co[0]; - avgcount[1] += ((EditEdge*)curredge->eed)->v2->co[1]; - avgcount[2] += ((EditEdge*)curredge->eed)->v2->co[2]; - - vcount +=2; - } - - avgcount[0] /= vcount; avgcount[1] /=vcount; avgcount[2] /= vcount; - - for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ - VECCOPY(((EditEdge*)curredge->eed)->v1->co,avgcount); - VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount); - } - - if (EM_texFaceCheck(em)) { - /*uv collapse*/ - for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0; - for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0; - for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ - curredge->eed->v1->f1 = 1; - curredge->eed->v2->f1 = 1; - curredge->eed->f1 = 1; - } - collapse_edgeuvs(em); - } - - } - freecollections(&allcollections); - removedoublesflag(em, 1, 0, MERGELIMIT); - - return mergecount; -} - - - -/********************** Region/Loop Operators *************************/ - -static int region_to_loop(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - EditEdge *eed; - EditFace *efa; - int selected= 0; - - for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = 0; - - for(efa=em->faces.first; efa; efa=efa->next){ - if(efa->f&SELECT){ - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) - efa->e4->f1++; - - selected= 1; - } - } - - if(!selected) - return OPERATOR_CANCELLED; - - EM_clear_flag_all(em, SELECT); - - for(eed=em->edges.first; eed; eed=eed->next){ - if(eed->f1 == 1) EM_select_edge(eed, 1); - } - - em->selectmode = SCE_SELECT_EDGE; - EM_selectmode_set(em); - - BKE_mesh_end_editmesh(obedit->data, em); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_region_to_loop(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Region to Loop"; - ot->idname= "MESH_OT_region_to_loop"; - - /* api callbacks */ - ot->exec= region_to_loop; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int validate_loop(EditMesh *em, Collection *edgecollection) -{ - EditEdge *eed; - EditFace *efa; - CollectedEdge *curredge; - - /*1st test*/ - for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ - curredge->eed->v1->f1 = 0; - curredge->eed->v2->f1 = 0; - } - for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ - curredge->eed->v1->f1++; - curredge->eed->v2->f1++; - } - for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ - if(curredge->eed->v1->f1 > 2) return(0); else - if(curredge->eed->v2->f1 > 2) return(0); - } - - /*2nd test*/ - for(eed = em->edges.first; eed; eed=eed->next) eed->f1 = 0; - for(efa=em->faces.first; efa; efa=efa->next){ - efa->e1->f1++; - efa->e2->f1++; - efa->e3->f1++; - if(efa->e4) efa->e4->f1++; - } - for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){ - if(curredge->eed->f1 > 2) return(0); - } - return(1); -} - -static int loop_bisect(EditMesh *em, Collection *edgecollection) -{ - EditFace *efa, *sf1, *sf2; - EditEdge *eed, *sed; - CollectedEdge *curredge; - int totsf1, totsf2, unbalanced,balancededges; - - for(eed=em->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0; - for(efa=em->faces.first; efa; efa=efa->next) efa->f1 = 0; - - for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next) curredge->eed->f1 = 1; - - sf1 = sf2 = NULL; - sed = ((CollectedEdge*)edgecollection->collectionbase.first)->eed; - - for(efa=em->faces.first; efa; efa=efa->next){ - if(sf2) break; - else if(sf1){ - if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf2 = efa; - } - else{ - if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf1 = efa; - } - } - - if(sf1==NULL || sf2==NULL) - return(-1); - - if(!(sf1->e1->f1)) sf1->e1->f2 = 1; - if(!(sf1->e2->f1)) sf1->e2->f2 = 1; - if(!(sf1->e3->f1)) sf1->e3->f2 = 1; - if(sf1->e4 && !(sf1->e4->f1)) sf1->e4->f2 = 1; - sf1->f1 = 1; - totsf1 = 1; - - if(!(sf2->e1->f1)) sf2->e1->f2 = 2; - if(!(sf2->e2->f1)) sf2->e2->f2 = 2; - if(!(sf2->e3->f1)) sf2->e3->f2 = 2; - if(sf2->e4 && !(sf2->e4->f1)) sf2->e4->f2 = 2; - sf2->f1 = 2; - totsf2 = 1; - - /*do sf1*/ - unbalanced = 1; - while(unbalanced){ - unbalanced = 0; - for(efa=em->faces.first; efa; efa=efa->next){ - balancededges = 0; - if(efa->f1 == 0){ - if(efa->e1->f2 == 1 || efa->e2->f2 == 1 || efa->e3->f2 == 1 || ( (efa->e4) ? efa->e4->f2 == 1 : 0) ){ - balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 1; - balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 1; - balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 1; - if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 1; - if(balancededges){ - unbalanced = 1; - efa->f1 = 1; - totsf1++; - } - } - } - } - } - - /*do sf2*/ - unbalanced = 1; - while(unbalanced){ - unbalanced = 0; - for(efa=em->faces.first; efa; efa=efa->next){ - balancededges = 0; - if(efa->f1 == 0){ - if(efa->e1->f2 == 2 || efa->e2->f2 == 2 || efa->e3->f2 == 2 || ( (efa->e4) ? efa->e4->f2 == 2 : 0) ){ - balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 2; - balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 2; - balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 2; - if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 2; - if(balancededges){ - unbalanced = 1; - efa->f1 = 2; - totsf2++; - } - } - } - } - } - - if(totsf1 < totsf2) return(1); - else return(2); -} - -static int loop_to_region(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - - EditFace *efa; - ListBase allcollections={NULL,NULL}; - Collection *edgecollection; - int testflag; - - build_edgecollection(em, &allcollections); - - for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){ - if(validate_loop(em, edgecollection)){ - testflag = loop_bisect(em, edgecollection); - for(efa=em->faces.first; efa; efa=efa->next){ - if(efa->f1 == testflag){ - if(efa->f&SELECT) EM_select_face(efa, 0); - else EM_select_face(efa,1); - } - } - } - } - - for(efa=em->faces.first; efa; efa=efa->next){ /*fix this*/ - if(efa->f&SELECT) EM_select_face(efa,1); - } - - freecollections(&allcollections); - BKE_mesh_end_editmesh(obedit->data, em); - - WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_loop_to_region(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Loop to Region"; - ot->idname= "MESH_OT_loop_to_region"; - - /* api callbacks */ - ot->exec= loop_to_region; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -/********************** Fill Operators *************************/ - -/* note; the EM_selectmode_set() calls here illustrate how badly constructed it all is... from before the -edge/face flags, with very mixed results.... */ -static void beauty_fill(EditMesh *em) -{ - EditVert *v1, *v2, *v3, *v4; - EditEdge *eed, *nexted; - EditEdge dia1, dia2; - EditFace *efa, *w; - // void **efaar, **efaa; - EVPTuple *efaar; - EVPtr *efaa; - float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2; - int totedge, ok, notbeauty=8, onedone, vindex[4]; - - /* - all selected edges with two faces - * - find the faces: store them in edges (using datablock) - * - per edge: - test convex - * - test edge: flip? - * - if true: remedge, addedge, all edges at the edge get new face pointers - */ - - EM_selectmode_set(em); // makes sure in selectmode 'face' the edges of selected faces are selected too - - totedge = count_selected_edges(em->edges.first); - if(totedge==0) return; - - /* temp block with face pointers */ - efaar= (EVPTuple *) MEM_callocN(totedge * sizeof(EVPTuple), "beautyfill"); - - while (notbeauty) { - notbeauty--; - - ok = collect_quadedges(efaar, em->edges.first, em->faces.first); - - /* there we go */ - onedone= 0; - - eed= em->edges.first; - while(eed) { - nexted= eed->next; - - /* f2 is set in collect_quadedges() */ - if(eed->f2==2 && eed->h==0) { - - efaa = (EVPtr *) eed->tmp.p; - - /* none of the faces should be treated before, nor be part of fgon */ - ok= 1; - efa= efaa[0]; - if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; - if(efa->fgonf) ok= 0; - efa= efaa[1]; - if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1) ok= 0; - if(efa->fgonf) ok= 0; - - if(ok) { - /* test convex */ - givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); - if(v1 && v2 && v3 && v4) { - if( convex(v1->co, v2->co, v3->co, v4->co) ) { - - /* test edges */ - if( (v1) > (v3) ) { - dia1.v1= v3; - dia1.v2= v1; - } - else { - dia1.v1= v1; - dia1.v2= v3; - } - - if( (v2) > (v4) ) { - dia2.v1= v4; - dia2.v2= v2; - } - else { - dia2.v1= v2; - dia2.v2= v4; - } - - /* testing rule: - * the area divided by the total edge lengths - */ - - len1= len_v3v3(v1->co, v2->co); - len2= len_v3v3(v2->co, v3->co); - len3= len_v3v3(v3->co, v4->co); - len4= len_v3v3(v4->co, v1->co); - len5= len_v3v3(v1->co, v3->co); - len6= len_v3v3(v2->co, v4->co); - - opp1= area_tri_v3(v1->co, v2->co, v3->co); - opp2= area_tri_v3(v1->co, v3->co, v4->co); - - fac1= opp1/(len1+len2+len5) + opp2/(len3+len4+len5); - - opp1= area_tri_v3(v2->co, v3->co, v4->co); - opp2= area_tri_v3(v2->co, v4->co, v1->co); - - fac2= opp1/(len2+len3+len6) + opp2/(len4+len1+len6); - - ok= 0; - if(fac1 > fac2) { - if(dia2.v1==eed->v1 && dia2.v2==eed->v2) { - eed->f1= 1; - efa= efaa[0]; - efa->f1= 1; - efa= efaa[1]; - efa->f1= 1; - - w= EM_face_from_faces(em, efaa[0], efaa[1], - vindex[0], vindex[1], 4+vindex[2], -1); - w->f |= SELECT; - - - w= EM_face_from_faces(em, efaa[0], efaa[1], - vindex[0], 4+vindex[2], 4+vindex[3], -1); - w->f |= SELECT; - - onedone= 1; - } - } - else if(fac1 < fac2) { - if(dia1.v1==eed->v1 && dia1.v2==eed->v2) { - eed->f1= 1; - efa= efaa[0]; - efa->f1= 1; - efa= efaa[1]; - efa->f1= 1; - - - w= EM_face_from_faces(em, efaa[0], efaa[1], - vindex[1], 4+vindex[2], 4+vindex[3], -1); - w->f |= SELECT; - - - w= EM_face_from_faces(em, efaa[0], efaa[1], - vindex[0], 4+vindex[1], 4+vindex[3], -1); - w->f |= SELECT; - - onedone= 1; - } - } - } - } - } - - } - eed= nexted; - } - - free_tagged_edges_faces(em, em->edges.first, em->faces.first); - - if(onedone==0) break; - - EM_selectmode_set(em); // new edges/faces were added - } - - MEM_freeN(efaar); - - EM_select_flush(em); - -} - -/* Got this from scanfill.c. You will need to juggle around the -* callbacks for the scanfill.c code a bit for this to work. */ -static void fill_mesh(EditMesh *em) -{ - EditVert *eve,*v1; - EditEdge *eed,*e1,*nexted; - EditFace *efa,*nextvl, *efan; - short ok; - - if(em==NULL) return; - waitcursor(1); - - /* copy all selected vertices */ - eve= em->verts.first; - while(eve) { - if(eve->f & SELECT) { - v1= BLI_addfillvert(eve->co); - eve->tmp.v= v1; - v1->tmp.v= eve; - v1->xs= 0; // used for counting edges - } - eve= eve->next; - } - /* copy all selected edges */ - eed= em->edges.first; - while(eed) { - if( (eed->v1->f & SELECT) && (eed->v2->f & SELECT) ) { - e1= BLI_addfilledge(eed->v1->tmp.v, eed->v2->tmp.v); - e1->v1->xs++; - e1->v2->xs++; - } - eed= eed->next; - } - /* from all selected faces: remove vertices and edges to prevent doubles */ - /* all edges add values, faces subtract, - then remove edges with vertices ->xs<2 */ - efa= em->faces.first; - ok= 0; - while(efa) { - nextvl= efa->next; - if( faceselectedAND(efa, 1) ) { - efa->v1->tmp.v->xs--; - efa->v2->tmp.v->xs--; - efa->v3->tmp.v->xs--; - if(efa->v4) efa->v4->tmp.v->xs--; - ok= 1; - - } - efa= nextvl; - } - if(ok) { /* there are faces selected */ - eed= filledgebase.first; - while(eed) { - nexted= eed->next; - if(eed->v1->xs<2 || eed->v2->xs<2) { - BLI_remlink(&filledgebase,eed); - } - eed= nexted; - } - } - - if(BLI_edgefill(0, em->mat_nr)) { - efa= fillfacebase.first; - while(efa) { - /* normals default pointing up */ - efan= addfacelist(em, efa->v3->tmp.v, efa->v2->tmp.v, - efa->v1->tmp.v, 0, NULL, NULL); - if(efan) EM_select_face(efan, 1); - efa= efa->next; - } - } - - BLI_end_edgefill(); - beauty_fill(em); - - WM_cursor_wait(0); - EM_select_flush(em); - -} - -static int fill_mesh_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - fill_mesh(em); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; - -} - -void MESH_OT_fill(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Fill"; - ot->idname= "MESH_OT_fill"; - - /* api callbacks */ - ot->exec= fill_mesh_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int beauty_fill_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - beauty_fill(em); - - BKE_mesh_end_editmesh(obedit->data, em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_beauty_fill(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Beauty Fill"; - ot->idname= "MESH_OT_beauty_fill"; - - /* api callbacks */ - ot->exec= beauty_fill_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -/********************** Quad/Tri Operators *************************/ - -static int quads_convert_to_tris_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh; - - //convert_to_triface(em,0); - if (!EDBM_CallOpf(em, op, "triangulate faces=%hf", BM_SELECT)) - return OPERATOR_CANCELLED; - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - return OPERATOR_FINISHED; -} - -void MESH_OT_quads_convert_to_tris(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Quads to Tris"; - ot->idname= "MESH_OT_quads_convert_to_tris"; - - /* api callbacks */ - ot->exec= quads_convert_to_tris_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int tris_convert_to_quads_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - join_triangles(em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_tris_convert_to_quads(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Tris to Quads"; - ot->idname= "MESH_OT_tris_convert_to_quads"; - - /* api callbacks */ - ot->exec= tris_convert_to_quads_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int edge_flip_exec(bContext *C, wmOperator *op) -{ - Object *obedit= CTX_data_edit_object(C); - EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - - edge_flip(em); - - DAG_id_flush_update(obedit->data, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); - - BKE_mesh_end_editmesh(obedit->data, em); - return OPERATOR_FINISHED; -} - -void MESH_OT_edge_flip(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Edge Flip"; - ot->idname= "MESH_OT_edge_flip"; - - /* api callbacks */ - ot->exec= edge_flip_exec; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 85996b462ed..a4b68d35984 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -32,11 +32,14 @@ #ifndef MESH_INTERN_H #define MESH_INTERN_H -#include "BLI_editVert.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_mesh_types.h" +#include "BKE_tessmesh.h" + +#include "BLI_editVert.h" + struct bContext; struct wmOperatorType; struct ViewContext; @@ -57,10 +60,14 @@ ok: the EDBM module is for editmode bmesh stuff. in contrast, the the BMEditMesh structure. */ -/*calls a bmesh op, reporting errors to the user, doing conversions, - etc.*/ +/*calls a bmesh op, reporting errors to the user, etc*/ int EDBM_CallOpf(struct BMEditMesh *em, struct wmOperator *op, char *fmt, ...); +/*calls a bmesh op, reporting errors to the user, etc. + + selects an output slot specified by selslot*/ +int EDBM_CallAndSelectOpf(struct BMEditMesh *em, struct wmOperator *op, char *selslot, char *fmt, ...); + /*same as above, but doesn't report errors.*/ int EDBM_CallOpfSilent(struct BMEditMesh *em, char *fmt, ...); @@ -83,15 +90,12 @@ void EDBM_stats_update(struct BMEditMesh *em); /* ******************** editface.c */ -int edgetag_context_check(Scene *scene, EditEdge *eed); -void edgetag_context_set(Scene *scene, EditEdge *eed, int val); -int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target); +int edgetag_context_check(Scene *scene, BMEdge *eed); +void edgetag_context_set(Scene *scene, BMEdge *eed, int val); +int edgetag_shortest_path(Scene *scene, BMEditMesh *em, EditEdge *source, EditEdge *target); /* ******************* editmesh.c */ -void EM_beginEditMesh(struct Object *ob); -void EM_endEditMesh(struct Object *ob, EditMesh *em); - extern void free_editvert(EditMesh *em, EditVert *eve); extern void free_editedge(EditMesh *em, EditEdge *eed); extern void free_editface(EditMesh *em, EditFace *efa); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 5c5eac0b5d2..7baae6bbb1f 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -96,8 +96,6 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_primitive_monkey_add); WM_operatortype_append(MESH_OT_primitive_uv_sphere_add); WM_operatortype_append(MESH_OT_primitive_ico_sphere_add); - WM_operatortype_append(MESH_OT_fgon_clear); - WM_operatortype_append(MESH_OT_fgon_make); WM_operatortype_append(MESH_OT_duplicate); WM_operatortype_append(MESH_OT_remove_doubles); WM_operatortype_append(MESH_OT_extrude); @@ -292,9 +290,6 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MESH_OT_delete", DELKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "MESH_OT_fgon_make", FKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "MESH_OT_fgon_clear", FKEY, KM_PRESS, KM_SHIFT|KM_ALT, 0); - WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY); WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 313ffe79c66..e1edefdd73f 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -56,6 +56,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "RNA_define.h" #include "RNA_access.h" @@ -74,13 +75,14 @@ #include "object_intern.h" -static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent) +static int return_editmesh_indexar(BMEditMesh *em, int *tot, int **indexar, float *cent) { - EditVert *eve; + BMVert *eve; + BMIter iter; int *index, nr, totvert=0; - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) totvert++; + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if(BM_TestHFlag(eve, BM_SELECT)) totvert++; } if(totvert==0) return 0; @@ -89,8 +91,8 @@ static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float nr= 0; cent[0]= cent[1]= cent[2]= 0.0; - for(eve= em->verts.first; eve; eve= eve->next) { - if(eve->f & SELECT) { + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if(BM_TestHFlag(eve, BM_SELECT)) { *index= nr; index++; add_v3_v3v3(cent, cent, eve->co); } @@ -102,10 +104,11 @@ static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float return totvert; } -static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent) +static int return_editmesh_vgroup(Object *obedit, BMEditMesh *em, char *name, float *cent) { MDeformVert *dvert; - EditVert *eve; + BMVert *eve; + BMIter iter; int i, totvert=0; cent[0]= cent[1]= cent[2]= 0.0; @@ -113,8 +116,8 @@ static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, floa if(obedit->actdef) { /* find the vertices */ - for(eve= em->verts.first; eve; eve= eve->next) { - dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + dvert= CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); if(dvert) { for(i=0; i<dvert->totweight; i++){ @@ -136,25 +139,27 @@ static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, floa return 0; } -static void select_editmesh_hook(Object *ob, HookModifierData *hmd) +static void select_editbmesh_hook(Object *ob, HookModifierData *hmd) { Mesh *me= ob->data; - EditMesh *em= BKE_mesh_get_editmesh(me); - EditVert *eve; + BMEditMesh *em= me->edit_btmesh; + BMVert *eve; + BMIter iter; int index=0, nr=0; if (hmd->indexar == NULL) return; - for(eve= em->verts.first; eve; eve= eve->next, nr++) { + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { if(nr==hmd->indexar[index]) { - eve->f |= SELECT; + BM_Select(em->bm, eve, 1); if(index < hmd->totindex-1) index++; } + + nr++; } - EM_select_flush(em); - BKE_mesh_end_editmesh(me, em); + EDBM_selectmode_flush(em); } static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent) @@ -303,15 +308,13 @@ static int object_hook_index_array(Object *obedit, int *tot, int **indexar, char case OB_MESH: { Mesh *me= obedit->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; /* check selected vertices first */ if( return_editmesh_indexar(em, tot, indexar, cent_r)) { - BKE_mesh_end_editmesh(me, em); return 1; } else { int ret = return_editmesh_vgroup(obedit, em, name, cent_r); - BKE_mesh_end_editmesh(me, em); return ret; } } @@ -380,7 +383,7 @@ static void object_hook_select(Object *ob, HookModifierData *hmd) if (hmd->indexar == NULL) return; - if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd); + if(ob->type==OB_MESH) select_editbmesh_hook(ob, hmd); else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd); else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd); else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 9d95c9dfe28..bcb6ad51e8c 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -75,6 +75,7 @@ #include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "WM_api.h" #include "WM_types.h" @@ -105,7 +106,8 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); Object *obedit= CTX_data_edit_object(C); - EditVert *eve; + BMVert *eve; + BMIter iter; Curve *cu; Nurb *nu; BezTriple *bezt; @@ -117,22 +119,17 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) if(obedit->type==OB_MESH) { Mesh *me= obedit->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; - eve= em->verts.first; - while(eve) { - if(eve->f & 1) { + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if (BM_TestHFlag(eve, BM_SELECT)) { if(v1==0) v1= nr; else if(v2==0) v2= nr; else if(v3==0) v3= nr; else if(v4==0) v4= nr; else break; } - nr++; - eve= eve->next; } - - BKE_mesh_end_editmesh(me, em); } else if(ELEM(obedit->type, OB_SURF, OB_CURVE)) { ListBase *editnurb= curve_get_editcurve(obedit); diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 43382562a8a..fcedf75b854 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -53,6 +53,7 @@ #include "BKE_object.h" #include "BKE_report.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "RNA_define.h" #include "RNA_access.h" @@ -712,11 +713,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) /* BezTriple *bezt; BPoint *bp; */ Nurb *nu, *nu1; - EditVert *eve; float cent[3], centn[3], min[3], max[3], omat[3][3]; int a, total= 0; - int centermode = RNA_enum_get(op->ptr, "type"); - + int centermode = RNA_enum_get(op->ptr, "type"); /* keep track of what is changed */ int tot_change=0, tot_lib_error=0, tot_multiuser_arm_error=0; MVert *mvert; @@ -732,14 +731,15 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) cent[0]= cent[1]= cent[2]= 0.0; if(obedit) { - INIT_MINMAX(min, max); if(obedit->type==OB_MESH) { Mesh *me= obedit->data; - EditMesh *em = BKE_mesh_get_editmesh(me); + BMEditMesh *em = me->edit_btmesh; + BMVert *eve; + BMIter iter; - for(eve= em->verts.first; eve; eve= eve->next) { + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { if(v3d->around==V3D_CENTROID) { total++; VECADD(cent, cent, eve->co); @@ -758,14 +758,13 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) cent[2]= (min[2]+max[2])/2.0f; } - for(eve= em->verts.first; eve; eve= eve->next) { + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { sub_v3_v3v3(eve->co, eve->co, cent); } - recalc_editnormals(em); + EDBM_RecalcNormals(em); tot_change++; DAG_id_flush_update(&obedit->id, OB_RECALC_DATA); - BKE_mesh_end_editmesh(me, em); } } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 6b92fc3fe4f..e5184ec98b0 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -61,6 +61,7 @@ #include "BKE_paint.h" #include "BKE_screen.h" #include "BKE_utildefines.h" +#include "BKE_tessmesh.h" #include "RE_pipeline.h" @@ -115,7 +116,7 @@ /* XXX */ static int simaFaceDraw_Check() {return 0;} -static int simaUVSel_Check() {return 0;} +static int simaUVSel_Check() { return 0;} /* XXX */ /* proto */ @@ -222,39 +223,32 @@ static void image_editvertex_buts(const bContext *C, uiBlock *block) { SpaceImage *sima= CTX_wm_space_image(C); Object *obedit= CTX_data_edit_object(C); + BMEditMesh *em; + BMFace *efa; + MTexPoly *tf; + BMLoop *l; + MLoopUV *luv; + BMIter iter, liter; static float ocent[2]; float cent[2]= {0.0, 0.0}; int imx= 256, imy= 256; int nactive= 0, step, digits; - EditMesh *em; - EditFace *efa; - MTFace *tf; image_transform_but_attr(sima, &imx, &imy, &step, &digits); - em= BKE_mesh_get_editmesh((Mesh *)obedit->data); - for (efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (simaFaceDraw_Check(efa, tf)) { + em= ((Mesh *)obedit->data)->edit_btmesh; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!simaFaceDraw_Check(efa, tf)) + continue; + + BM_ITER(l, &iter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - if (simaUVSel_Check(efa, tf, 0)) { - cent[0]+= tf->uv[0][0]; - cent[1]+= tf->uv[0][1]; - nactive++; - } - if (simaUVSel_Check(efa, tf, 1)) { - cent[0]+= tf->uv[1][0]; - cent[1]+= tf->uv[1][1]; - nactive++; - } - if (simaUVSel_Check(efa, tf, 2)) { - cent[0]+= tf->uv[2][0]; - cent[1]+= tf->uv[2][1]; - nactive++; - } - if (efa->v4 && simaUVSel_Check(efa, tf, 3)) { - cent[0]+= tf->uv[3][0]; - cent[1]+= tf->uv[3][1]; + if (simaUVSel_Check(efa, tf, luv)) { + cent[0] += luv->uv[0]; + cent[1] += luv->uv[1]; + nactive++; } } @@ -297,32 +291,23 @@ static void image_editvertex_buts(const bContext *C, uiBlock *block) delta[1]= ocent[1]/imy - cent[1]; } - for (efa= em->faces.first; efa; efa= efa->next) { - tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); - if (simaFaceDraw_Check(efa, tf)) { - if (simaUVSel_Check(efa, tf, 0)) { - tf->uv[0][0]+= delta[0]; - tf->uv[0][1]+= delta[1]; - } - if (simaUVSel_Check(efa, tf, 1)) { - tf->uv[1][0]+= delta[0]; - tf->uv[1][1]+= delta[1]; - } - if (simaUVSel_Check(efa, tf, 2)) { - tf->uv[2][0]+= delta[0]; - tf->uv[2][1]+= delta[1]; - } - if (efa->v4 && simaUVSel_Check(efa, tf, 3)) { - tf->uv[3][0]+= delta[0]; - tf->uv[3][1]+= delta[1]; + BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + if (!simaFaceDraw_Check(efa, tf)) + continue; + + BM_ITER(l, &iter, em->bm, BM_LOOPS_OF_FACE, efa) { + luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + + if (simaUVSel_Check(efa, tf, luv)) { + luv->uv[0] += delta[0]; + luv->uv[1] += delta[1]; } } } - + WM_event_add_notifier(C, NC_IMAGE, sima->image); } - - BKE_mesh_end_editmesh(obedit->data, em); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index d1463151a27..4eb270471d5 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -379,20 +379,19 @@ static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, View3D *v3d if(ob->type==OB_MESH) { Mesh *me= ob->data; - EditMesh *em = BKE_mesh_get_editmesh(me); - EditVert *eve; - EditEdge *eed; - - eve= em->verts.first; - while(eve) { - if(eve->f & SELECT) { + BMEditMesh *em = me->edit_btmesh; + BMVert *eve; + BMEdge *eed; + BMIter iter; + + BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { + if(BM_TestHFlag(eve, BM_SELECT)) { add_v3_v3v3(eve->co, eve->co, median); } - eve= eve->next; } - for(eed= em->edges.first; eed; eed= eed->next) { - if(eed->f & SELECT) { + BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) { + if(BM_TestHFlag(eed, BM_SELECT)) { /* ensure the median can be set to zero or one */ if(ve_median[3]==0.0f) eed->crease= 0.0f; else if(ve_median[3]==1.0f) eed->crease= 1.0f; @@ -403,9 +402,7 @@ static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, View3D *v3d } } - recalc_editnormals(em); - - BKE_mesh_end_editmesh(me, em); + EDBM_RecalcNormals(em); } else if(ob->type==OB_CURVE || ob->type==OB_SURF) { Curve *cu= ob->data; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index a57d3f55f15..f9b938e49b8 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -172,7 +172,7 @@ void EDBM_backbuf_checkAndSelectVerts(BMEditMesh *em, int select) } } -void EM_backbuf_checkAndSelectEdges(BMEditMesh *em, int select) +void EDBM_backbuf_checkAndSelectEdges(BMEditMesh *em, int select) { BMEdge *eed; BMIter iter; @@ -188,7 +188,7 @@ void EM_backbuf_checkAndSelectEdges(BMEditMesh *em, int select) } } -void EM_backbuf_checkAndSelectFaces(BMEditMesh *em, int select) +void EDBM_backbuf_checkAndSelectFaces(BMEditMesh *em, int select) { BMFace *efa; BMIter iter; @@ -204,7 +204,7 @@ void EM_backbuf_checkAndSelectFaces(BMEditMesh *em, int select) } } -void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select) +void EDBM_backbuf_checkAndSelectTFaces(Mesh *me, int select) { MFace *mface = me->mface; int a; @@ -431,7 +431,7 @@ static void do_lasso_select_mesh__doSelectEdge(void *userData, BMEdge *eed, int { struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData; - if (EM_check_backbuf(bm_solidoffs+index)) { + if (EDBM_check_backbuf(bm_solidoffs+index)) { if (data->pass==0) { if ( edge_fully_inside_rect(data->rect, x0, y0, x1, y1) && lasso_inside(data->mcords, data->moves, x0, y0) && @@ -474,11 +474,11 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves data.done = 0; data.pass = 0; - /* workaround: init mats first, EM_mask_init_backbuf_border can change + /* workaround: init mats first, EDBM_mask_init_backbuf_border can change view matrix to pixel space, breaking edge select with backbuf .. */ // XXX not needed anymore, check here if selection is broken //ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + bbsel= EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); if(vc->scene->toolsettings->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { @@ -501,13 +501,13 @@ static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) { if (bbsel) { - EM_backbuf_checkAndSelectFaces(vc->em, select); + EDBM_backbuf_checkAndSelectFaces(vc->em, select); } else { mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data); } } - EM_free_backbuf(); + EDBM_free_backbuf(); EDBM_selectmode_flush(vc->em); } @@ -680,11 +680,11 @@ static void do_lasso_select_facemode(ViewContext *vc, short mcords[][2], short m bm_vertoffs= me->totface+1; /* max index array */ lasso_select_boundbox(&rect, mcords, moves); - EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - EM_backbuf_checkAndSelectTFaces(me, select); + EDBM_backbuf_checkAndSelectTFaces(me, select); - EM_free_backbuf(); + EDBM_free_backbuf(); // XXX object_tface_flags_changed(ob, 0); } @@ -1336,7 +1336,7 @@ static void do_mesh_box_select__doSelectEdge(void *userData, BMEdge *eed, int x0 { struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData; - if(EM_check_backbuf(bm_solidoffs+index)) { + if(EDBM_check_backbuf(bm_solidoffs+index)) { if (data->pass==0) { if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) { BM_Select_Edge(data->vc.em->bm, eed, data->select); @@ -1405,13 +1405,13 @@ static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exte if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) { if(bbsel) { - EM_backbuf_checkAndSelectFaces(vc->em, select); + EDBM_backbuf_checkAndSelectFaces(vc->em, select); } else { mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data); } } - EM_free_backbuf(); + EDBM_free_backbuf(); EDBM_selectmode_flush(vc->em); } @@ -1459,7 +1459,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op) Mesh *me= obedit->data; vc.em= me->edit_btmesh; do_mesh_box_select(&vc, &rect, selecting, extend); -// if (EM_texFaceCheck()) +// if (EDBM_texFaceCheck()) WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data); } @@ -1834,7 +1834,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa if(vc->scene->toolsettings->selectmode & SCE_SELECT_EDGE) { if (bbsel) { - EM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE); + EDBM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE); } else { mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, 0); } @@ -1842,7 +1842,7 @@ static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, floa if(vc->scene->toolsettings->selectmode & SCE_SELECT_FACE) { if(bbsel) { - EM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE); + EDBM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE); } else { mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 6edec42d91a..8d31b8dc2fd 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1329,11 +1329,11 @@ void calculateCenter(TransInfo *t) /* EDIT MODE ACTIVE EDITMODE ELEMENT */ if (t->obedit && t->obedit->type == OB_MESH) { - EditSelection ese; - EditMesh *em = BKE_mesh_get_editmesh(t->obedit->data); + BMEditSelection ese; + BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh; - if (EM_get_actSelection(em, &ese)) { - EM_editselection_center(t->center, &ese); + if (EDBM_get_actSelection(em, &ese)) { + EDBM_editselection_center(em, t->center, &ese); calculateCenter2D(t); break; } diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index dd658f02d35..67a06423993 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -990,7 +990,7 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit select= 1; BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { - tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); a = 0; BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) { @@ -1174,7 +1174,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, float limit[ MEM_freeN(stack); MEM_freeN(flag); EDBM_free_uv_vert_map(vmap); - EM_free_index_arrays(); + EDBM_free_index_arrays(em); } /* ******************** align operator **************** */ @@ -1352,7 +1352,7 @@ static int stitch_exec(bContext *C, wmOperator *op) a = 0; BM_ITER(eve, &iter, em->bm, BM_VERTS_OF_MESH, NULL) { - vlist= EM_get_uv_map_vert(vmap, a); + vlist= EDBM_get_uv_map_vert(vmap, a); while(vlist) { newuv[0]= 0; newuv[1]= 0; @@ -1504,7 +1504,7 @@ static int select_inverse_exec(bContext *C, wmOperator *op) } else { BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { - tf = CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); if(!uvedit_face_visible(scene, ima, efa, tf)) continue; @@ -1859,7 +1859,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) /* deselect */ if(select==0) { BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { - tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); if(!uvedit_face_visible(scene, ima, efa, tf)) continue; @@ -1913,7 +1913,7 @@ static int mouse_select(bContext *C, float co[2], int extend, int loop) /* select sticky uvs */ if(sticky != SI_STICKY_DISABLE) { BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) { - tf= CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); if(!uvedit_face_visible(scene, ima, efa, tf)) continue; |