Compare commits
193 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 930dd9a762 | |||
| fc12f15ee4 | |||
| aaee1b5e39 | |||
| 4fef2ad448 | |||
| 726ddc71f9 | |||
| 9415d2d0c4 | |||
| bbfe3aedce | |||
| 524bda9547 | |||
| ac182bf9d9 | |||
| 05789429cf | |||
| 15482dcad6 | |||
| effe30ba69 | |||
| 1bcb7275db | |||
| 9bf0c5890f | |||
| d17c9e35d5 | |||
| 2605b54d89 | |||
| 1621bd0deb | |||
| fd6c8382ee | |||
| f177aa6467 | |||
| c29228d785 | |||
| eec4a5975c | |||
| 10902d7d4f | |||
| fcaa312616 | |||
| a713eafc95 | |||
| acc94f3baf | |||
| 710a470706 | |||
| 087cdd8169 | |||
| fd544b4ba9 | |||
| 887fac2ab1 | |||
| 5223aff0fb | |||
| 757af860be | |||
| feec92c94a | |||
| c5723f1f89 | |||
| 3e0bd9e34a | |||
| af4c8ffa82 | |||
| 866e20543d | |||
| 7d9b3445a7 | |||
| c63cb3d9dc | |||
| ae653d1d5c | |||
| 3e981e0712 | |||
| c849e9970e | |||
| 31fe74b3a7 | |||
| 56d29f212b | |||
| 6f302d33fe | |||
| 7d457f189d | |||
| b601ed911c | |||
| 3aac13eacf | |||
| c8042bed16 | |||
| d60a737ae8 | |||
| a06533392b | |||
| 3569b135bb | |||
| d1ad3b4926 | |||
| 59177020a6 | |||
| f238295c2d | |||
| 68ac5c1c8c | |||
| 9647ac5fdd | |||
| a36c87c71d | |||
| 9a053b860d | |||
| 31b3358291 | |||
| 459790624f | |||
| 664bc12c9a | |||
| bc3a3d3c8c | |||
| 83f4b2c293 | |||
| 0bd3f9d8a9 | |||
| a22a8a00a1 | |||
| 1833ae86de | |||
| 75c515691d | |||
| 4b191ff830 | |||
| dd35d0d035 | |||
| d66b34050d | |||
| 641fd1b287 | |||
| 3f48031cb4 | |||
| 142e796244 | |||
| 9c5ff9164e | |||
| 92b8d8a690 | |||
| 293856b705 | |||
| 326ec081ce | |||
| cf6e561e5a | |||
| f7f717db9e | |||
| 1f08f07d38 | |||
| b7f66680ab | |||
| 3473e5d424 | |||
| 00a8a784ec | |||
| 8443756ff5 | |||
| 35a61883e1 | |||
| 1fc9b07a2e | |||
| a4f29eb509 | |||
| 570aac5399 | |||
| cb8926155c | |||
| c8f0338ae1 | |||
| 20a19b3245 | |||
| 07900daa07 | |||
| ae0ff4f405 | |||
| 8f2e08758d | |||
| a9d1b557ed | |||
| e81a31f638 | |||
| a01202aaa7 | |||
| 81b94827ee | |||
| d8bc205b75 | |||
| 77b5fd9a5d | |||
| d64ba16bbf | |||
| c6b3d2f688 | |||
| 344f88cb05 | |||
| 1e2806095c | |||
| 2db76146a7 | |||
| 6b3fefa166 | |||
| f7111e00a4 | |||
| 8fc35c5981 | |||
| 987ec6d705 | |||
| 1d80800838 | |||
| d8d521150d | |||
| 766f787d84 | |||
| e13e09b888 | |||
| a52eb0d4b9 | |||
| 8458569bda | |||
| 6e187c3b0e | |||
| de8de44276 | |||
| a019468c4a | |||
| 9b20f21792 | |||
| dcb8738f55 | |||
| 5c0cc8dc8a | |||
| 46cd5a3809 | |||
| bc5c7f80df | |||
| 914520becb | |||
| ecce035d2d | |||
| a00912ba77 | |||
| 18952f7a4b | |||
| c47bbd0cfe | |||
| 9364930948 | |||
| 71d47a137d | |||
| de1abd6719 | |||
| 0d5ec23d1f | |||
| 506dc005f4 | |||
| 754d82428f | |||
| 81fcd18e8d | |||
| 3a41e39de8 | |||
| 1d074847b6 | |||
| 83badab7c0 | |||
| 2f49c0979f | |||
| c0d54e0a49 | |||
| 5b9cfb2d32 | |||
| 44783edf98 | |||
| 09dd45aa7a | |||
| fe085edd79 | |||
| cba832d1e6 | |||
| 58d028b4ba | |||
| e6f9974235 | |||
| 0793fcccca | |||
| 9d5b46196e | |||
| 1ccdc547a9 | |||
| 5de0153a36 | |||
| 639546574e | |||
| 882ba47de7 | |||
| ad6353995e | |||
| a95fa37d3e | |||
| 56d6a02b1b | |||
| b14a90946b | |||
| adf84d0ecf | |||
| 64c79f51db | |||
| 3bb9491fba | |||
| 046f0384f4 | |||
| 279a2c3fb2 | |||
| fa62b41622 | |||
| dfac3dbe27 | |||
| 3cdbd61e9c | |||
| ee3e46d8d1 | |||
| aeab707a92 | |||
| 0cf4b544f0 | |||
| 5129e62ed2 | |||
| fe76983fd3 | |||
| 394f74cf9e | |||
| 6d621563aa | |||
| fbbe82ebfd | |||
| fb98d8611a | |||
| 74f63c8293 | |||
| 5511405272 | |||
| 398076fdde | |||
| 0974cab1a4 | |||
| d615b466d7 | |||
| 3fa1f515ee | |||
| 7d9855c849 | |||
| 51deef0dcd | |||
| 2e068fe4a8 | |||
| 7fb4ac2634 | |||
| 497600f8d0 | |||
| 6b1e7a3546 | |||
| 8af35dc211 | |||
| 877e77c09d | |||
| 5a179983a2 | |||
| 41f7c5f6c5 | |||
| 0a61c568a6 | |||
| a22a43b927 | |||
| 3ee4ffc404 |
@@ -0,0 +1,66 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignOperands: DontAlign
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 100
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 4
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Left
|
||||
ReflowComments: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: true
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
---
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,boost-*,bugprone-*,performance-*,readability-*,portability-*,modernize-*,cppcoreguidelines-*,concurrency-*'
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,boost-*,bugprone-*,
|
||||
performance-*,readability-*,portability-*,modernize-*,cppcoreguidelines-*,
|
||||
concurrency-*,-modernize-use-trailing-return-type, -modernize-use-nodiscard,
|
||||
-readability-redundant-access-specifiers'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
AnalyzeTemporaryDtors: false
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)
|
||||
# relates to FindOpenGL module
|
||||
# and cache variables OPENGL_gl_LIBRARY, OPENGL_glu_LIBRARY
|
||||
if (POLICY CMP0072)
|
||||
cmake_policy(SET CMP0072 OLD)
|
||||
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||
endif(POLICY CMP0072)
|
||||
|
||||
find_program(CCACHE_PROGRAM ccache) #This check should occur before project()
|
||||
@@ -18,9 +18,9 @@ project(FreeCAD)
|
||||
set(PACKAGE_VERSION_NAME "Vulcan")
|
||||
set(PACKAGE_VERSION_MAJOR "0")
|
||||
set(PACKAGE_VERSION_MINOR "20")
|
||||
set(PACKAGE_VERSION_PATCH "1")
|
||||
set(PACKAGE_VERSION_PATCH "2")
|
||||
set(PACKAGE_VERSION_SUFFIX "") # either "dev" for development snapshot or "" (empty string)
|
||||
set(FREECAD_VERSION_PATCH "1") # number of patch release (e.g. "4" for the 0.18.4 release)
|
||||
set(FREECAD_VERSION_PATCH "2") # number of patch release (e.g. "4" for the 0.18.4 release)
|
||||
|
||||
set(FREECAD_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}")
|
||||
set(PACKAGE_VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}")
|
||||
|
||||
@@ -121,6 +121,10 @@ macro(SetupSalomeSMESH)
|
||||
find_package(SMESH CONFIG)
|
||||
set (SMESH_INCLUDE_DIR ${SMESH_INCLUDE_PATH})
|
||||
set(EXTERNAL_SMESH_LIBS ${SMESH_LIBRARIES})
|
||||
# If this definition is not set, linker errors will occur against SMESH on 64 bit machines.
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_definitions(-DSALOME_USE_64BIT_IDS)
|
||||
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
if(NOT SMESH_FOUND)
|
||||
message(ERROR "================\n"
|
||||
"SMESH not found.\n"
|
||||
|
||||
+32
-10
@@ -2614,15 +2614,37 @@ bool Document::saveToFile(const char* filename) const
|
||||
bool policy = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Document")->GetBool("BackupPolicy",true);
|
||||
|
||||
//realpath is canonical filename i.e. without symlink
|
||||
auto canonical_path = [](const char* filename) {
|
||||
try {
|
||||
#ifdef FC_OS_WIN32
|
||||
QString utf8Name = QString::fromUtf8(filename);
|
||||
auto realpath = fs::weakly_canonical(fs::absolute(fs::path(utf8Name.toStdWString())));
|
||||
std::string nativePath = QString::fromStdWString(realpath.native()).toStdString();
|
||||
QString utf8Name = QString::fromUtf8(filename);
|
||||
auto realpath = fs::weakly_canonical(fs::absolute(fs::path(utf8Name.toStdWString())));
|
||||
std::string nativePath = QString::fromStdWString(realpath.native()).toStdString();
|
||||
#else
|
||||
auto realpath = fs::weakly_canonical(fs::absolute(fs::path(filename)));
|
||||
std::string nativePath = realpath.native();
|
||||
auto realpath = fs::weakly_canonical(fs::absolute(fs::path(filename)));
|
||||
std::string nativePath = realpath.native();
|
||||
#endif
|
||||
// In case some folders in the path do not exist
|
||||
auto parentPath = realpath.parent_path();
|
||||
fs::create_directories(parentPath);
|
||||
|
||||
return nativePath;
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
#ifdef FC_OS_WIN32
|
||||
QString utf8Name = QString::fromUtf8(filename);
|
||||
auto parentPath = fs::absolute(fs::path(utf8Name.toStdWString())).parent_path();
|
||||
#else
|
||||
auto parentPath = fs::absolute(fs::path(filename)).parent_path();
|
||||
#endif
|
||||
fs::create_directories(parentPath);
|
||||
|
||||
return std::string(filename);
|
||||
}
|
||||
};
|
||||
|
||||
//realpath is canonical filename i.e. without symlink
|
||||
std::string nativePath = canonical_path(filename);
|
||||
|
||||
// make a tmp. file where to save the project data first and then rename to
|
||||
// the actual file name. This may be useful if overwriting an existing file
|
||||
@@ -2636,10 +2658,6 @@ bool Document::saveToFile(const char* filename) const
|
||||
Base::FileInfo tmp(fn);
|
||||
|
||||
|
||||
// In case some folders in the path do not exist
|
||||
auto parentPath = realpath.parent_path();
|
||||
fs::create_directories(parentPath);
|
||||
|
||||
// open extra scope to close ZipWriter properly
|
||||
{
|
||||
Base::ofstream file(tmp, std::ios::out | std::ios::binary);
|
||||
@@ -4225,6 +4243,10 @@ void Document::removeObject(const char* sName)
|
||||
}
|
||||
}
|
||||
|
||||
// In case the object gets deleted the pointer must be nullified
|
||||
if (tobedestroyed) {
|
||||
tobedestroyed->pcNameInDocument = nullptr;
|
||||
}
|
||||
d->objectMap.erase(pos);
|
||||
}
|
||||
|
||||
|
||||
+53
-27
@@ -96,11 +96,9 @@ DocumentObject::~DocumentObject(void)
|
||||
}
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn *DocumentObject::recompute(void)
|
||||
void DocumentObject::printInvalidLinks() const
|
||||
{
|
||||
//check if the links are valid before making the recompute
|
||||
if(!GeoFeatureGroupExtension::areLinksValid(this)) {
|
||||
#if 1
|
||||
try {
|
||||
// Get objects that have invalid link scope, and print their names.
|
||||
// Truncate the invalid object list name strings for readability, if they happen to be very long.
|
||||
std::vector<App::DocumentObject*> invalid_linkobjs;
|
||||
@@ -114,28 +112,44 @@ App::DocumentObjectExecReturn *DocumentObject::recompute(void)
|
||||
scopenames += "... ";
|
||||
break;
|
||||
}
|
||||
|
||||
scopenames += scope.first->getNameInDocument();
|
||||
scopenames += " ";
|
||||
}
|
||||
|
||||
if (objnames.length() > 80) {
|
||||
objnames += "... ";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (objnames.empty()) {
|
||||
objnames = "N/A";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
objnames.pop_back();
|
||||
}
|
||||
|
||||
if (scopenames.empty()) {
|
||||
scopenames = "N/A";
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
scopenames.pop_back();
|
||||
}
|
||||
Base::Console().Warning("%s: Link(s) to object(s) '%s' go out of the allowed scope '%s'. Instead, the linked object(s) reside within '%s'.\n", getTypeId().getName(), objnames.c_str(), getNameInDocument(), scopenames.c_str());
|
||||
#else
|
||||
return new App::DocumentObjectExecReturn("Links go out of the allowed scope", this);
|
||||
#endif
|
||||
|
||||
Base::Console().Warning("%s: Link(s) to object(s) '%s' go out of the allowed scope '%s'. Instead, the linked object(s) reside within '%s'.\n",
|
||||
getTypeId().getName(), objnames.c_str(), getNameInDocument(), scopenames.c_str());
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
e.ReportException();
|
||||
}
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn *DocumentObject::recompute()
|
||||
{
|
||||
//check if the links are valid before making the recompute
|
||||
if (!GeoFeatureGroupExtension::areLinksValid(this)) {
|
||||
printInvalidLinks();
|
||||
}
|
||||
|
||||
// set/unset the execution bit
|
||||
@@ -887,31 +901,43 @@ std::vector<std::string> DocumentObject::getSubObjects(int reason) const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::pair<App::DocumentObject *,std::string> > DocumentObject::getParents(int depth) const {
|
||||
std::vector<std::pair<App::DocumentObject *,std::string> > ret;
|
||||
if(!getNameInDocument() || !GetApplication().checkLinkDepth(depth))
|
||||
std::vector<std::pair<App::DocumentObject *,std::string>> DocumentObject::getParents(int depth) const {
|
||||
std::vector<std::pair<App::DocumentObject *, std::string>> ret;
|
||||
if (!getNameInDocument() || !GetApplication().checkLinkDepth(depth, false)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string name(getNameInDocument());
|
||||
name += ".";
|
||||
for(auto parent : getInList()) {
|
||||
if(!parent || !parent->getNameInDocument())
|
||||
continue;
|
||||
if(!parent->hasChildElement() &&
|
||||
!parent->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId()))
|
||||
continue;
|
||||
if(!parent->getSubObject(name.c_str()))
|
||||
for (auto parent : getInList()) {
|
||||
if (!parent || !parent->getNameInDocument()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto links = GetApplication().getLinksTo(parent,App::GetLinkRecursive);
|
||||
if (!parent->hasChildElement() &&
|
||||
!parent->hasExtension(GeoFeatureGroupExtension::getExtensionClassTypeId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!parent->getSubObject(name.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto links = GetApplication().getLinksTo(parent, App::GetLinkRecursive);
|
||||
links.insert(parent);
|
||||
for(auto parent : links) {
|
||||
auto parents = parent->getParents(depth+1);
|
||||
if(parents.empty())
|
||||
parents.emplace_back(parent,std::string());
|
||||
for(auto &v : parents)
|
||||
ret.emplace_back(v.first,v.second+name);
|
||||
|
||||
for (auto parent : links) {
|
||||
auto parents = parent->getParents(depth + 1);
|
||||
if (parents.empty()) {
|
||||
parents.emplace_back(parent, std::string());
|
||||
}
|
||||
|
||||
for (auto &v : parents) {
|
||||
ret.emplace_back(v.first, v.second + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -614,6 +614,9 @@ protected:
|
||||
/// get called when a property status has changed
|
||||
virtual void onPropertyStatusChanged(const Property &prop, unsigned long oldStatus) override;
|
||||
|
||||
private:
|
||||
void printInvalidLinks() const;
|
||||
|
||||
/// python object of this class and all descendent
|
||||
protected: // attributes
|
||||
Py::SmartPtr PythonObject;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
// inclution of the generated files (generated out of PropertyContainerPy.xml)
|
||||
// inclusion of the generated files (generated out of PropertyContainerPy.xml)
|
||||
#include "DocumentObjectExtensionPy.h"
|
||||
#include "DocumentObjectExtensionPy.cpp"
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ void DocumentObserverPython::slotCreatedDocument(const App::Document& Doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
Base::pyCall(pyCreatedDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -137,7 +137,7 @@ void DocumentObserverPython::slotDeletedDocument(const App::Document& Doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
Base::pyCall(pyDeletedDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -151,7 +151,7 @@ void DocumentObserverPython::slotRelabelDocument(const App::Document& Doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
Base::pyCall(pyRelabelDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -165,7 +165,7 @@ void DocumentObserverPython::slotActivateDocument(const App::Document& Doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
Base::pyCall(pyActivateDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -179,7 +179,7 @@ void DocumentObserverPython::slotUndoDocument(const App::Document& Doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
Base::pyCall(pyUndoDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -194,7 +194,7 @@ void DocumentObserverPython::slotRedoDocument(const App::Document& Doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
Base::pyCall(pyRedoDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -260,7 +260,7 @@ void DocumentObserverPython::slotBeforeChangeDocument(const App::Document& Doc,
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = Doc.getPropertyName(&Prop);
|
||||
@@ -280,7 +280,7 @@ void DocumentObserverPython::slotChangedDocument(const App::Document& Doc, const
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(Doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(Doc).getPyObject()));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = Doc.getPropertyName(&Prop);
|
||||
@@ -300,7 +300,7 @@ void DocumentObserverPython::slotCreatedObject(const App::DocumentObject& Obj)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::DocumentObject&>(Obj).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
|
||||
Base::pyCall(pyCreatedObject.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -314,7 +314,7 @@ void DocumentObserverPython::slotDeletedObject(const App::DocumentObject& Obj)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::DocumentObject&>(Obj).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
|
||||
Base::pyCall(pyDeletedObject.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -329,7 +329,7 @@ void DocumentObserverPython::slotBeforeChangeObject(const App::DocumentObject& O
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::DocumentObject&>(Obj).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = Obj.getPropertyName(&Prop);
|
||||
@@ -350,7 +350,7 @@ void DocumentObserverPython::slotChangedObject(const App::DocumentObject& Obj,
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::DocumentObject&>(Obj).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = Obj.getPropertyName(&Prop);
|
||||
@@ -370,7 +370,7 @@ void DocumentObserverPython::slotRecomputedObject(const App::DocumentObject& Obj
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::DocumentObject&>(Obj).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::DocumentObject&>(Obj).getPyObject()));
|
||||
Base::pyCall(pyRecomputedObject.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -384,7 +384,7 @@ void DocumentObserverPython::slotRecomputedDocument(const App::Document& doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
|
||||
Base::pyCall(pyRecomputedDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -398,7 +398,7 @@ void DocumentObserverPython::slotBeforeRecomputeDocument(const App::Document& do
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
|
||||
Base::pyCall(pyBeforeRecomputeDocument.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -412,7 +412,7 @@ void DocumentObserverPython::slotOpenTransaction(const App::Document& doc, std::
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
|
||||
args.setItem(1, Py::String(str));
|
||||
Base::pyCall(pyOpenTransaction.ptr(),args.ptr());
|
||||
}
|
||||
@@ -427,7 +427,7 @@ void DocumentObserverPython::slotCommitTransaction(const App::Document& doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
|
||||
Base::pyCall(pyCommitTransaction.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -441,7 +441,7 @@ void DocumentObserverPython::slotAbortTransaction(const App::Document& doc)
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
|
||||
Base::pyCall(pyAbortTransaction.ptr(),args.ptr());
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
@@ -456,7 +456,7 @@ void DocumentObserverPython::slotAppendDynamicProperty(const App::Property& Prop
|
||||
try {
|
||||
auto container = Prop.getContainer();
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(container->getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(container->getPyObject()));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = container->getPropertyName(&Prop);
|
||||
@@ -477,7 +477,7 @@ void DocumentObserverPython::slotRemoveDynamicProperty(const App::Property& Prop
|
||||
try {
|
||||
auto container = Prop.getContainer();
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(container->getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(container->getPyObject()));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = container->getPropertyName(&Prop);
|
||||
@@ -498,7 +498,7 @@ void DocumentObserverPython::slotChangePropertyEditor(const App::Document &, con
|
||||
try {
|
||||
auto container = Prop.getContainer();
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(container->getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(container->getPyObject()));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = container->getPropertyName(&Prop);
|
||||
@@ -518,7 +518,7 @@ void DocumentObserverPython::slotStartSaveDocument(const App::Document& doc, con
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
|
||||
args.setItem(1, Py::String(file));
|
||||
Base::pyCall(pyStartSaveDocument.ptr(),args.ptr());
|
||||
}
|
||||
@@ -533,7 +533,7 @@ void DocumentObserverPython::slotFinishSaveDocument(const App::Document& doc, co
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::Document&>(doc).getPyObject(), true));
|
||||
args.setItem(0, Py::asObject(const_cast<App::Document&>(doc).getPyObject()));
|
||||
args.setItem(1, Py::String(file));
|
||||
Base::pyCall(pyFinishSaveDocument.ptr(),args.ptr());
|
||||
}
|
||||
@@ -548,7 +548,7 @@ void DocumentObserverPython::slotBeforeAddingDynamicExtension(const App::Extensi
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::ExtensionContainer&>(extcont).getPyObject()));
|
||||
args.setItem(0, Py::asObject(const_cast<App::ExtensionContainer&>(extcont).getPyObject()));
|
||||
args.setItem(1, Py::String(extension));
|
||||
Base::pyCall(pyBeforeAddingDynamicExtension.ptr(),args.ptr());
|
||||
}
|
||||
@@ -563,7 +563,7 @@ void DocumentObserverPython::slotAddedDynamicExtension(const App::ExtensionConta
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(const_cast<App::ExtensionContainer&>(extcont).getPyObject()));
|
||||
args.setItem(0, Py::asObject(const_cast<App::ExtensionContainer&>(extcont).getPyObject()));
|
||||
args.setItem(1, Py::String(extension));
|
||||
Base::pyCall(pyAddedDynamicExtension.ptr(),args.ptr());
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
// inclution of the generated files (generated out of PropertyContainerPy.xml)
|
||||
// inclusion of the generated files (generated out of PropertyContainerPy.xml)
|
||||
#include <App/ExtensionPy.h>
|
||||
#include <App/ExtensionPy.cpp>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <boost/iostreams/device/array.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
|
||||
// inclution of the generated files (generated out of PropertyContainerPy.xml)
|
||||
// inclusion of the generated files (generated out of PropertyContainerPy.xml)
|
||||
#include "PropertyContainerPy.h"
|
||||
#include "PropertyContainerPy.cpp"
|
||||
|
||||
|
||||
@@ -1034,7 +1034,6 @@ PyObject *PropertyLinkSub::getPyObject(void)
|
||||
Py::Tuple tup(2);
|
||||
Py::List list(static_cast<int>(_cSubList.size()));
|
||||
if (_pcLinkSub) {
|
||||
_pcLinkSub->getPyObject();
|
||||
tup[0] = Py::asObject(_pcLinkSub->getPyObject());
|
||||
for(unsigned int i = 0;i<_cSubList.size(); i++)
|
||||
list[i] = Py::String(_cSubList[i]);
|
||||
|
||||
@@ -194,9 +194,12 @@ void Transaction::addObjectNew(TransactionalObject *Obj)
|
||||
auto pos = index.find(Obj);
|
||||
if (pos != index.end()) {
|
||||
if (pos->second->status == TransactionObject::Del) {
|
||||
delete pos->second;
|
||||
delete pos->first;
|
||||
// first remove the item from the container before deleting it
|
||||
auto second = pos->second;
|
||||
auto first = pos->first;
|
||||
index.erase(pos);
|
||||
delete second;
|
||||
delete first;
|
||||
}
|
||||
else {
|
||||
pos->second->status = TransactionObject::New;
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
#include "Builder3D.h"
|
||||
#include "Console.h"
|
||||
#include "Exception.h"
|
||||
#include "FileInfo.h"
|
||||
#include "Matrix.h"
|
||||
#include "Stream.h"
|
||||
#include "Tools.h"
|
||||
|
||||
|
||||
@@ -320,7 +322,8 @@ void Builder3D::saveToLog()
|
||||
void Builder3D::saveToFile(const char* FileName)
|
||||
{
|
||||
result << "} ";
|
||||
std::ofstream file(FileName);
|
||||
Base::FileInfo fi(FileName);
|
||||
Base::ofstream file(fi);
|
||||
if(!file)
|
||||
throw FileException("Builder3D::saveToFile(): Can not open file...");
|
||||
|
||||
|
||||
@@ -266,7 +266,13 @@ std::stringstream &LogLevel::prefix(std::stringstream &str, const char *src, int
|
||||
PyFrameObject* frame = PyEval_GetFrame();
|
||||
if (frame) {
|
||||
line = PyFrame_GetLineNumber(frame);
|
||||
#if PY_VERSION_HEX < 0x030b0000
|
||||
src = PyUnicode_AsUTF8(frame->f_code->co_filename);
|
||||
#else
|
||||
PyCodeObject* code = PyFrame_GetCode(frame);
|
||||
src = PyUnicode_AsUTF8(code->co_filename);
|
||||
Py_DECREF(code);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (print_src && src && src[0]) {
|
||||
|
||||
@@ -524,6 +524,7 @@ void InterpreterSingleton::addPythonPath(const char* Path)
|
||||
list.append(Py::String(Path));
|
||||
}
|
||||
|
||||
#if PY_VERSION_HEX < 0x030b0000
|
||||
const char* InterpreterSingleton::init(int argc,char *argv[])
|
||||
{
|
||||
if (!Py_IsInitialized()) {
|
||||
@@ -566,6 +567,61 @@ const char* InterpreterSingleton::init(int argc,char *argv[])
|
||||
PyGILStateLocker lock;
|
||||
return Py_EncodeLocale(Py_GetPath(),nullptr);
|
||||
}
|
||||
#else
|
||||
namespace {
|
||||
void initInterpreter(int argc,char *argv[])
|
||||
{
|
||||
PyStatus status;
|
||||
PyConfig config;
|
||||
PyConfig_InitPythonConfig(&config);
|
||||
|
||||
status = PyConfig_SetBytesArgv(&config, argc, argv);
|
||||
if (PyStatus_Exception(status)) {
|
||||
throw Base::RuntimeError("Failed to set config");
|
||||
}
|
||||
|
||||
status = Py_InitializeFromConfig(&config);
|
||||
if (PyStatus_Exception(status)) {
|
||||
throw Base::RuntimeError("Failed to init from config");
|
||||
}
|
||||
|
||||
PyConfig_Clear(&config);
|
||||
|
||||
Py_Initialize();
|
||||
const char* virtualenv = getenv("VIRTUAL_ENV");
|
||||
if (virtualenv) {
|
||||
PyRun_SimpleString(
|
||||
"# Check for virtualenv, and activate if present.\n"
|
||||
"# See https://virtualenv.pypa.io/en/latest/userguide/#using-virtualenv-without-bin-python\n"
|
||||
"import os\n"
|
||||
"import sys\n"
|
||||
"base_path = os.getenv(\"VIRTUAL_ENV\")\n"
|
||||
"if not base_path is None:\n"
|
||||
" activate_this = os.path.join(base_path, \"bin\", \"activate_this.py\")\n"
|
||||
" exec(open(activate_this).read(), {'__file__':activate_this})\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
const char* InterpreterSingleton::init(int argc,char *argv[])
|
||||
{
|
||||
try {
|
||||
if (!Py_IsInitialized()) {
|
||||
initInterpreter(argc, argv);
|
||||
|
||||
PythonStdOutput::init_type();
|
||||
this->_global = PyEval_SaveThread();
|
||||
}
|
||||
|
||||
PyGILStateLocker lock;
|
||||
return Py_EncodeLocale(Py_GetPath(),nullptr);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
e.ReportException();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void InterpreterSingleton::replaceStdOutput()
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "Persistence.h"
|
||||
#include "Writer.h"
|
||||
|
||||
// inclution of the generated files (generated By PersitancePy.xml)
|
||||
// inclusion of the generated files (generated By PersitancePy.xml)
|
||||
#include "PersistencePy.h"
|
||||
#include "PersistencePy.cpp"
|
||||
|
||||
|
||||
@@ -60,7 +60,11 @@ PyObjectBase::PyObjectBase(void* p,PyTypeObject *T)
|
||||
, baseProxy(nullptr)
|
||||
, attrDict(nullptr)
|
||||
{
|
||||
#if PY_VERSION_HEX < 0x030b0000
|
||||
Py_TYPE(this) = T;
|
||||
#else
|
||||
this->ob_type = T;
|
||||
#endif
|
||||
_Py_NewReference(this);
|
||||
#ifdef FC_LOGPYOBJECTS
|
||||
Base::Console().Log("PyO+: %s (%p)\n",T->tp_name, this);
|
||||
|
||||
+9
-1
@@ -15,8 +15,10 @@ is provided on an as is basis, without warranties of any kind.
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <compile.h>
|
||||
#include <eval.h>
|
||||
#include <frameobject.h>
|
||||
#if PY_VERSION_HEX < 0x030b0000
|
||||
#include <eval.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -310,7 +312,13 @@ void PP_Fetch_Error_Text()
|
||||
if(!frame)
|
||||
return;
|
||||
int line = PyFrame_GetLineNumber(frame);
|
||||
#if PY_VERSION_HEX < 0x030b0000
|
||||
const char *file = PyUnicode_AsUTF8(frame->f_code->co_filename);
|
||||
#else
|
||||
PyCodeObject* code = PyFrame_GetCode(frame);
|
||||
const char *file = PyUnicode_AsUTF8(code->co_filename);
|
||||
Py_DECREF(code);
|
||||
#endif
|
||||
#ifdef FC_OS_WIN32
|
||||
const char *_f = strstr(file, "\\src\\");
|
||||
#else
|
||||
|
||||
+22
-12
@@ -339,17 +339,22 @@ class FileInfo;
|
||||
class ofstream : public std::ofstream
|
||||
{
|
||||
public:
|
||||
ofstream() = default;
|
||||
ofstream(const FileInfo& fi, ios_base::openmode mode =
|
||||
std::ios::out | std::ios::trunc)
|
||||
#ifdef _MSC_VER
|
||||
: std::ofstream(fi.toStdWString().c_str(), mode)
|
||||
: std::ofstream(fi.toStdWString().c_str(), mode) {}
|
||||
#else
|
||||
: std::ofstream(fi.filePath().c_str(), mode)
|
||||
: std::ofstream(fi.filePath().c_str(), mode) {}
|
||||
#endif
|
||||
~ofstream() override = default;
|
||||
void open(const FileInfo& fi, ios_base::openmode mode =
|
||||
std::ios::out | std::ios::trunc) {
|
||||
#ifdef _MSC_VER
|
||||
std::ofstream::open(fi.toStdWString().c_str(), mode);
|
||||
#else
|
||||
std::ofstream::open(fi.filePath().c_str(), mode);
|
||||
#endif
|
||||
{
|
||||
}
|
||||
virtual ~ofstream()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -362,17 +367,22 @@ public:
|
||||
class ifstream : public std::ifstream
|
||||
{
|
||||
public:
|
||||
ifstream() = default;
|
||||
ifstream(const FileInfo& fi, ios_base::openmode mode =
|
||||
std::ios::in)
|
||||
#ifdef _MSC_VER
|
||||
: std::ifstream(fi.toStdWString().c_str(), mode)
|
||||
: std::ifstream(fi.toStdWString().c_str(), mode) {}
|
||||
#else
|
||||
: std::ifstream(fi.filePath().c_str(), mode)
|
||||
: std::ifstream(fi.filePath().c_str(), mode) {}
|
||||
#endif
|
||||
~ifstream() override = default;
|
||||
void open(const FileInfo& fi, ios_base::openmode mode =
|
||||
std::ios::in) {
|
||||
#ifdef _MSC_VER
|
||||
std::ifstream::open(fi.toStdWString().c_str(), mode);
|
||||
#else
|
||||
std::ifstream::open(fi.filePath().c_str(), mode);
|
||||
#endif
|
||||
{
|
||||
}
|
||||
virtual ~ifstream()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+12
-12
@@ -87,9 +87,9 @@ const char* UnitsApi::getDescription(UnitSystem system)
|
||||
}
|
||||
}
|
||||
|
||||
UnitsSchemaPtr UnitsApi::createSchema(UnitSystem s)
|
||||
UnitsSchemaPtr UnitsApi::createSchema(UnitSystem system)
|
||||
{
|
||||
switch (s) {
|
||||
switch (system) {
|
||||
case UnitSystem::SI1:
|
||||
return std::make_unique<UnitsSchemaInternal>();
|
||||
case UnitSystem::SI2:
|
||||
@@ -115,14 +115,14 @@ UnitsSchemaPtr UnitsApi::createSchema(UnitSystem s)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UnitsApi::setSchema(UnitSystem s)
|
||||
void UnitsApi::setSchema(UnitSystem system)
|
||||
{
|
||||
if (UserPrefSystem) {
|
||||
UserPrefSystem->resetSchemaUnits(); // for schemas changed the Quantity constants
|
||||
}
|
||||
|
||||
UserPrefSystem = createSchema(s);
|
||||
currentSystem = s;
|
||||
UserPrefSystem = createSchema(system);
|
||||
currentSystem = system;
|
||||
|
||||
// for wrong value fall back to standard schema
|
||||
if (!UserPrefSystem) {
|
||||
@@ -133,21 +133,21 @@ void UnitsApi::setSchema(UnitSystem s)
|
||||
UserPrefSystem->setSchemaUnits(); // if necessary a unit schema can change the constants in Quantity (e.g. mi=1.8km rather then 1.6km).
|
||||
}
|
||||
|
||||
QString UnitsApi::toString(const Base::Quantity& q, const QuantityFormat& f)
|
||||
QString UnitsApi::toString(const Base::Quantity& quantity, const QuantityFormat& format)
|
||||
{
|
||||
QString value = QString::fromLatin1("'%1 %2'").arg(q.getValue(), 0, f.toFormat(), f.precision)
|
||||
.arg(q.getUnit().getString());
|
||||
QString value = QString::fromLatin1("'%1 %2'").arg(quantity.getValue(), 0, format.toFormat(), format.precision)
|
||||
.arg(quantity.getUnit().getString());
|
||||
return value;
|
||||
}
|
||||
|
||||
QString UnitsApi::toNumber(const Base::Quantity& q, const QuantityFormat& f)
|
||||
QString UnitsApi::toNumber(const Base::Quantity& quantity, const QuantityFormat& format)
|
||||
{
|
||||
return toNumber(q.getValue(), f);
|
||||
return toNumber(quantity.getValue(), format);
|
||||
}
|
||||
|
||||
QString UnitsApi::toNumber(double d, const QuantityFormat& f)
|
||||
QString UnitsApi::toNumber(double value, const QuantityFormat& format)
|
||||
{
|
||||
QString number = QString::fromLatin1("%1").arg(d, 0, f.toFormat(), f.precision);
|
||||
QString number = QString::fromLatin1("%1").arg(value, 0, format.toFormat(), format.precision);
|
||||
return number;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QString>
|
||||
|
||||
#include "UnitsSchemaInternal.h"
|
||||
#include <cmath>
|
||||
|
||||
|
||||
using namespace Base;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QString>
|
||||
|
||||
#include "UnitsSchemaMKS.h"
|
||||
#include <cmath>
|
||||
|
||||
|
||||
using namespace Base;
|
||||
|
||||
@@ -203,7 +203,7 @@ bool BitmapFactoryInst::findPixmapInCache(const char* name, QPixmap& px) const
|
||||
|
||||
QIcon BitmapFactoryInst::iconFromTheme(const char* name, const QIcon& fallback)
|
||||
{
|
||||
QString iconName = QString::fromLatin1(name);
|
||||
QString iconName = QString::fromUtf8(name);
|
||||
QIcon icon = QIcon::fromTheme(iconName, fallback);
|
||||
if (icon.isNull()) {
|
||||
QPixmap px = pixmap(name);
|
||||
|
||||
@@ -657,8 +657,15 @@ void Command::printPyCaller() {
|
||||
if(!frame)
|
||||
return;
|
||||
int line = PyFrame_GetLineNumber(frame);
|
||||
#if PY_VERSION_HEX < 0x030b0000
|
||||
const char *file = PyUnicode_AsUTF8(frame->f_code->co_filename);
|
||||
printCaller(file?file:"<no file>",line);
|
||||
#else
|
||||
PyCodeObject* code = PyFrame_GetCode(frame);
|
||||
const char* file = PyUnicode_AsUTF8(code->co_filename);
|
||||
printCaller(file?file:"<no file>",line);
|
||||
Py_DECREF(code);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Command::printCaller(const char *file, int line) {
|
||||
|
||||
+42
-5
@@ -87,6 +87,37 @@ using namespace Gui;
|
||||
using Gui::Dialog::DlgSettingsImageImp;
|
||||
namespace bp = boost::placeholders;
|
||||
|
||||
namespace {
|
||||
// A helper class to open a transaction when changing properties of view providers.
|
||||
// It uses the same parameter key as the PropertyView to control the behaviour.
|
||||
class TransactionView {
|
||||
Gui::Document* document;
|
||||
|
||||
public:
|
||||
static bool getDefault() {
|
||||
auto hGrp = App::GetApplication().GetParameterGroupByPath(
|
||||
"User parameter:BaseApp/Preferences/PropertyView");
|
||||
return hGrp->GetBool("AutoTransactionView", false);
|
||||
}
|
||||
TransactionView(Gui::Document* doc, const char* name, bool enable = getDefault())
|
||||
: document(doc)
|
||||
{
|
||||
if (document && enable) {
|
||||
document->openCommand(name);
|
||||
}
|
||||
else {
|
||||
document = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~TransactionView() {
|
||||
if (document) {
|
||||
document->commitCommand();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
DEF_STD_CMD_AC(StdOrthographicCamera)
|
||||
@@ -863,6 +894,7 @@ StdCmdToggleVisibility::StdCmdToggleVisibility()
|
||||
void StdCmdToggleVisibility::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg);
|
||||
TransactionView transaction(getActiveGuiDocument(), QT_TRANSLATE_NOOP("Command", "Toggle visibility"));
|
||||
Selection().setVisible(SelectionSingleton::VisToggle);
|
||||
}
|
||||
|
||||
@@ -898,16 +930,21 @@ void StdCmdToggleSelectability::activated(int iMsg)
|
||||
std::vector<App::DocumentObject*> sel = Selection().getObjectsOfType
|
||||
(App::DocumentObject::getClassTypeId(), (*it)->getName());
|
||||
|
||||
if (sel.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (std::vector<App::DocumentObject*>::const_iterator ft=sel.begin();ft!=sel.end();++ft) {
|
||||
ViewProvider *pr = pcDoc->getViewProviderByName((*ft)->getNameInDocument());
|
||||
TransactionView transaction(pcDoc, QT_TRANSLATE_NOOP("Command", "Toggle selectability"));
|
||||
|
||||
for (const auto & ft : sel) {
|
||||
ViewProvider *pr = pcDoc->getViewProviderByName(ft->getNameInDocument());
|
||||
if (pr && pr->isDerivedFrom(ViewProviderGeometryObject::getClassTypeId())){
|
||||
if (static_cast<ViewProviderGeometryObject*>(pr)->Selectable.getValue())
|
||||
doCommand(Gui,"Gui.getDocument(\"%s\").getObject(\"%s\").Selectable=False"
|
||||
, (*it)->getName(), (*ft)->getNameInDocument());
|
||||
, (*it)->getName(), ft->getNameInDocument());
|
||||
else
|
||||
doCommand(Gui,"Gui.getDocument(\"%s\").getObject(\"%s\").Selectable=True"
|
||||
, (*it)->getName(), (*ft)->getNameInDocument());
|
||||
, (*it)->getName(), ft->getNameInDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3702,7 +3739,7 @@ public:
|
||||
|
||||
addCommand(new StdTreeDrag(),cmds.size());
|
||||
addCommand(new StdTreeSelection(),cmds.size());
|
||||
};
|
||||
}
|
||||
virtual const char* className() const {return "StdCmdTreeViewActions";}
|
||||
};
|
||||
|
||||
|
||||
@@ -367,16 +367,17 @@ Action * StdCmdToolBarMenu::createAction()
|
||||
|
||||
class FilterStatusBar : public QObject
|
||||
{
|
||||
// Q_OBJECT
|
||||
// Q_OBJECT
|
||||
|
||||
public:
|
||||
FilterStatusBar(Action * action):QObject(action) {this->action = action;}
|
||||
// virtual ~FilterStatusBar() {}
|
||||
FilterStatusBar(Action* action) :QObject(action) { this->action = action; }
|
||||
// virtual ~FilterStatusBar() {}
|
||||
protected:
|
||||
Action * action;
|
||||
bool eventFilter(QObject *obj, QEvent *event)
|
||||
Action* action;
|
||||
bool eventFilter(QObject* obj, QEvent* event) override
|
||||
{
|
||||
if (getMainWindow()->findChild<QStatusBar *>() != nullptr && obj == getMainWindow()->statusBar() && ((event->type() == QEvent::Hide) || (event->type() == QEvent::Show))) {
|
||||
if (getMainWindow() && getMainWindow()->findChild<QStatusBar*>() && obj == getMainWindow()->statusBar() &&
|
||||
((event->type() == QEvent::Hide) || (event->type() == QEvent::Show))) {
|
||||
this->action->setChecked(getMainWindow()->statusBar()->isVisible());
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -259,6 +259,8 @@ void DlgGeneralImp::loadSettings()
|
||||
model->sort(0);
|
||||
|
||||
int current = getMainWindow()->iconSize().width();
|
||||
current = hGrp->GetInt("ToolbarIconSize", current);
|
||||
ui->toolbarIconSize->clear();
|
||||
ui->toolbarIconSize->addItem(tr("Small (%1px)").arg(16), QVariant((int)16));
|
||||
ui->toolbarIconSize->addItem(tr("Medium (%1px)").arg(24), QVariant((int)24));
|
||||
ui->toolbarIconSize->addItem(tr("Large (%1px)").arg(32), QVariant((int)32));
|
||||
@@ -270,6 +272,7 @@ void DlgGeneralImp::loadSettings()
|
||||
}
|
||||
ui->toolbarIconSize->setCurrentIndex(index);
|
||||
|
||||
ui->treeMode->clear();
|
||||
ui->treeMode->addItem(tr("Combo View"));
|
||||
ui->treeMode->addItem(tr("TreeView and PropertyView"));
|
||||
ui->treeMode->addItem(tr("Both"));
|
||||
@@ -308,6 +311,7 @@ void DlgGeneralImp::loadSettings()
|
||||
}
|
||||
|
||||
// now add all unique items
|
||||
ui->StyleSheets->clear();
|
||||
ui->StyleSheets->addItem(tr("No style sheet"), QString::fromLatin1(""));
|
||||
for (QMap<QString, QString>::iterator it = cssFiles.begin(); it != cssFiles.end(); ++it) {
|
||||
ui->StyleSheets->addItem(it.key(), it.value());
|
||||
@@ -333,7 +337,8 @@ void DlgGeneralImp::loadSettings()
|
||||
}
|
||||
}
|
||||
|
||||
if (index > -1) ui->StyleSheets->setCurrentIndex(index);
|
||||
if (index > -1)
|
||||
ui->StyleSheets->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void DlgGeneralImp::changeEvent(QEvent *e)
|
||||
|
||||
@@ -328,6 +328,11 @@ void DlgCustomKeyboardImp::on_editShortcut_textChanged(const QString& sc)
|
||||
Command* cmd = cCmdMgr.getCommandByName(name.constData());
|
||||
if (cmd && !cmd->getAction()) {
|
||||
Base::Console().Warning("Command %s not in use yet\n", cmd->getName());
|
||||
QMessageBox::warning(this,
|
||||
tr("Command not in use yet"),
|
||||
tr("The command '%1' is loaded but not in use yet, so it can't be assigned a new shortcut.\n"
|
||||
"To enable assignment, please make '%2' the active workbench").arg(data.toString(),ui->categoryBox->currentText()),
|
||||
QMessageBox::Ok);
|
||||
ui->buttonAssign->setEnabled(false); // command not in use
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -409,7 +409,7 @@ void DlgMacroExecuteImp::on_deleteButton_clicked()
|
||||
MacroItem * mitem = static_cast<MacroItem *>(item);
|
||||
|
||||
if (mitem->systemWide) {
|
||||
QMessageBox::critical(qApp->activeWindow(), QObject::tr("Delete macro"),
|
||||
QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Delete macro"),
|
||||
QObject::tr("Not allowed to delete system-wide macros"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -176,15 +176,24 @@ QTabWidget* DlgPreferencesImp::createTabForGroup(const std::string &groupName)
|
||||
*/
|
||||
void DlgPreferencesImp::createPageInGroup(QTabWidget *tabWidget, const std::string &pageName)
|
||||
{
|
||||
PreferencePage* page = WidgetFactory().createPreferencePage(pageName.c_str());
|
||||
if (page) {
|
||||
tabWidget->addTab(page, page->windowTitle());
|
||||
page->loadSettings();
|
||||
page->setProperty("GroupName", tabWidget->property("GroupName"));
|
||||
page->setProperty("PageName", QVariant(QString::fromStdString(pageName)));
|
||||
try {
|
||||
PreferencePage* page = WidgetFactory().createPreferencePage(pageName.c_str());
|
||||
if (page) {
|
||||
tabWidget->addTab(page, page->windowTitle());
|
||||
page->loadSettings();
|
||||
page->setProperty("GroupName", tabWidget->property("GroupName"));
|
||||
page->setProperty("PageName", QVariant(QString::fromStdString(pageName)));
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("%s is not a preference page\n", pageName.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning("%s is not a preference page\n", pageName.c_str());
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("Base exception thrown for '%s'\n", pageName.c_str());
|
||||
e.ReportException();
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
Base::Console().Error("C++ exception thrown for '%s' (%s)\n", pageName.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,13 +53,15 @@ void ExpressionBindingPy::init_type()
|
||||
|
||||
PyObject *ExpressionBindingPy::PyMake(struct _typeobject *, PyObject * args, PyObject *)
|
||||
{
|
||||
Py::Tuple tuple(args);
|
||||
PyObject* pyObj;
|
||||
if (!PyArg_ParseTuple(args,"O", &pyObj))
|
||||
return nullptr;
|
||||
|
||||
ExpressionBinding* expr = nullptr;
|
||||
PythonWrapper wrap;
|
||||
wrap.loadWidgetsModule();
|
||||
|
||||
QWidget* obj = dynamic_cast<QWidget*>(wrap.toQObject(tuple.getItem(0)));
|
||||
QWidget* obj = dynamic_cast<QWidget*>(wrap.toQObject(Py::Object(pyObj)));
|
||||
if (obj) {
|
||||
do {
|
||||
QuantitySpinBox* sb = qobject_cast<QuantitySpinBox*>(obj);
|
||||
|
||||
+24
-30
@@ -92,6 +92,27 @@ void FileDialog::onSelectedFilter(const QString& /*filter*/)
|
||||
}
|
||||
}
|
||||
|
||||
QList<QUrl> FileDialog::fetchSidebarUrls()
|
||||
{
|
||||
QStringList list;
|
||||
list << QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
||||
list << QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
list << QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
|
||||
list << QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
|
||||
list << getWorkingDirectory();
|
||||
list << restoreLocation();
|
||||
list << QDir::currentPath();
|
||||
|
||||
QList<QUrl> urls;
|
||||
for (const auto& it : list) {
|
||||
if (QFileInfo::exists(it)) {
|
||||
urls << QUrl::fromLocalFile(it);
|
||||
}
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
bool FileDialog::hasSuffix(const QString& ext) const
|
||||
{
|
||||
QRegExp rx(QString::fromLatin1("\\*.(%1)\\W").arg(ext));
|
||||
@@ -181,18 +202,9 @@ QString FileDialog::getSaveFileName (QWidget * parent, const QString & caption,
|
||||
// before showing the file dialog.
|
||||
QString file;
|
||||
if (DialogOptions::dontUseNativeFileDialog()) {
|
||||
QList<QUrl> urls;
|
||||
QList<QUrl> urls = fetchSidebarUrls();
|
||||
|
||||
options |= QFileDialog::DontUseNativeDialog;
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation));
|
||||
urls << QUrl::fromLocalFile(getWorkingDirectory());
|
||||
urls << QUrl::fromLocalFile(restoreLocation());
|
||||
urls << QUrl::fromLocalFile(QDir::currentPath());
|
||||
|
||||
FileDialog dlg(parent);
|
||||
dlg.setWindowTitle(windowTitle);
|
||||
@@ -263,18 +275,9 @@ QString FileDialog::getOpenFileName(QWidget * parent, const QString & caption, c
|
||||
|
||||
QString file;
|
||||
if (DialogOptions::dontUseNativeFileDialog()) {
|
||||
QList<QUrl> urls;
|
||||
QList<QUrl> urls = fetchSidebarUrls();
|
||||
|
||||
options |= QFileDialog::DontUseNativeDialog;
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation));
|
||||
urls << QUrl::fromLocalFile(getWorkingDirectory());
|
||||
urls << QUrl::fromLocalFile(restoreLocation());
|
||||
urls << QUrl::fromLocalFile(QDir::currentPath());
|
||||
|
||||
FileDialog dlg(parent);
|
||||
dlg.setWindowTitle(windowTitle);
|
||||
@@ -324,18 +327,9 @@ QStringList FileDialog::getOpenFileNames (QWidget * parent, const QString & capt
|
||||
|
||||
QStringList files;
|
||||
if (DialogOptions::dontUseNativeFileDialog()) {
|
||||
QList<QUrl> urls;
|
||||
QList<QUrl> urls = fetchSidebarUrls();
|
||||
|
||||
options |= QFileDialog::DontUseNativeDialog;
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MusicLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
|
||||
urls << QUrl::fromLocalFile(QStandardPaths::writableLocation(QStandardPaths::MoviesLocation));
|
||||
urls << QUrl::fromLocalFile(getWorkingDirectory());
|
||||
urls << QUrl::fromLocalFile(restoreLocation());
|
||||
urls << QUrl::fromLocalFile(QDir::currentPath());
|
||||
|
||||
FileDialog dlg(parent);
|
||||
dlg.setWindowTitle(windowTitle);
|
||||
|
||||
@@ -86,6 +86,7 @@ private Q_SLOTS:
|
||||
|
||||
private:
|
||||
bool hasSuffix(const QString&) const;
|
||||
static QList<QUrl> fetchSidebarUrls();
|
||||
static QString workingDirectory;
|
||||
};
|
||||
|
||||
|
||||
+34
-22
@@ -2,26 +2,34 @@
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48"
|
||||
height="48"
|
||||
id="svg23883"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.43+devel"
|
||||
inkscape:version="0.46"
|
||||
version="1.0"
|
||||
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
|
||||
sodipodi:docname="edit-cut.svg"
|
||||
inkscape:export-filename="/home/garrett/edit-cut.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
inkscape:export-ydpi="90"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs23885">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective70" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2269">
|
||||
@@ -362,14 +370,26 @@
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
gridempspacing="4"
|
||||
gridtolerance="0.5px"
|
||||
inkscape:window-width="1011"
|
||||
inkscape:window-height="1110"
|
||||
inkscape:window-x="378"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-height="818"
|
||||
inkscape:window-x="177"
|
||||
inkscape:window-y="30"
|
||||
stroke="#a40000"
|
||||
inkscape:showpageshadow="false" />
|
||||
inkscape:showpageshadow="false">
|
||||
<inkscape:grid
|
||||
id="GridFromPre046Settings"
|
||||
type="xygrid"
|
||||
originx="0px"
|
||||
originy="0px"
|
||||
spacingx="1px"
|
||||
spacingy="1px"
|
||||
color="#0000ff"
|
||||
empcolor="#0000ff"
|
||||
opacity="0.2"
|
||||
empopacity="0.4"
|
||||
empspacing="4" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata23888">
|
||||
<rdf:RDF>
|
||||
@@ -392,7 +412,7 @@
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.0/" />
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
@@ -400,21 +420,13 @@
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-nc-sa/2.0/">
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Attribution" />
|
||||
<cc:prohibits
|
||||
rdf:resource="http://web.resource.org/cc/CommercialUse" />
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -652,6 +652,10 @@ void Placement::bindObject()
|
||||
ui->yawAngle ->bind(App::ObjectIdentifier::parse(obj, propertyName + std::string(".Rotation.Yaw")));
|
||||
ui->pitchAngle->bind(App::ObjectIdentifier::parse(obj, propertyName + std::string(".Rotation.Pitch")));
|
||||
ui->rollAngle ->bind(App::ObjectIdentifier::parse(obj, propertyName + std::string(".Rotation.Roll")));
|
||||
|
||||
ui->yawAngle->evaluateExpression();
|
||||
ui->pitchAngle->evaluateExpression();
|
||||
ui->rollAngle->evaluateExpression();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -563,6 +563,14 @@ void PythonDebugger::hideDebugMarker(const QString& fn)
|
||||
}
|
||||
}
|
||||
|
||||
#if PY_VERSION_HEX < 0x030900B1
|
||||
static PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
|
||||
{
|
||||
Py_INCREF(frame->f_code);
|
||||
return frame->f_code;
|
||||
}
|
||||
#endif
|
||||
|
||||
// http://www.koders.com/cpp/fidBA6CD8A0FE5F41F1464D74733D9A711DA257D20B.aspx?s=PyEval_SetTrace
|
||||
// http://code.google.com/p/idapython/source/browse/trunk/python.cpp
|
||||
// http://www.koders.com/cpp/fid191F7B13CF73133935A7A2E18B7BF43ACC6D1784.aspx?s=PyEval_SetTrace
|
||||
@@ -578,7 +586,9 @@ int PythonDebugger::tracer_callback(PyObject *obj, PyFrameObject *frame, int wha
|
||||
|
||||
//no = frame->f_tstate->recursion_depth;
|
||||
//std::string funcname = PyString_AsString(frame->f_code->co_name);
|
||||
QString file = QString::fromUtf8(PyUnicode_AsUTF8(frame->f_code->co_filename));
|
||||
PyCodeObject* code = PyFrame_GetCode(frame);
|
||||
QString file = QString::fromUtf8(PyUnicode_AsUTF8(code->co_filename));
|
||||
Py_DECREF(code);
|
||||
switch (what) {
|
||||
case PyTrace_CALL:
|
||||
self->depth++;
|
||||
@@ -592,7 +602,10 @@ int PythonDebugger::tracer_callback(PyObject *obj, PyFrameObject *frame, int wha
|
||||
//PyObject *str;
|
||||
//str = PyObject_Str(frame->f_code->co_filename);
|
||||
//no = frame->f_lineno;
|
||||
int line = PyCode_Addr2Line(frame->f_code, frame->f_lasti);
|
||||
PyCodeObject* f_code = PyFrame_GetCode(frame);
|
||||
int f_lasti = PyFrame_GetLineNumber(frame);
|
||||
int line = PyCode_Addr2Line(f_code, f_lasti);
|
||||
Py_DECREF(f_code);
|
||||
//if (str) {
|
||||
// Base::Console().Message("PROFILING: %s:%d\n", PyString_AsString(str), frame->f_lineno);
|
||||
// Py_DECREF(str);
|
||||
|
||||
+119
-11
@@ -23,6 +23,9 @@
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <limits>
|
||||
# include <unordered_map>
|
||||
# include <list>
|
||||
# include <QApplication>
|
||||
# include <QDir>
|
||||
# include <QIcon>
|
||||
# include <QWidget>
|
||||
@@ -121,6 +124,7 @@ PyTypeObject** SbkPySide2_QtWidgetsTypes=nullptr;
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/QuantityPy.h>
|
||||
|
||||
@@ -149,7 +153,7 @@ PyObject* toPythonFuncQuantityTyped(Base::Quantity cpx) {
|
||||
|
||||
PyObject* toPythonFuncQuantity(const void* cpp)
|
||||
{
|
||||
return toPythonFuncQuantityTyped(*reinterpret_cast<const Base::Quantity*>(cpp));
|
||||
return toPythonFuncQuantityTyped(*static_cast<const Base::Quantity*>(cpp));
|
||||
}
|
||||
|
||||
void toCppPointerConvFuncQuantity(PyObject* pyobj,void* cpp)
|
||||
@@ -217,6 +221,108 @@ void registerTypes()
|
||||
// --------------------------------------------------------
|
||||
|
||||
namespace Gui {
|
||||
template<typename qttype>
|
||||
PyTypeObject *getPyTypeObjectForTypeName();
|
||||
|
||||
/*!
|
||||
* \brief The WrapperManager class
|
||||
* This is a helper class that records the Python wrappers of a QObject and invalidates
|
||||
* them when the QObject is about to be destroyed.
|
||||
* This is to make sure that if the Python wrapper doesn't own the QObject it won't be notified
|
||||
* if the QObject is destroyed.
|
||||
* \code
|
||||
* ui = Gui.UiLoader()
|
||||
* lineedit = ui.createWidget("QLineEdit")
|
||||
* lineedit.deleteLater()
|
||||
* # Make sure this won't crash
|
||||
* lineedit.show()
|
||||
* \endcode
|
||||
*/
|
||||
class WrapperManager : public QObject
|
||||
{
|
||||
std::unordered_map<QObject*, std::list<Py::Object>> wrappers;
|
||||
|
||||
public:
|
||||
static WrapperManager& instance()
|
||||
{
|
||||
static WrapperManager singleton;
|
||||
return singleton;
|
||||
}
|
||||
/*!
|
||||
* \brief addQObject
|
||||
* \param obj
|
||||
* \param pyobj
|
||||
* Add the QObject and its Python wrapper to the list.
|
||||
*/
|
||||
void addQObject(QObject* obj, PyObject* pyobj)
|
||||
{
|
||||
if (wrappers.find(obj) == wrappers.end()) {
|
||||
QObject::connect(obj, &QObject::destroyed, this, &WrapperManager::destroyed);
|
||||
}
|
||||
|
||||
auto& pylist = wrappers[obj];
|
||||
if (std::find_if(pylist.cbegin(), pylist.cend(), [pyobj](const Py::Object& py) { return py.ptr() == pyobj; }) == pylist.end()) {
|
||||
pylist.emplace_back(pyobj);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
* \brief destroyed
|
||||
* \param obj
|
||||
* The listed QObject is about to be destroyed. Invalidate its Python wrappers now.
|
||||
*/
|
||||
void destroyed(QObject* obj = nullptr)
|
||||
{
|
||||
if (obj) {
|
||||
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
|
||||
auto key = wrappers.find(obj);
|
||||
if (key != wrappers.end()) {
|
||||
Base::PyGILStateLocker lock;
|
||||
for (const auto& it : key->second) {
|
||||
auto value = it.ptr();
|
||||
Shiboken::Object::setValidCpp(reinterpret_cast<SbkObject*>(value), false);
|
||||
}
|
||||
|
||||
wrappers.erase(key);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void clear()
|
||||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
wrappers.clear();
|
||||
}
|
||||
void wrapQApplication()
|
||||
{
|
||||
// We have to explicitly hold a reference to the wrapper of the QApplication
|
||||
// as otherwise it can happen that when running the gc the program crashes
|
||||
// The code snippet below caused a crash on older versions:
|
||||
// mw = Gui.getMainWindow()
|
||||
// mw.style()
|
||||
// import gc
|
||||
// gc.collect()
|
||||
#if defined (HAVE_SHIBOKEN) && defined(HAVE_PYSIDE)
|
||||
PyTypeObject * type = getPyTypeObjectForTypeName<QApplication>();
|
||||
if (type) {
|
||||
auto sbk_type = reinterpret_cast<SbkObjectType*>(type);
|
||||
std::string typeName = "QApplication";
|
||||
PyObject* pyobj = Shiboken::Object::newObject(sbk_type, qApp, false, false, typeName.c_str());
|
||||
addQObject(qApp, pyobj);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
WrapperManager()
|
||||
{
|
||||
connect(QApplication::instance(), &QCoreApplication::aboutToQuit,
|
||||
this, &WrapperManager::clear);
|
||||
wrapQApplication();
|
||||
}
|
||||
~WrapperManager() = default;
|
||||
};
|
||||
|
||||
template<typename qttype>
|
||||
Py::Object qt_wrapInstance(qttype object, const char* className,
|
||||
const char* shiboken, const char* pyside,
|
||||
@@ -353,19 +459,19 @@ QObject* PythonWrapper::toQObject(const Py::Object& pyobject)
|
||||
if (Shiboken::Object::checkType(pyobject.ptr())) {
|
||||
SbkObject* sbkobject = reinterpret_cast<SbkObject *>(pyobject.ptr());
|
||||
void* cppobject = Shiboken::Object::cppPointer(sbkobject, type);
|
||||
return reinterpret_cast<QObject*>(cppobject);
|
||||
return static_cast<QObject*>(cppobject);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Access shiboken2/PySide2 via Python
|
||||
//
|
||||
void* ptr = qt_getCppPointer(pyobject, "shiboken2", "getCppPointer");
|
||||
return reinterpret_cast<QObject*>(ptr);
|
||||
return static_cast<QObject*>(ptr);
|
||||
#endif
|
||||
|
||||
#if 0 // Unwrapping using sip/PyQt
|
||||
#ifdef HAVE_PYQT // Unwrapping using sip/PyQt
|
||||
void* ptr = qt_getCppPointer(pyobject, "sip", "unwrapinstance");
|
||||
return reinterpret_cast<QObject*>(ptr);
|
||||
return static_cast<QObject*>(ptr);
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
@@ -379,14 +485,14 @@ QGraphicsItem* PythonWrapper::toQGraphicsItem(PyObject* pyPtr)
|
||||
if (Shiboken::Object::checkType(pyPtr)) {
|
||||
SbkObject* sbkobject = reinterpret_cast<SbkObject*>(pyPtr);
|
||||
void* cppobject = Shiboken::Object::cppPointer(sbkobject, type);
|
||||
return reinterpret_cast<QGraphicsItem*>(cppobject);
|
||||
return static_cast<QGraphicsItem*>(cppobject);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Access shiboken2/PySide2 via Python
|
||||
//
|
||||
void* ptr = qt_getCppPointer(Py::asObject(pyPtr), "shiboken2", "getCppPointer");
|
||||
return reinterpret_cast<QGraphicsItem*>(ptr);
|
||||
return static_cast<QGraphicsItem*>(ptr);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
@@ -435,7 +541,7 @@ QIcon *PythonWrapper::toQIcon(PyObject *pyobj)
|
||||
if (Shiboken::Object::checkType(pyobj)) {
|
||||
SbkObject* sbkobject = reinterpret_cast<SbkObject *>(pyobj);
|
||||
void* cppobject = Shiboken::Object::cppPointer(sbkobject, type);
|
||||
return reinterpret_cast<QIcon*>(cppobject);
|
||||
return static_cast<QIcon*>(cppobject);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -466,7 +572,7 @@ QDir* PythonWrapper::toQDir(PyObject* pyobj)
|
||||
if (Shiboken::Object::checkType(pyobj)) {
|
||||
SbkObject* sbkobject = reinterpret_cast<SbkObject*>(pyobj);
|
||||
void* cppobject = Shiboken::Object::cppPointer(sbkobject, type);
|
||||
return reinterpret_cast<QDir*>(cppobject);
|
||||
return static_cast<QDir*>(cppobject);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -491,6 +597,7 @@ Py::Object PythonWrapper::fromQObject(QObject* object, const char* className)
|
||||
else
|
||||
typeName = object->metaObject()->className();
|
||||
PyObject* pyobj = Shiboken::Object::newObject(sbk_type, object, false, false, typeName.c_str());
|
||||
WrapperManager::instance().addQObject(object, pyobj);
|
||||
return Py::asObject(pyobj);
|
||||
}
|
||||
throw Py::RuntimeError("Failed to wrap object");
|
||||
@@ -499,7 +606,7 @@ Py::Object PythonWrapper::fromQObject(QObject* object, const char* className)
|
||||
//
|
||||
return qt_wrapInstance<QObject*>(object, className, "shiboken2", "PySide2.QtCore", "wrapInstance");
|
||||
#endif
|
||||
#if 0 // Unwrapping using sip/PyQt
|
||||
#ifdef HAVE_PYQT // Unwrapping using sip/PyQt
|
||||
Q_UNUSED(className);
|
||||
return qt_wrapInstance<QObject*>(object, "QObject", "sip", "PyQt5.QtCore", "wrapinstance");
|
||||
#endif
|
||||
@@ -519,6 +626,7 @@ Py::Object PythonWrapper::fromQWidget(QWidget* widget, const char* className)
|
||||
else
|
||||
typeName = widget->metaObject()->className();
|
||||
PyObject* pyobj = Shiboken::Object::newObject(sbk_type, widget, false, false, typeName.c_str());
|
||||
WrapperManager::instance().addQObject(widget, pyobj);
|
||||
return Py::asObject(pyobj);
|
||||
}
|
||||
throw Py::RuntimeError("Failed to wrap widget");
|
||||
@@ -529,7 +637,7 @@ Py::Object PythonWrapper::fromQWidget(QWidget* widget, const char* className)
|
||||
return qt_wrapInstance<QWidget*>(widget, className, "shiboken2", "PySide2.QtWidgets", "wrapInstance");
|
||||
#endif
|
||||
|
||||
#if 0 // Unwrapping using sip/PyQt
|
||||
#ifdef HAVE_PYQT // Unwrapping using sip/PyQt
|
||||
Q_UNUSED(className);
|
||||
return qt_wrapInstance<QWidget*>(widget, "QWidget", "sip", "PyQt5.QtWidgets", "wrapinstance");
|
||||
#endif
|
||||
|
||||
@@ -412,6 +412,13 @@ QString Gui::QuantitySpinBox::expressionText() const
|
||||
return QString();
|
||||
}
|
||||
|
||||
void QuantitySpinBox::evaluateExpression()
|
||||
{
|
||||
if (isBound() && getExpression()) {
|
||||
showValidExpression(Number::SetIfNumber);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::QuantitySpinBox::setNumberExpression(App::NumberExpression* expr)
|
||||
{
|
||||
lineEdit()->setText(getUserString(expr->getQuantity()));
|
||||
|
||||
@@ -108,6 +108,7 @@ public:
|
||||
|
||||
/// Gets the expression as a string
|
||||
QString expressionText() const;
|
||||
void evaluateExpression();
|
||||
|
||||
/// Set the number portion selected
|
||||
void selectNumber();
|
||||
|
||||
@@ -256,8 +256,6 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev)
|
||||
newmode = NavigationStyle::SELECTION;
|
||||
break;
|
||||
case BUTTON1DOWN|BUTTON2DOWN:
|
||||
newmode = NavigationStyle::PANNING;
|
||||
break;
|
||||
case BUTTON3DOWN:
|
||||
newmode = NavigationStyle::PANNING;
|
||||
break;
|
||||
@@ -273,6 +271,13 @@ SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev)
|
||||
break;
|
||||
|
||||
default:
|
||||
// Reset mode to SELECTION when button 3 is released
|
||||
// This stops the DRAGGING when button 3 is released but SHIFT is still pressed
|
||||
// This stops the ZOOMING when button 3 is released but CTRL is still pressed
|
||||
if ((curmode == NavigationStyle::DRAGGING || curmode == NavigationStyle::ZOOMING)
|
||||
&& !this->button3down) {
|
||||
newmode = NavigationStyle::SELECTION;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2357,8 +2357,14 @@ PyObject *SelectionSingleton::sGetCompleteSelection(PyObject * /*self*/, PyObjec
|
||||
sel = Selection().getCompleteSelection(toEnum(resolve));
|
||||
|
||||
Py::List list;
|
||||
for (std::vector<SelectionSingleton::SelObj>::iterator it = sel.begin(); it != sel.end(); ++it) {
|
||||
list.append(Py::asObject(it->pObject->getPyObject()));
|
||||
for (const auto & it : sel) {
|
||||
SelectionObject obj(SelectionChanges(SelectionChanges::AddSelection,
|
||||
it.DocName,
|
||||
it.FeatName,
|
||||
it.SubName,
|
||||
it.TypeName,
|
||||
it.x, it.y, it.z));
|
||||
list.append(Py::asObject(obj.getPyObject()));
|
||||
}
|
||||
return Py::new_reference_to(list);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ void SoFCOffscreenRenderer::writeToImageFile(const char* filename, const char* c
|
||||
QByteArray ba;
|
||||
QBuffer buffer(&ba);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
image.save(&buffer, "JPG");
|
||||
image.save(&buffer, "JPG", 90);
|
||||
writeJPEGComment(com, ba);
|
||||
|
||||
QFile file(QString::fromUtf8(filename));
|
||||
|
||||
@@ -639,7 +639,7 @@ void AboutDialog::showLibraryInformation()
|
||||
out << "</ul>\n</body>\n</html>";
|
||||
textField->setHtml(html);
|
||||
|
||||
connect(textField, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkActivated(QUrl)));
|
||||
connect(textField, &QTextBrowser::anchorClicked, this, &AboutDialog::linkActivated);
|
||||
}
|
||||
|
||||
void AboutDialog::showCollectionInformation()
|
||||
|
||||
@@ -114,7 +114,7 @@ SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev)
|
||||
const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
|
||||
const int button = event->getButton();
|
||||
const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
|
||||
SbBool canOpenPopupMenu = false;
|
||||
SbBool shortRMBclick = false;
|
||||
|
||||
switch (button) {
|
||||
case SoMouseButtonEvent::BUTTON1:
|
||||
@@ -144,7 +144,7 @@ SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev)
|
||||
float dci = float(QApplication::doubleClickInterval())/1000.0f;
|
||||
// time between press and release event
|
||||
if (tmp.getValue() < dci) {
|
||||
canOpenPopupMenu = true;
|
||||
shortRMBclick = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,14 +156,16 @@ SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev)
|
||||
processed = true;
|
||||
}
|
||||
else if (!press && (curmode == NavigationStyle::DRAGGING)) {
|
||||
if (!viewer->isEditing() && canOpenPopupMenu) {
|
||||
// If we are in drag mode but mouse hasn't been moved open the context-menu
|
||||
if (this->isPopupMenuEnabled()) {
|
||||
this->openPopupMenu(event->getPosition());
|
||||
if (shortRMBclick) {
|
||||
newmode = NavigationStyle::IDLE;
|
||||
if (!viewer->isEditing()) {
|
||||
// If we are in drag mode but mouse hasn't been moved open the context-menu
|
||||
if (this->isPopupMenuEnabled()) {
|
||||
this->openPopupMenu(event->getPosition());
|
||||
}
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
newmode = NavigationStyle::IDLE;
|
||||
processed = true;
|
||||
}
|
||||
break;
|
||||
case SoMouseButtonEvent::BUTTON3:
|
||||
|
||||
@@ -813,12 +813,24 @@ void View3DInventorViewer::checkGroupOnTop(const SelectionChanges &Reason) {
|
||||
|
||||
std::vector<ViewProvider*> groups;
|
||||
auto grpVp = vp;
|
||||
std::set<ViewProvider*> visited;
|
||||
for(auto childVp=vp;;childVp=grpVp) {
|
||||
auto grp = App::GeoFeatureGroupExtension::getGroupOfObject(childVp->getObject());
|
||||
if(!grp || !grp->getNameInDocument()) break;
|
||||
if(!grp || !grp->getNameInDocument()) {
|
||||
break;
|
||||
}
|
||||
|
||||
grpVp = dynamic_cast<ViewProviderDocumentObject*>(
|
||||
Application::Instance->getViewProvider(grp));
|
||||
if(!grpVp) break;
|
||||
if(!grpVp) {
|
||||
break;
|
||||
}
|
||||
|
||||
// avoid endless-loops
|
||||
if (!visited.insert(childVp).second) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto childRoot = grpVp->getChildRoot();
|
||||
auto modeSwitch = grpVp->getModeSwitch();
|
||||
auto idx = modeSwitch->whichChild.getValue();
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# include <sstream>
|
||||
#endif
|
||||
|
||||
// inclution of the generated files (generated out of PropertyContainerPy.xml)
|
||||
// inclusion of the generated files (generated out of PropertyContainerPy.xml)
|
||||
#include "ViewProviderExtensionPy.h"
|
||||
#include "ViewProviderExtensionPy.cpp"
|
||||
#include "ViewProviderDocumentObject.h"
|
||||
|
||||
+11
-11
@@ -59,10 +59,10 @@ Check if the object is visible.</UserDocu>
|
||||
</Methode>
|
||||
<Methode Name="canDragObject">
|
||||
<Documentation>
|
||||
<UserDocu>canDragObject(obj) -> bool\n
|
||||
<UserDocu>canDragObject(obj=None) -> bool\n
|
||||
Check whether the child object can be removed by dragging.
|
||||
If 'obj' is not given, check without filter by any particular object.\n
|
||||
obj : App.DocumentObject\n Object to be dragged. Optional.</UserDocu>
|
||||
obj : App.DocumentObject or None\n Object to be dragged.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="dragObject">
|
||||
@@ -74,25 +74,25 @@ obj : App.DocumentObject\n Object to be dragged.</UserDocu>
|
||||
</Methode>
|
||||
<Methode Name="canDropObject" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>canDropObject(obj, owner, subname, elem) -> bool\n
|
||||
<UserDocu>canDropObject(obj=None, owner=None, subname, elem=None) -> bool\n
|
||||
Check whether the child object can be added by dropping.
|
||||
If 'obj' is not given, check without filter by any particular object.\n
|
||||
obj : App.DocumentObject\n Object to be dropped. Optional.
|
||||
owner : App.DocumentObject\n Parent object of the dropping object. Optional.
|
||||
obj : App.DocumentObject or None\n Object to be dropped.
|
||||
owner : App.DocumentObject or None\n Parent object of the dropping object.
|
||||
subname : str\n Subname reference to the dropping object. Optional.
|
||||
elem : sequence of str\n Non-objects subelements selected when the object is
|
||||
being dropped. Optional.</UserDocu>
|
||||
elem : sequence of str or None\n Non-objects subelements selected when the object is
|
||||
being dropped.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="dropObject" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>dropObject(obj, owner, subname, elem) -> str\n
|
||||
<UserDocu>dropObject(obj, owner=None, subname, elem=None) -> str\n
|
||||
Add a child object by dropping.\n
|
||||
obj : App.DocumentObject\n Object to be dropped.
|
||||
owner : App.DocumentObject\n Parent object of the dropping object. Optional.
|
||||
owner : App.DocumentObject or None\n Parent object of the dropping object.
|
||||
subname : str\n Subname reference to the dropping object. Optional.
|
||||
elem : sequence of str\n Non-objects subelements selected when the object is
|
||||
being dropped. Optional.</UserDocu>
|
||||
elem : sequence of str or None\n Non-objects subelements selected when the object is
|
||||
being dropped.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="canDragAndDropObject">
|
||||
|
||||
@@ -161,17 +161,23 @@ PyObject* ViewProviderPy::isVisible(PyObject *args)
|
||||
|
||||
PyObject* ViewProviderPy::canDragObject(PyObject *args)
|
||||
{
|
||||
PyObject *obj = nullptr;
|
||||
if (!PyArg_ParseTuple(args, "|O!", &App::DocumentObjectPy::Type, &obj))
|
||||
PyObject *obj = Py_None;
|
||||
if (!PyArg_ParseTuple(args, "|O", &obj))
|
||||
return nullptr;
|
||||
|
||||
PY_TRY {
|
||||
bool ret;
|
||||
if (!obj)
|
||||
if (obj == Py_None) {
|
||||
ret = getViewProviderPtr()->canDragObjects();
|
||||
else
|
||||
}
|
||||
else {
|
||||
if (!PyObject_TypeCheck(obj, &App::DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "'obj' must be a App::DocumentObject or None");
|
||||
return nullptr;
|
||||
}
|
||||
ret = getViewProviderPtr()->canDragObject(
|
||||
static_cast<App::DocumentObjectPy*>(obj)->getDocumentObjectPtr());
|
||||
}
|
||||
|
||||
return Py::new_reference_to(Py::Boolean(ret));
|
||||
}
|
||||
@@ -180,14 +186,12 @@ PyObject* ViewProviderPy::canDragObject(PyObject *args)
|
||||
|
||||
PyObject* ViewProviderPy::canDropObject(PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *obj = nullptr;
|
||||
PyObject *owner = nullptr;
|
||||
PyObject *pyElements = nullptr;
|
||||
PyObject *obj = Py_None;
|
||||
PyObject *owner = Py_None;
|
||||
PyObject *pyElements = Py_None;
|
||||
const char *subname = nullptr;
|
||||
static char* kwlist[] = {"obj","owner","subname","elem",nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "|O!O!sO", kwlist,
|
||||
&App::DocumentObjectPy::Type,&obj, &App::DocumentObjectPy::Type, &owner,
|
||||
&subname, &pyElements))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "|OOsO", kwlist, &obj, &owner, &subname, &pyElements))
|
||||
return nullptr;
|
||||
|
||||
PY_TRY {
|
||||
@@ -195,18 +199,30 @@ PyObject* ViewProviderPy::canDropObject(PyObject *args, PyObject *kw)
|
||||
App::DocumentObject* pcObject;
|
||||
App::DocumentObject* pcOwner = nullptr;
|
||||
App::PropertyStringList elements;
|
||||
if (!obj && (owner || pyElements || subname)) {
|
||||
if (obj == Py_None && (owner != Py_None || pyElements != Py_None || subname)) {
|
||||
PyErr_SetString(PyExc_ValueError, "'obj' must be specified if 'owner', 'subname' or 'elem' is given");
|
||||
return nullptr;
|
||||
}
|
||||
if(!obj) {
|
||||
if(obj == Py_None) {
|
||||
ret = getViewProviderPtr()->canDropObjects();
|
||||
return Py::new_reference_to(Py::Boolean(ret));
|
||||
}
|
||||
pcObject = static_cast<App::DocumentObjectPy*>(obj)->getDocumentObjectPtr();
|
||||
if (owner)
|
||||
else {
|
||||
if (!PyObject_TypeCheck(obj, &App::DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "'obj' must be a App::DocumentObject or None");
|
||||
return nullptr;
|
||||
}
|
||||
pcObject = static_cast<App::DocumentObjectPy*>(obj)->getDocumentObjectPtr();
|
||||
}
|
||||
|
||||
if (owner != Py_None) {
|
||||
if (!PyObject_TypeCheck(owner, &App::DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "'owner' must be a App::DocumentObject or None");
|
||||
return nullptr;
|
||||
}
|
||||
pcOwner = static_cast<App::DocumentObjectPy*>(owner)->getDocumentObjectPtr();
|
||||
if (pyElements) {
|
||||
}
|
||||
if (pyElements != Py_None) {
|
||||
try {
|
||||
elements.setPyObject(pyElements);
|
||||
}
|
||||
@@ -238,22 +254,27 @@ PyObject* ViewProviderPy::canDragAndDropObject(PyObject *args)
|
||||
PyObject* ViewProviderPy::dropObject(PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyObject *obj;
|
||||
PyObject *owner = nullptr;
|
||||
PyObject *pyElements = nullptr;
|
||||
PyObject *owner = Py_None;
|
||||
PyObject *pyElements = Py_None;
|
||||
const char *subname = nullptr;
|
||||
static char* kwlist[] = {"obj","owner","subname","elem",nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|O!sO", kwlist,
|
||||
&App::DocumentObjectPy::Type,&obj, &App::DocumentObjectPy::Type, &owner,
|
||||
&subname, &pyElements))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "O!|OsO", kwlist,
|
||||
&App::DocumentObjectPy::Type, &obj, &owner, &subname, &pyElements))
|
||||
return nullptr;
|
||||
|
||||
PY_TRY {
|
||||
auto pcObject = static_cast<App::DocumentObjectPy*>(obj)->getDocumentObjectPtr();
|
||||
App::DocumentObject *pcOwner = nullptr;
|
||||
App::PropertyStringList elements;
|
||||
if (owner)
|
||||
if (owner != Py_None) {
|
||||
if (!PyObject_TypeCheck(owner, &App::DocumentObjectPy::Type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "'owner' must be a App::DocumentObject or None");
|
||||
return nullptr;
|
||||
}
|
||||
pcOwner = static_cast<App::DocumentObjectPy*>(owner)->getDocumentObjectPtr();
|
||||
if (pyElements) {
|
||||
}
|
||||
|
||||
if (pyElements != Py_None) {
|
||||
try {
|
||||
elements.setPyObject(pyElements);
|
||||
}
|
||||
|
||||
@@ -747,6 +747,7 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent *) {
|
||||
case MA_Expression:
|
||||
if(contextIndex == currentIndex()) {
|
||||
Base::FlagToggler<> flag(binding);
|
||||
closeEditor();
|
||||
openEditor(contextIndex);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
# ***************************************************************************
|
||||
|
||||
import os
|
||||
import functools
|
||||
import shutil
|
||||
import stat
|
||||
import tempfile
|
||||
@@ -573,7 +574,7 @@ class CommandAddonManager:
|
||||
self.startup_sequence.append(self.load_macro_metadata)
|
||||
selection = pref.GetString("SelectedAddon", "")
|
||||
if selection:
|
||||
self.startup_sequence.insert(2, lambda: self.select_addon(selection))
|
||||
self.startup_sequence.insert(2, functools.partial(self.select_addon, selection))
|
||||
pref.SetString("SelectedAddon", "")
|
||||
if ADDON_MANAGER_DEVELOPER_MODE:
|
||||
self.startup_sequence.append(self.validate)
|
||||
@@ -954,16 +955,17 @@ class CommandAddonManager:
|
||||
def __init__(self, repo: Addon, all_repos: List[Addon]):
|
||||
|
||||
deps = Addon.Dependencies()
|
||||
repo_name_dict = dict()
|
||||
repo_name_dict = {}
|
||||
for r in all_repos:
|
||||
repo_name_dict[repo.name] = r
|
||||
repo_name_dict[repo.display_name] = r
|
||||
repo_name_dict[r.name] = r
|
||||
repo_name_dict[r.display_name] = r
|
||||
|
||||
repo.walk_dependency_tree(repo_name_dict, deps)
|
||||
|
||||
self.external_addons = []
|
||||
for dep in deps.required_external_addons:
|
||||
if dep.status() == Addon.Status.NOT_INSTALLED:
|
||||
self.external_addons.append(dep)
|
||||
self.external_addons.append(dep.name)
|
||||
|
||||
# Now check the loaded addons to see if we are missing an internal workbench:
|
||||
wbs = [wb.lower() for wb in FreeCADGui.listWorkbenches()]
|
||||
@@ -1131,10 +1133,10 @@ class CommandAddonManager:
|
||||
|
||||
self.dependency_dialog.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.Yes
|
||||
).clicked.connect(lambda: self.dependency_dialog_yes_clicked(repo))
|
||||
).clicked.connect(functools.partial(self.dependency_dialog_yes_clicked, repo))
|
||||
self.dependency_dialog.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.Ignore
|
||||
).clicked.connect(lambda: self.dependency_dialog_ignore_clicked(repo))
|
||||
).clicked.connect(functools.partial(self.dependency_dialog_ignore_clicked, repo))
|
||||
self.dependency_dialog.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.Cancel
|
||||
).setDefault(True)
|
||||
@@ -1176,7 +1178,7 @@ class CommandAddonManager:
|
||||
# No missing deps, just install
|
||||
self.install(repo)
|
||||
|
||||
def dependency_dialog_yes_clicked(self, repo: Addon) -> None:
|
||||
def dependency_dialog_yes_clicked(self, installing_repo: Addon) -> None:
|
||||
# Get the lists out of the dialog:
|
||||
addons = []
|
||||
for row in range(self.dependency_dialog.listWidgetAddons.count()):
|
||||
@@ -1201,15 +1203,15 @@ class CommandAddonManager:
|
||||
addons, python_required, python_optional
|
||||
)
|
||||
self.dependency_installation_worker.no_python_exe.connect(
|
||||
lambda: self.no_python_exe(repo)
|
||||
functools.partial(self.no_python_exe, installing_repo)
|
||||
)
|
||||
self.dependency_installation_worker.no_pip.connect(
|
||||
lambda command: self.no_pip(command, repo)
|
||||
functools.partial(self.no_pip, repo=installing_repo)
|
||||
)
|
||||
self.dependency_installation_worker.failure.connect(
|
||||
self.dependency_installation_failure
|
||||
)
|
||||
self.dependency_installation_worker.success.connect(lambda: self.install(repo))
|
||||
self.dependency_installation_worker.success.connect(functools.partial(self.install,installing_repo))
|
||||
self.dependency_installation_dialog = QtWidgets.QMessageBox(
|
||||
QtWidgets.QMessageBox.Information,
|
||||
translate("AddonsInstaller", "Installing dependencies"),
|
||||
@@ -1373,10 +1375,10 @@ class CommandAddonManager:
|
||||
self.update_all_worker.progress_made.connect(self.update_progress_bar)
|
||||
self.update_all_worker.status_message.connect(self.show_information)
|
||||
self.update_all_worker.success.connect(
|
||||
lambda repo: self.subupdates_succeeded.append(repo)
|
||||
self.subupdates_succeeded.append
|
||||
)
|
||||
self.update_all_worker.failure.connect(
|
||||
lambda repo: self.subupdates_failed.append(repo)
|
||||
self.subupdates_failed.append
|
||||
)
|
||||
self.update_all_worker.finished.connect(self.on_update_all_completed)
|
||||
self.update_all_worker.start()
|
||||
|
||||
@@ -240,7 +240,17 @@ if HAVE_QTNETWORK:
|
||||
) # This may still be QNetworkProxy.NoProxy
|
||||
elif userProxyCheck:
|
||||
host, _, port_string = proxy_string.rpartition(":")
|
||||
port = 0 if not port_string else int(port_string)
|
||||
try:
|
||||
port = 0 if not port_string else int(port_string)
|
||||
except ValueError:
|
||||
FreeCAD.Console.PrintError(
|
||||
translate(
|
||||
"AddonsInstaller",
|
||||
"Failed to convert the specified proxy port '{}' to a port number",
|
||||
).format(port_string)
|
||||
+ "\n"
|
||||
)
|
||||
port = 0
|
||||
# For now assume an HttpProxy, but eventually this should be a parameter
|
||||
proxy = QtNetwork.QNetworkProxy(
|
||||
QtNetwork.QNetworkProxy.HttpProxy, host, port
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -261,7 +261,7 @@ class Macro(object):
|
||||
FreeCAD.Console.PrintWarning(
|
||||
translate(
|
||||
"AddonsInstaller",
|
||||
"Unable to open macro code URL {rawcodeurl}",
|
||||
"Unable to open macro code URL {}",
|
||||
).format(self.raw_code_url)
|
||||
+ "\n"
|
||||
)
|
||||
|
||||
@@ -972,7 +972,10 @@ class InstallWorkbenchWorker(QtCore.QThread):
|
||||
return
|
||||
|
||||
basedir = FreeCAD.getUserAppDataDir()
|
||||
moddir = basedir + os.sep + "Mod"
|
||||
if basedir[-1:] != os.sep:
|
||||
moddir = basedir + os.sep + "Mod"
|
||||
else:
|
||||
moddir = basedir + "Mod"
|
||||
if not os.path.exists(moddir):
|
||||
os.makedirs(moddir)
|
||||
target_dir = moddir + os.sep + self.repo.name
|
||||
@@ -1551,7 +1554,12 @@ class UpdateMetadataCacheWorker(QtCore.QThread):
|
||||
repo.display_name
|
||||
)
|
||||
)
|
||||
f = io.StringIO(data.data().decode("utf8"))
|
||||
try:
|
||||
f = io.StringIO(data.data().decode("utf8"))
|
||||
except UnicodeDecodeError as e:
|
||||
FreeCAD.Console.PrintWarning(str(e))
|
||||
FreeCAD.Console.PrintWarning(f" in package {repo.name}\n")
|
||||
return
|
||||
while True:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
@@ -1600,7 +1608,12 @@ class UpdateMetadataCacheWorker(QtCore.QThread):
|
||||
"Downloaded requirements.txt for {}",
|
||||
).format(repo.display_name)
|
||||
)
|
||||
f = io.StringIO(data.data().decode("utf8"))
|
||||
try:
|
||||
f = io.StringIO(data.data().decode("utf8"))
|
||||
except UnicodeDecodeError as e:
|
||||
FreeCAD.Console.PrintWarning(str(e))
|
||||
FreeCAD.Console.PrintWarning(f" in package {repo.name}\n")
|
||||
return
|
||||
lines = f.readlines()
|
||||
for line in lines:
|
||||
break_chars = " <>=~!+#"
|
||||
|
||||
@@ -457,7 +457,7 @@ class BuildingPart(ArchIFC.IfcProduct):
|
||||
shapes = []
|
||||
solidindex = 0
|
||||
materialstable = {}
|
||||
for child in Draft.get_group_contents(obj):
|
||||
for child in Draft.get_group_contents(obj, walls=True):
|
||||
if not Draft.get_type(child) in ["Space"]:
|
||||
if hasattr(child,'Shape') and child.Shape:
|
||||
shapes.append(child.Shape)
|
||||
@@ -660,6 +660,7 @@ class ViewProviderBuildingPart:
|
||||
self.sep.addChild(self.dst)
|
||||
self.lco = coin.SoCoordinate3()
|
||||
self.sep.addChild(self.lco)
|
||||
import PartGui # Required for "SoBrepEdgeSet" (because a BuildingPart is not a Part::FeaturePython object).
|
||||
lin = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
|
||||
if lin:
|
||||
lin.coordIndex.setValues([0,1,-1,2,3,-1,4,5,-1])
|
||||
@@ -733,7 +734,7 @@ class ViewProviderBuildingPart:
|
||||
"recursively get the colors of objects inside this BuildingPart"
|
||||
|
||||
colors = []
|
||||
for child in Draft.get_group_contents(obj):
|
||||
for child in Draft.get_group_contents(obj, walls=True):
|
||||
if not Draft.get_type(child) in ["Space"]:
|
||||
if hasattr(child,'Shape') and (hasattr(child.ViewObject,"DiffuseColor") or hasattr(child.ViewObject,"ShapeColor")):
|
||||
if hasattr(child.ViewObject,"DiffuseColor") and len(child.ViewObject.DiffuseColor) == len(child.Shape.Faces):
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#* *
|
||||
#*****************************************************************************
|
||||
|
||||
import FreeCAD,ArchCommands
|
||||
import FreeCAD, Draft, ArchCommands
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
@@ -61,12 +61,11 @@ def cutComponentwithPlane(archObject, cutPlane, sideFace):
|
||||
if cutVolume:
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::Feature","CutVolume")
|
||||
obj.Shape = cutVolume
|
||||
obj.ViewObject.ShapeColor = (1.00,0.00,0.00)
|
||||
obj.ViewObject.Transparency = 75
|
||||
if "Additions" in archObject.Object.PropertiesList:
|
||||
ArchCommands.removeComponents(obj,archObject.Object)
|
||||
ArchCommands.removeComponents(obj, archObject.Object) # Also changes the obj colors.
|
||||
return None
|
||||
else:
|
||||
Draft.format_object(obj, archObject.Object)
|
||||
cutObj = FreeCAD.ActiveDocument.addObject("Part::Cut","CutPlane")
|
||||
cutObj.Base = archObject.Object
|
||||
cutObj.Tool = obj
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
#***************************************************************************
|
||||
#* Copyright (c) 2020 Yorik van Havre <yorik@uncreated.net> *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* 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 Library General Public License for more details. *
|
||||
#* *
|
||||
#* You should have received a copy of the GNU Library 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 *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
"""View providers and UI elements for the Ifc classes."""
|
||||
|
||||
import FreeCAD, ArchIFC
|
||||
|
||||
@@ -1053,6 +1053,7 @@ class _ViewProviderSectionPlane:
|
||||
self.drawstyle = coin.SoDrawStyle()
|
||||
self.drawstyle.style = coin.SoDrawStyle.LINES
|
||||
self.lcoords = coin.SoCoordinate3()
|
||||
import PartGui # Required for "SoBrepEdgeSet" (because a SectionPlane is not a Part::FeaturePython object).
|
||||
ls = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
|
||||
ls.coordIndex.setValues(0,57,[0,1,-1,2,3,4,5,-1,6,7,8,9,-1,10,11,-1,12,13,14,15,-1,16,17,18,19,-1,20,21,-1,22,23,24,25,-1,26,27,28,29,-1,30,31,-1,32,33,34,35,-1,36,37,38,39,-1,40,41,42,43,44])
|
||||
self.txtcoords = coin.SoTransform()
|
||||
|
||||
@@ -672,11 +672,13 @@ class _ViewProviderSpace(ArchComponent.ViewProviderComponent):
|
||||
if hasattr(vobj,"FirstLine"):
|
||||
scale = vobj.FirstLine.Value/vobj.FontSize.Value
|
||||
self.header.scaleFactor.setValue([scale,scale,scale])
|
||||
self.onChanged(vobj, "TextPosition")
|
||||
|
||||
elif (prop == "FirstLine"):
|
||||
if hasattr(self,"header") and hasattr(vobj,"FontSize") and hasattr(vobj,"FirstLine"):
|
||||
scale = vobj.FirstLine.Value/vobj.FontSize.Value
|
||||
self.header.scaleFactor.setValue([scale,scale,scale])
|
||||
self.onChanged(vobj, "TextPosition")
|
||||
|
||||
elif prop == "TextColor":
|
||||
if hasattr(self,"color") and hasattr(vobj,"TextColor"):
|
||||
|
||||
+54
-54
@@ -110,7 +110,7 @@ def makeStairs(baseobj=None,length=None,width=None,height=None,steps=None,name="
|
||||
stairs[i].Base = baseobjI
|
||||
|
||||
if (len(baseobjI.Shape.Edges) > 1):
|
||||
stepsI = 1 #'landing' if 'multi-edges' currently
|
||||
stepsI = 1 #'landing' if 'multi-edges' currently
|
||||
elif steps:
|
||||
stepsI = steps
|
||||
else:
|
||||
@@ -121,7 +121,7 @@ def makeStairs(baseobj=None,length=None,width=None,height=None,steps=None,name="
|
||||
additions.append(stairs[i])
|
||||
stairs[i].LastSegment = stairs[i-1]
|
||||
else:
|
||||
if len(stairs) > 1: # i.e. length >1, have a 'master' staircase created
|
||||
if len(stairs) > 1: # i.e. length >1, have a 'master' staircase created
|
||||
stairs[0].Base = stairs[1]
|
||||
i += 1
|
||||
if lenSelection > 1:
|
||||
@@ -161,25 +161,25 @@ def makeRailing(stairs):
|
||||
if side == "L":
|
||||
outlineLR = stair.OutlineLeft
|
||||
outlineLRAll = stair.OutlineLeftAll
|
||||
stairs0RailingLR = "RailingLeft" # stairs0OutlineWireLR = "OutlineWireLeft"
|
||||
stairRailingLR = "RailingLeft" # stairOutlineWireLR = "OutlineWireLeft"
|
||||
stairs0RailingLR = "RailingLeft" # stairs0OutlineWireLR = "OutlineWireLeft"
|
||||
stairRailingLR = "RailingLeft" # stairOutlineWireLR = "OutlineWireLeft"
|
||||
elif side == "R":
|
||||
outlineLR = stair.OutlineRight
|
||||
outlineLRAll = stair.OutlineRightAll
|
||||
stairs0RailingLR = "RailingRight" # stairs0OutlineWireLR = "OutlineWireRight"
|
||||
stairRailingLR = "RailingRight" # stairOutlineWireLR = "OutlineWireRight"
|
||||
stairs0RailingLR = "RailingRight" # stairs0OutlineWireLR = "OutlineWireRight"
|
||||
stairRailingLR = "RailingRight" # stairOutlineWireLR = "OutlineWireRight"
|
||||
if outlineLR or outlineLRAll:
|
||||
lrRail = ArchPipe.makePipe(baseobj=None,diameter=0,length=0,placement=None,name="Rail")
|
||||
if outlineLRAll:
|
||||
#lrRail.Base = lrRailWire # no need to set here as _Stairs will do
|
||||
setattr(stair, stairRailingLR, lrRail.Name) # setattr(stair, stairOutlineWireLR, lrRailWire.Name)
|
||||
#lrRail.Base = lrRailWire # no need to set here as _Stairs will do
|
||||
setattr(stair, stairRailingLR, lrRail.Name) # setattr(stair, stairOutlineWireLR, lrRailWire.Name)
|
||||
railList = stairs[0].Additions
|
||||
railList.append(lrRail)
|
||||
stairs[0].Additions = railList
|
||||
break
|
||||
elif outlineLR:
|
||||
#lrRail.Base = lrRailWire # no need to set here as _Stairs will do
|
||||
setattr(stair, stairRailingLR, lrRail.Name) # setattr(stair, stairOutlineWireLR, lrRailWire.Name)
|
||||
#lrRail.Base = lrRailWire # no need to set here as _Stairs will do
|
||||
setattr(stair, stairRailingLR, lrRail.Name) # setattr(stair, stairOutlineWireLR, lrRailWire.Name)
|
||||
railList = stair.Additions
|
||||
railList.append(lrRail)
|
||||
stair.Additions = railList
|
||||
@@ -188,7 +188,7 @@ def makeRailing(stairs):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
sel0 = sel[0]
|
||||
stairs = []
|
||||
if Draft.getType(sel[0]) == "Stairs": # TODO currently consider 1st selected object, then would tackle multiple objects ?
|
||||
if Draft.getType(sel[0]) == "Stairs": # TODO currently consider 1st selected object, then would tackle multiple objects ?
|
||||
stairs.append(sel0)
|
||||
if Draft.getType(sel0.Base) == "Stairs":
|
||||
stairs.append(sel0.Base)
|
||||
@@ -469,7 +469,7 @@ class _Stairs(ArchComponent.Component):
|
||||
if isinstance(edge.Curve,(Part.LineSegment,Part.Line)):
|
||||
# preparing for multi-edges landing / segment staircase
|
||||
if obj.NumberOfSteps > 1:
|
||||
self.makeStraightStairsWithLanding(obj,edge) # all cases use makeStraightStairsWithLanding()
|
||||
self.makeStraightStairsWithLanding(obj,edge) # all cases use makeStraightStairsWithLanding()
|
||||
|
||||
# preparing for multi-edges landing / segment staircase
|
||||
if obj.NumberOfSteps == 1:
|
||||
@@ -528,9 +528,9 @@ class _Stairs(ArchComponent.Component):
|
||||
|
||||
if railWireL:
|
||||
# Migration
|
||||
if Draft.getType(railingLeftObject.Base) != "Part": # None or not "Part"
|
||||
if Draft.getType(railingLeftObject.Base) != "Part": # None or not "Part"
|
||||
railingLeftWireObject = FreeCAD.ActiveDocument.addObject("Part::Feature","RailingWire")
|
||||
if railingLeftObject.Base: # if has railingLeftObject.Base but that != "Part"
|
||||
if railingLeftObject.Base: # if has railingLeftObject.Base but that != "Part"
|
||||
railingLeftObject.Document.removeObject(railingLeftObject.Base.Name) # Delete the previous Base object... # Not Using FreeCAD.ActiveDocument...
|
||||
railingLeftObject.Base = railingLeftWireObject
|
||||
# update the Base object shape
|
||||
@@ -657,7 +657,7 @@ class _Stairs(ArchComponent.Component):
|
||||
return stepWire, stepFace
|
||||
|
||||
|
||||
@staticmethod # obj become stairsObj
|
||||
@staticmethod # obj become stairsObj
|
||||
def returnOutlines(stairsObj, edges, align="Left", mode=None, widthFirstSegment=zeroMM, widthOtherSegments=[], treadThickness=zeroMM,
|
||||
railStartRiser=zeroMM, offsetHLeft=zeroMM, offsetHRight=zeroMM, offsetVLeft=zeroMM, offsetVRight=zeroMM, widthFirstSegmentDefault=False):
|
||||
|
||||
@@ -669,7 +669,7 @@ class _Stairs(ArchComponent.Component):
|
||||
|
||||
v, vLength, vWidth, vBase = [], [], [], []
|
||||
|
||||
p1, p2, p3, p4, pArc, pArc1, pArc2 = [], [], [], [], [], [], [] # p1o, p2o - Not used
|
||||
p1, p2, p3, p4, pArc, pArc1, pArc2 = [], [], [], [], [], [], [] # p1o, p2o - Not used
|
||||
outline, outlineP1P2, outlineP3P4, outlineP1P2Closed, outlineP3P4Closed, outlineP1P2Ordered = [], [], [], [], [], []
|
||||
|
||||
if not isinstance(edges, list):
|
||||
@@ -679,10 +679,10 @@ class _Stairs(ArchComponent.Component):
|
||||
for i, edge in enum_edges:
|
||||
|
||||
isLine = isinstance(edge.Curve,(Part.Line, Part.LineSegment))
|
||||
isArc = isinstance(edge.Curve,Part.Circle) # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
isArc = isinstance(edge.Curve,Part.Circle) # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
|
||||
''' (1) append v (vec) '''
|
||||
v.append(DraftGeomUtils.vec(edge)) # TODO check all function below ok with curve?
|
||||
v.append(DraftGeomUtils.vec(edge)) # TODO check all function below ok with curve?
|
||||
|
||||
|
||||
''' (2) get netWidthI '''
|
||||
@@ -709,7 +709,7 @@ class _Stairs(ArchComponent.Component):
|
||||
#vBase2vec = (vBase2-vBase[i]) # - would not be correct if Align is not Left
|
||||
|
||||
''' (1a) calc & append vLength - Need v (vec) '''
|
||||
vLength.append(Vector(v[i].x,v[i].y,v[i].z)) # TODO check all function below ok with curve? # TODO vLength in this f() is 3d
|
||||
vLength.append(Vector(v[i].x,v[i].y,v[i].z)) # TODO check all function below ok with curve? # TODO vLength in this f() is 3d
|
||||
|
||||
|
||||
''' (1b, 2a) calc & append vWidth - Need vLength, netWidthI '''
|
||||
@@ -720,7 +720,7 @@ class _Stairs(ArchComponent.Component):
|
||||
dvec = vLength[i].cross(Vector(0,0,1))
|
||||
|
||||
elif isArc:
|
||||
#dvec = edge.Vertexes[0].Point.sub(edge.Curve.Center) # TODO - how to determine direction? - Reference from ArchWall; used tangentAt instead
|
||||
#dvec = edge.Vertexes[0].Point.sub(edge.Curve.Center) # TODO - how to determine direction? - Reference from ArchWall; used tangentAt instead
|
||||
#dvec1 = edge.Vertexes[1].Point.sub(edge.Curve.Center)
|
||||
dvec = edge.tangentAt(edge.FirstParameter).cross(Vector(0,0,1))
|
||||
dvec1 = edge.tangentAt(edge.LastParameter).cross(Vector(0,0,1))
|
||||
@@ -742,7 +742,7 @@ class _Stairs(ArchComponent.Component):
|
||||
vBase[i] = vBase[i].add(Vector(0,0,railStartRiser.Value))
|
||||
|
||||
if isArc:
|
||||
vBase1 = vBase1.add(Vector(0,0,offsetVLeft.Value)) # TODO - if arc is flight (sloping then), arc would be ellipse, so the following become incorrect?
|
||||
vBase1 = vBase1.add(Vector(0,0,offsetVLeft.Value)) # TODO - if arc is flight (sloping then), arc would be ellipse, so the following become incorrect?
|
||||
vBase1 = vBase1.add(Vector(0,0,railStartRiser.Value))
|
||||
vBase2 = vBase2.add(Vector(0,0,offsetVLeft.Value))
|
||||
vBase2 = vBase2.add(Vector(0,0,railStartRiser.Value))
|
||||
@@ -783,7 +783,7 @@ class _Stairs(ArchComponent.Component):
|
||||
''' (3c, 2c/2d) from [p1, p2, p3, p4] - calc outlineP1P2, outlineP3P4 '''
|
||||
|
||||
if i > 0:
|
||||
lastEdge = edges[i-1] # thisEdge = edge
|
||||
lastEdge = edges[i-1] # thisEdge = edge
|
||||
p1last = p1[i-1]
|
||||
p2last = p2[i-1]
|
||||
p3last = p3[i-1]
|
||||
@@ -801,7 +801,7 @@ class _Stairs(ArchComponent.Component):
|
||||
lastEdgeIsLineSegmentBool = isinstance(lastEdge.Curve,(Part.Line, Part.LineSegment))
|
||||
thisEdgeIsLineSegmentBool = isinstance(edge.Curve,(Part.Line, Part.LineSegment))
|
||||
|
||||
lastEdgeIsCircleBool = isinstance(lastEdge.Curve,(Part.Circle)) # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
lastEdgeIsCircleBool = isinstance(lastEdge.Curve,(Part.Circle)) # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
thisEdgeIsCircleBool = isinstance(edge.Curve,(Part.Circle))
|
||||
|
||||
intersectionP1P2, intersectionP3P4 = _Stairs.findLineArcIntersections(p1last, p2last, p3last, p4last, p1this, p2this, p3this, p4this, lastEdgeIsLineSegmentBool, thisEdgeIsLineSegmentBool,
|
||||
@@ -821,24 +821,24 @@ class _Stairs(ArchComponent.Component):
|
||||
outline.append(p1[0])
|
||||
|
||||
pArc1.append(None)
|
||||
pArc2 = pArc2[::-1] # pArcReverse = pArc2[::-1]
|
||||
pArc2 = pArc2[::-1] # pArcReverse = pArc2[::-1]
|
||||
pArc2.append(None)
|
||||
pArc.extend(pArc1)
|
||||
pArc.extend(pArc2) # pArc.extend(pArcReverse)
|
||||
pArc.extend(pArc2) # pArc.extend(pArcReverse)
|
||||
|
||||
firstEdgeIsLineSegmentBool = isinstance(edges[0].Curve,(Part.Line, Part.LineSegment))
|
||||
firstEdgeIsCircleBool = isinstance(edges[0].Curve,(Part.Circle)) # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
firstEdgeIsCircleBool = isinstance(edges[0].Curve,(Part.Circle)) # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
|
||||
if mode in ["OrderedClose", "OrderedCloseAndOrderedOpen"]: # seem only using 'OrderedClose'
|
||||
if mode in ["OrderedClose", "OrderedCloseAndOrderedOpen"]: # seem only using 'OrderedClose'
|
||||
intersectionP1P2, intersectionP3P4 = _Stairs.findLineArcIntersections(p1this, p2this, p3this, p4this, p1[0], p2[0], p3[0], p4[0], thisEdgeIsLineSegmentBool, firstEdgeIsLineSegmentBool,
|
||||
thisEdgeIsCircleBool, firstEdgeIsCircleBool, pArc1this, pArc2this, pArc1[0], pArc2[0])
|
||||
outlineP1P2Closed = list(outlineP1P2)
|
||||
outlineP1P2Closed[0] = intersectionP1P2 #intersection[0]
|
||||
outlineP1P2Closed[i+1] = intersectionP1P2 #intersection[0]
|
||||
outlineP1P2Closed[0] = intersectionP1P2 #intersection[0]
|
||||
outlineP1P2Closed[i+1] = intersectionP1P2 #intersection[0]
|
||||
|
||||
outlineP3P4Closed = list(outlineP3P4)
|
||||
outlineP3P4Closed[0] = intersectionP3P4 #intersection[0]
|
||||
outlineP3P4Closed[i+1] = intersectionP3P4 #intersection[0]
|
||||
outlineP3P4Closed[0] = intersectionP3P4 #intersection[0]
|
||||
outlineP3P4Closed[i+1] = intersectionP3P4 #intersection[0]
|
||||
|
||||
if mode in ["OrderedOpen", "OrderedCloseAndOrderedOpen"]:
|
||||
if i > 0: # Multi-edge, otherwise no use
|
||||
@@ -889,24 +889,24 @@ class _Stairs(ArchComponent.Component):
|
||||
return intersectionsP1P2[0], intersectionsP3P4[0]
|
||||
else:
|
||||
if lastEdgeIsCircleBool:
|
||||
edge1 = Part.Arc(p1last,pArc1last,p2last).toShape() # edge1 = Part.Arc(p1[i-1],pArc1[i-1],p2[i-1]).toShape()
|
||||
edge1a = Part.Arc(p3last,pArc2last,p4last).toShape() # edge1a = Part.Arc(p3[i-1],pArc2[i-1],p4[i-1]).toShape()
|
||||
edge1 = Part.Arc(p1last,pArc1last,p2last).toShape() # edge1 = Part.Arc(p1[i-1],pArc1[i-1],p2[i-1]).toShape()
|
||||
edge1a = Part.Arc(p3last,pArc2last,p4last).toShape() # edge1a = Part.Arc(p3[i-1],pArc2[i-1],p4[i-1]).toShape()
|
||||
else:
|
||||
edge1 = Part.LineSegment(p1last,p2last).toShape() # edge1 = Part.LineSegment(p1[i-1],p2[i-1]).toShape()
|
||||
edge1a = Part.LineSegment(p3last,p4last).toShape() # edge1a = Part.LineSegment(p3[i-1],p4[i-1]).toShape()
|
||||
edge1 = Part.LineSegment(p1last,p2last).toShape() # edge1 = Part.LineSegment(p1[i-1],p2[i-1]).toShape()
|
||||
edge1a = Part.LineSegment(p3last,p4last).toShape() # edge1a = Part.LineSegment(p3[i-1],p4[i-1]).toShape()
|
||||
|
||||
if thisEdgeIsCircleBool: # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
edge2 = Part.Arc(p1this,pArc1this,p2this).toShape() # edge2 = Part.Arc(p1[i],pArc1[i],p2[i]).toShape()
|
||||
edge2a = Part.Arc(p3this,pArc2this,p4this).toShape() # edge2a = Part.Arc(p3[i],pArc2[i],p4[i]).toShape()
|
||||
if thisEdgeIsCircleBool: # why it is Part.Circle for an Arc Edge? - why Part.ArcOfCircle Not Working?
|
||||
edge2 = Part.Arc(p1this,pArc1this,p2this).toShape() # edge2 = Part.Arc(p1[i],pArc1[i],p2[i]).toShape()
|
||||
edge2a = Part.Arc(p3this,pArc2this,p4this).toShape() # edge2a = Part.Arc(p3[i],pArc2[i],p4[i]).toShape()
|
||||
else:
|
||||
edge2 = Part.LineSegment(p1this,p2this).toShape() # edge2 = Part.LineSegment(p1[i],p2[i]).toShape()
|
||||
edge2a = Part.LineSegment(p3this,p4this).toShape() # edge2a = Part.LineSegment(p3[i],p4[i]).toShape()
|
||||
edge2 = Part.LineSegment(p1this,p2this).toShape() # edge2 = Part.LineSegment(p1[i],p2[i]).toShape()
|
||||
edge2a = Part.LineSegment(p3this,p4this).toShape() # edge2a = Part.LineSegment(p3[i],p4[i]).toShape()
|
||||
intersections = DraftGeomUtils.findIntersection(edge1, edge2, True,True)
|
||||
|
||||
enum_intersections = enumerate(intersections)
|
||||
distList = []
|
||||
for n, intersectionI in enum_intersections:
|
||||
distList.append((intersectionI-p1this).Length) # distList.append((intersectionI-p1[i]).Length)) # TODO just use p1[i] for test; may be p2[i-1]...?
|
||||
distList.append((intersectionI-p1this).Length) # distList.append((intersectionI-p1[i]).Length)) # TODO just use p1[i] for test; may be p2[i-1]...?
|
||||
|
||||
# TODO - To test and follow up if none intersection is found
|
||||
nearestIntersectionIndex = distList.index(min(distList))
|
||||
@@ -916,7 +916,7 @@ class _Stairs(ArchComponent.Component):
|
||||
enum_intersections = enumerate(intersections)
|
||||
distList = []
|
||||
for n, intersectionI in enum_intersections:
|
||||
distList.append((intersectionI-p4this).Length) # distList.append((intersectionI-p4[i]).Length)) # TODO just use p4[i] for test; may be p3[i-1]...?
|
||||
distList.append((intersectionI-p4this).Length) # distList.append((intersectionI-p4[i]).Length)) # TODO just use p4[i] for test; may be p3[i-1]...?
|
||||
nearestIntersectionIndex = distList.index(min(distList))
|
||||
nearestIntersectionP3P4 = intersections[nearestIntersectionIndex]
|
||||
return nearestIntersectionP1P2, nearestIntersectionP3P4
|
||||
@@ -925,12 +925,12 @@ class _Stairs(ArchComponent.Component):
|
||||
def vbaseFollowLastSegment(obj, vBase):
|
||||
if obj.LastSegment:
|
||||
lastSegmentAbsTop = obj.LastSegment.AbsTop
|
||||
vBase = Vector(vBase.x, vBase.y,lastSegmentAbsTop.z) # use Last Segment top's z-coordinate
|
||||
vBase = Vector(vBase.x, vBase.y,lastSegmentAbsTop.z) # use Last Segment top's z-coordinate
|
||||
return vBase
|
||||
|
||||
|
||||
# Add flag (temporarily?) for indicating which method call this to determine whether the landing has been 're-based' before or not
|
||||
def makeStraightLanding(self,obj,edge,numberofsteps=None, callByMakeStraightStairsWithLanding=False): # what is use of numberofsteps ?
|
||||
def makeStraightLanding(self,obj,edge,numberofsteps=None, callByMakeStraightStairsWithLanding=False): # what is use of numberofsteps ?
|
||||
"builds a landing from a straight edge"
|
||||
|
||||
# general data
|
||||
@@ -1129,14 +1129,14 @@ class _Stairs(ArchComponent.Component):
|
||||
lastSegmentAbsTop = obj.LastSegment.AbsTop
|
||||
print("lastSegmentAbsTop is: ")
|
||||
print(lastSegmentAbsTop)
|
||||
vBase = Vector(vBase.x, vBase.y,lastSegmentAbsTop.z) # use Last Segment top's z-coordinate
|
||||
vBase = Vector(vBase.x, vBase.y,lastSegmentAbsTop.z) # use Last Segment top's z-coordinate
|
||||
obj.AbsTop = vBase.add(Vector(0,0,h))
|
||||
|
||||
vNose = DraftVecUtils.scaleTo(vLength,-abs(obj.Nosing.Value))
|
||||
a = math.atan(vHeight.Length/vLength.Length)
|
||||
|
||||
vBasedAligned = self.align(vBase,obj.Align,vWidth)
|
||||
vRiserThickness = DraftVecUtils.scaleTo(vLength,obj.RiserThickness.Value) # 50)
|
||||
vRiserThickness = DraftVecUtils.scaleTo(vLength,obj.RiserThickness.Value) # 50)
|
||||
|
||||
# steps and risers
|
||||
for i in range(numberofsteps-1):
|
||||
@@ -1162,17 +1162,17 @@ class _Stairs(ArchComponent.Component):
|
||||
''' risers - add to steps or pseudosteps in the meantime before adding self.risers / self.pseudorisers '''
|
||||
|
||||
#vResHeight = vHeight.add(Vector(0,0,-abs(obj.TreadThickness.Value)))
|
||||
r2 = r1.add(DraftVecUtils.neg(vHeight)) #vResHeight
|
||||
r2 = r1.add(DraftVecUtils.neg(vHeight)) #vResHeight
|
||||
if i == 0:
|
||||
r2 = r2.add(Vector(0,0,abs(obj.TreadThickness.Value)))
|
||||
r3 = r2.add(vWidth)
|
||||
r4 = r3.add(vHeight) #vResHeight
|
||||
r4 = r3.add(vHeight) #vResHeight
|
||||
if i == 0:
|
||||
r4 = r4.add(Vector(0,0,-abs(obj.TreadThickness.Value)))
|
||||
riser = Part.Face(Part.makePolygon([r1,r2,r3,r4,r1]))
|
||||
|
||||
if obj.RiserThickness.Value:
|
||||
riser = riser.extrude(vRiserThickness) #Vector(0,100,0))
|
||||
riser = riser.extrude(vRiserThickness) #Vector(0,100,0))
|
||||
self.steps.append(riser)
|
||||
else:
|
||||
self.pseudosteps.append(riser)
|
||||
@@ -1320,12 +1320,12 @@ class _Stairs(ArchComponent.Component):
|
||||
else:
|
||||
reslength = edge.Length - obj.Width.Value
|
||||
|
||||
treadDepth = float(reslength)/(obj.NumberOfSteps-2) # why needs 'float'?
|
||||
treadDepth = float(reslength)/(obj.NumberOfSteps-2) # why needs 'float'?
|
||||
obj.TreadDepth = treadDepth
|
||||
vLength = DraftVecUtils.scaleTo(v,treadDepth)
|
||||
else:
|
||||
reslength = edge.Length
|
||||
treadDepth = float(reslength)/(obj.NumberOfSteps-1) # why needs 'float'?
|
||||
treadDepth = float(reslength)/(obj.NumberOfSteps-1) # why needs 'float'?
|
||||
obj.TreadDepth = treadDepth
|
||||
vLength = DraftVecUtils.scaleTo(v,treadDepth)
|
||||
else:
|
||||
@@ -1355,7 +1355,7 @@ class _Stairs(ArchComponent.Component):
|
||||
|
||||
if obj.LastSegment:
|
||||
lastSegmentAbsTop = obj.LastSegment.AbsTop
|
||||
p1 = Vector(p1.x, p1.y,lastSegmentAbsTop.z) # use Last Segment top's z-coordinate
|
||||
p1 = Vector(p1.x, p1.y,lastSegmentAbsTop.z) # use Last Segment top's z-coordinate
|
||||
|
||||
obj.AbsTop = p1.add(Vector(0,0,h))
|
||||
p2 = p1.add(DraftVecUtils.scale(vLength,landing-1).add(Vector(0,0,landing*hstep)))
|
||||
@@ -1414,8 +1414,8 @@ class _Stairs(ArchComponent.Component):
|
||||
obj.OutlineLeft = outlineRailL # outlineL # outlineP1P2
|
||||
obj.OutlineRight = outlineRailR # outlineR # outlineP3P4
|
||||
|
||||
self.OutlineRailArcLeft = pArcRailL #obj.OutlineRailArcLeft = pArcRailL
|
||||
self.OutlineRailArcRight = pArcRailR #obj.OutlineRailArcRight = pArcRailR
|
||||
self.OutlineRailArcLeft = pArcRailL #obj.OutlineRailArcLeft = pArcRailL
|
||||
self.OutlineRailArcRight = pArcRailR #obj.OutlineRailArcRight = pArcRailR
|
||||
|
||||
outlineLeftAll, outlineRightAll, outlineRailArcLeftAll, outlineRailArcRightAll = [], [], [], []
|
||||
|
||||
|
||||
@@ -1351,7 +1351,7 @@ class _Wall(ArchComponent.Component):
|
||||
|
||||
if not DraftVecUtils.isNull(dvec):
|
||||
dvec.normalize()
|
||||
sh = None
|
||||
face = None
|
||||
|
||||
curAligns = aligns[0]
|
||||
off = obj.Offset.Value
|
||||
@@ -1399,7 +1399,7 @@ class _Wall(ArchComponent.Component):
|
||||
normal=normal,
|
||||
basewireOffset=off)
|
||||
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
face = DraftGeomUtils.bind(w1, w2, per_segment=True)
|
||||
|
||||
elif curAligns == "Right":
|
||||
dvec = dvec.negative()
|
||||
@@ -1440,7 +1440,7 @@ class _Wall(ArchComponent.Component):
|
||||
normal=normal,
|
||||
basewireOffset=off)
|
||||
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
face = DraftGeomUtils.bind(w1, w2, per_segment=True)
|
||||
|
||||
#elif obj.Align == "Center":
|
||||
elif curAligns == "Center":
|
||||
@@ -1473,18 +1473,16 @@ class _Wall(ArchComponent.Component):
|
||||
alignList=aligns,
|
||||
normal=normal,
|
||||
basewireOffset=off)
|
||||
sh = DraftGeomUtils.bind(w1,w2)
|
||||
face = DraftGeomUtils.bind(w1, w2, per_segment=True)
|
||||
|
||||
del widths[0:edgeNum]
|
||||
del aligns[0:edgeNum]
|
||||
if sh:
|
||||
if face:
|
||||
|
||||
if layers and (layers[i] < 0):
|
||||
# layers with negative values are not drawn
|
||||
continue
|
||||
|
||||
sh.fix(0.1,0,1) # fixes self-intersecting wires
|
||||
f = Part.Face(sh)
|
||||
if baseface:
|
||||
|
||||
# To allow exportIFC.py to work properly on
|
||||
@@ -1505,14 +1503,14 @@ class _Wall(ArchComponent.Component):
|
||||
# - 1st finding : if a rectangle + 1 line, can't removesSplitter properly...
|
||||
# - 2nd finding : if 2 faces do not touch, can't form a shell; then, subsequently for remaining faces even though touch each faces, can't form a shell
|
||||
|
||||
baseface.append(f)
|
||||
baseface.append(face)
|
||||
# The above make Refine methods below (in else) useless, regardless removeSpitters yet to be improved for cases do not work well
|
||||
''' Whether layers or not, all baseface.append(f) '''
|
||||
''' Whether layers or not, all baseface.append(face) '''
|
||||
|
||||
else:
|
||||
baseface = [f]
|
||||
baseface = [face]
|
||||
|
||||
''' Whether layers or not, all baseface = [f] '''
|
||||
''' Whether layers or not, all baseface = [face] '''
|
||||
|
||||
if baseface:
|
||||
base,placement = self.rebase(baseface)
|
||||
|
||||
@@ -651,8 +651,8 @@ class _Window(ArchComponent.Component):
|
||||
if hasattr(self,prop):
|
||||
if getattr(self,prop) != getattr(obj,prop):
|
||||
touchhosts = True
|
||||
if touchhosts and hasattr(obj,"Hosts"):
|
||||
for host in obj.Hosts:
|
||||
if touchhosts and hasattr(self, "Hosts") and hasattr(obj, "Hosts"):
|
||||
for host in set(self.Hosts + obj.Hosts): # use set to remove duplicates
|
||||
# mark host to recompute so it can detect this object
|
||||
host.touch()
|
||||
if prop in ["Width","Height","Frame"]:
|
||||
|
||||
@@ -184,7 +184,7 @@ def createStructuralMember(ifcfile, ifcbin, obj):
|
||||
# - no profile properties are taken into account
|
||||
# - no materials properties are takein into account
|
||||
# -
|
||||
# create geometry
|
||||
# create geometry
|
||||
verts = [None for _ in range(len(edges)+1)]
|
||||
verts[0] = tuple(edges[0].Vertexes[ 0].Point.multiply(scaling))
|
||||
verts[1] = tuple(edges[0].Vertexes[-1].Point.multiply(scaling))
|
||||
|
||||
+34
-34
@@ -650,14 +650,14 @@ def getHTMLTemplate():
|
||||
|
||||
def export( exportList, filename, colors = None, camera = None ):
|
||||
"""Exports objects to an html file"""
|
||||
|
||||
|
||||
global disableCompression, base, baseFloat
|
||||
|
||||
|
||||
data = { 'camera':{}, 'file':{}, 'objects':[] }
|
||||
|
||||
|
||||
if not FreeCADGui and not camera:
|
||||
camera = OfflineRenderingUtils.getCamera(FreeCAD.ActiveDocument.FileName)
|
||||
|
||||
|
||||
if camera:
|
||||
# REF: https://github.com/FreeCAD/FreeCAD/blob/master/src/Mod/Arch/OfflineRenderingUtils.py
|
||||
camnode = OfflineRenderingUtils.getCoinCamera(camera)
|
||||
@@ -674,17 +674,17 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
data['camera']['focalDistance'] = v.getCameraNode().focalDistance.getValue()
|
||||
data['camera']['position_x'] = v.viewPosition().Base.x
|
||||
data['camera']['position_y'] = v.viewPosition().Base.y
|
||||
data['camera']['position_z'] = v.viewPosition().Base.z
|
||||
|
||||
data['camera']['position_z'] = v.viewPosition().Base.z
|
||||
|
||||
# Take the objects out of groups
|
||||
objectslist = Draft.get_group_contents(exportList, walls=True, addgroups=False)
|
||||
# objectslist = Arch.pruneIncluded(objectslist)
|
||||
|
||||
|
||||
for obj in objectslist:
|
||||
|
||||
|
||||
# Pull all obj data before we dig down the links
|
||||
label = obj.Label
|
||||
|
||||
|
||||
color = '#cccccc';
|
||||
opacity = 1.0
|
||||
if FreeCADGui:
|
||||
@@ -692,8 +692,8 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
opacity = int((100 - obj.ViewObject.Transparency)/5) / 20 # 0>>1 with step of 0.05
|
||||
elif colors:
|
||||
if label in colors:
|
||||
color = Draft.getrgb(colors[label], testbw = False)
|
||||
|
||||
color = Draft.getrgb(colors[label], testbw = False)
|
||||
|
||||
validObject = False
|
||||
if obj.isDerivedFrom('Mesh::Feature'):
|
||||
mesh = obj.Mesh
|
||||
@@ -720,26 +720,26 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
mesh.Placement = linkPlacement
|
||||
validObject = True
|
||||
break
|
||||
|
||||
|
||||
if not validObject: continue
|
||||
|
||||
|
||||
objdata = { 'name': label, 'color': color, 'opacity': opacity, 'verts':'', 'facets':'', 'wires':[], 'faceColors':[], 'facesToFacets':[], 'floats':[] }
|
||||
|
||||
|
||||
if obj.isDerivedFrom('Part::Feature'):
|
||||
|
||||
|
||||
deviation = 0.5
|
||||
if FreeCADGui:
|
||||
deviation = obj.ViewObject.Deviation
|
||||
|
||||
|
||||
# obj.ViewObject.DiffuseColor is length=1 when all faces are the same color, length=len(faces) for when they're not
|
||||
if len(obj.ViewObject.DiffuseColor) == len(objShape.Faces):
|
||||
for fc in obj.ViewObject.DiffuseColor:
|
||||
objdata['faceColors'].append( Draft.getrgb(fc, testbw = False) )
|
||||
|
||||
|
||||
# get verts and facets for ENTIRE object
|
||||
shapeData = objShape.tessellate( deviation )
|
||||
mesh = Mesh.Mesh(shapeData)
|
||||
|
||||
|
||||
if len(objShape.Faces) > 1:
|
||||
# Map each Facet created by tessellate() to a Face so that it can be colored correctly using faceColors
|
||||
# This is done by matching the results of a tessellate() on EACH FACE to the overall tessellate stored in shapeData
|
||||
@@ -759,8 +759,8 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
FreeCAD.Console.PrintMessage("Facet to Face Mismatch.\n")
|
||||
objdata['facesToFacets'] = []
|
||||
break
|
||||
|
||||
# map each of the face facets to the shape facets and make a list of shape facet indices that belong to this face
|
||||
|
||||
# map each of the face facets to the shape facets and make a list of shape facet indices that belong to this face
|
||||
facetList = []
|
||||
for ff in faceData[1]: # face facets
|
||||
found = False
|
||||
@@ -774,9 +774,9 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
FreeCAD.Console.PrintMessage("Facet List Mismatch.\n")
|
||||
objdata['facesToFacets'] = []
|
||||
break
|
||||
|
||||
|
||||
objdata['facesToFacets'].append( baseEncode(facetList) )
|
||||
|
||||
|
||||
wires = [] # Add wires
|
||||
for f in objShape.Faces:
|
||||
for w in f.Wires:
|
||||
@@ -787,7 +787,7 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
wire.append( '{:.5f}'.format(v.y) )
|
||||
wire.append( '{:.5f}'.format(v.z) )
|
||||
wires.append( wire )
|
||||
|
||||
|
||||
if not disableCompression:
|
||||
for w in range( len(wires) ):
|
||||
for wv in range( len(wires[w]) ):
|
||||
@@ -802,7 +802,7 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
wires[w][wv] = len(objdata['floats'])-1
|
||||
wires[w] = baseEncode(wires[w])
|
||||
objdata['wires'] = wires
|
||||
|
||||
|
||||
vIndex = {}
|
||||
verts = []
|
||||
for p in range( len(mesh.Points) ):
|
||||
@@ -810,7 +810,7 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
verts.append( '{:.5f}'.format(mesh.Points[p].Vector.x) )
|
||||
verts.append( '{:.5f}'.format(mesh.Points[p].Vector.y) )
|
||||
verts.append( '{:.5f}'.format(mesh.Points[p].Vector.z) )
|
||||
|
||||
|
||||
# create floats list to compress verts and wires being written into the JS
|
||||
if not disableCompression:
|
||||
for v in range( len(verts) ):
|
||||
@@ -824,13 +824,13 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
objdata['floats'].append( verts[v] )
|
||||
verts[v] = len(objdata['floats'])-1
|
||||
objdata['verts'] = baseEncode(verts)
|
||||
|
||||
|
||||
facets = []
|
||||
for f in mesh.Facets:
|
||||
for i in f.PointIndices:
|
||||
facets.append( vIndex[i] )
|
||||
objdata['facets'] = baseEncode(facets)
|
||||
|
||||
|
||||
# compress floats
|
||||
if not disableCompression:
|
||||
# use ratio of 7x base13 to 4x base90 because 13^7 ~ 90^4
|
||||
@@ -848,20 +848,20 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
floatStr += base[ quotient % baseCt ]
|
||||
quotient = int(quotient / baseCt)
|
||||
objdata['floats'] = floatStr
|
||||
|
||||
|
||||
data['objects'].append( objdata )
|
||||
|
||||
|
||||
html = getHTMLTemplate()
|
||||
|
||||
|
||||
html = html.replace('$pagetitle',FreeCAD.ActiveDocument.Label)
|
||||
version = FreeCAD.Version()
|
||||
html = html.replace('$version',version[0] + '.' + version[1] + '.' + version[2])
|
||||
|
||||
|
||||
# Remove data compression in JS
|
||||
data['compressed'] = not disableCompression
|
||||
data['base'] = base
|
||||
data['baseFloat'] = baseFloat
|
||||
|
||||
|
||||
html = html.replace('$data', json.dumps(data, separators=(',', ':')) ) # Shape Data
|
||||
|
||||
if six.PY2:
|
||||
@@ -874,11 +874,11 @@ def export( exportList, filename, colors = None, camera = None ):
|
||||
|
||||
def baseEncode( arr ):
|
||||
"""Compresses an array of ints into a base90 string"""
|
||||
|
||||
|
||||
global disableCompression, base
|
||||
if disableCompression: return arr
|
||||
if len(arr) == 0: return ''
|
||||
|
||||
|
||||
longest = 0
|
||||
output = []
|
||||
baseCt = len(base)
|
||||
|
||||
@@ -151,13 +151,8 @@ inCommandShortcuts = {
|
||||
translate("draft","Cycle snap object"),
|
||||
None
|
||||
],
|
||||
"NearSnap": [
|
||||
Draft.getParam("inCommandShortcutNearSnap", "N"),
|
||||
translate("draft","Toggle near snap on/off"),
|
||||
None
|
||||
],
|
||||
"Undo": [
|
||||
Draft.getParam("inCommandShortcutNearSnap", "/"),
|
||||
Draft.getParam("inCommandShortcutUndo", "/"),
|
||||
translate("draft","Undo last segment"),
|
||||
None
|
||||
],
|
||||
@@ -1671,9 +1666,6 @@ class DraftToolBar:
|
||||
elif txt.upper().startswith(inCommandShortcuts["Snap"][0]):
|
||||
self.togglesnap()
|
||||
spec = True
|
||||
elif txt.upper().startswith(inCommandShortcuts["NearSnap"][0]):
|
||||
self.togglenearsnap()
|
||||
spec = True
|
||||
elif txt.upper().startswith(inCommandShortcuts["Increase"][0]):
|
||||
self.toggleradius(1)
|
||||
spec = True
|
||||
@@ -2097,13 +2089,6 @@ class DraftToolBar:
|
||||
def togglesnap(self):
|
||||
FreeCADGui.doCommand('FreeCADGui.runCommand("Draft_Snap_Lock")')
|
||||
|
||||
def togglenearsnap(self):
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
if hasattr(FreeCADGui.Snapper,"toolbarButtons"):
|
||||
for b in FreeCADGui.Snapper.toolbarButtons:
|
||||
if b.objectName() == "SnapButtonpassive":
|
||||
b.toggle()
|
||||
|
||||
def toggleradius(self,val):
|
||||
if hasattr(FreeCADGui,"Snapper"):
|
||||
par = Draft.getParam("snapRange", 8)
|
||||
|
||||
@@ -76,13 +76,20 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Continue</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<item row="0" column="4">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_3">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -119,14 +126,21 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<item row="0" column="7">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_4">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -163,6 +177,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="8">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
@@ -207,14 +228,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Subelement Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<item row="1" column="4">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_11">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -251,14 +272,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<item row="1" column="6">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Fill</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<item row="1" column="7">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_12">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -339,14 +360,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Select Edge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<item row="2" column="4">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_13">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -383,14 +404,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<item row="2" column="6">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Add Hold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="5">
|
||||
<item row="2" column="7">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_15">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -471,14 +492,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>Wipe</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<item row="3" column="4">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_14">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -515,14 +536,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<item row="3" column="6">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>Set WP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<item row="3" column="7">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_16">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -603,14 +624,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<item row="4" column="3">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Global</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<item row="4" column="4">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_21">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -647,7 +668,51 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="4" column="6">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Undo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="7">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_22">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>/</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="clearButtonEnabled" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>inCommandShortcutUndo</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Draft</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Snap</string>
|
||||
@@ -691,14 +756,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Increase Radius</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<item row="5" column="4">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_19">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -735,14 +800,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<item row="5" column="6">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Decrease Radius</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="5">
|
||||
<item row="5" column="7">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_17">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -823,14 +888,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<item row="6" column="3">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>Restrict Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<item row="6" column="4">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_20">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
@@ -867,14 +932,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="4">
|
||||
<item row="6" column="6">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>Restrict Z</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="5">
|
||||
<item row="6" column="7">
|
||||
<widget class="Gui::PrefLineEdit" name="lineEdit_18">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
|
||||
@@ -345,13 +345,15 @@ class Plane:
|
||||
self.u = Vector(0, -1, 0)
|
||||
self.v = Vector(0, 0, 1)
|
||||
elif upvec:
|
||||
self.v = upvec
|
||||
self.u = upvec.cross(self.axis)
|
||||
self.u.normalize()
|
||||
self.v = self.axis.cross(self.u)
|
||||
self.v.normalize()
|
||||
self.u = self.v.cross(self.axis)
|
||||
else:
|
||||
self.v = axis.cross(Vector(1, 0, 0))
|
||||
self.v.normalize()
|
||||
self.u = DraftVecUtils.rotate(self.v, -math.pi/2, self.axis)
|
||||
self.u.normalize()
|
||||
offsetVector = Vector(axis)
|
||||
offsetVector.multiply(offset)
|
||||
self.position = point.add(offsetVector)
|
||||
|
||||
@@ -72,9 +72,12 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
newwire = None
|
||||
delete = None
|
||||
|
||||
if utils.get_type(obj).startswith("Part::") or utils.get_type(obj).startswith("Sketcher::"):
|
||||
copy = True
|
||||
if (copy is False
|
||||
and (utils.get_type(obj).startswith("Sketcher::")
|
||||
or utils.get_type(obj).startswith("Part::")
|
||||
or utils.get_type(obj).startswith("PartDesign::"))): # For PartDesign_SubShapeBinders which can reference sketches.
|
||||
print("the offset tool is currently unable to offset a non-Draft object directly - Creating a copy")
|
||||
copy = True
|
||||
|
||||
def getRect(p,obj):
|
||||
"""returns length,height,placement"""
|
||||
@@ -199,7 +202,7 @@ def offset(obj, delta, copy=False, bind=False, sym=False, occ=False):
|
||||
try:
|
||||
if p:
|
||||
newobj = make_wire(p)
|
||||
newobj.Closed = obj.Shape.isClosed()
|
||||
newobj.Closed = DraftGeomUtils.isReallyClosed(obj.Shape)
|
||||
except Part.OCCError:
|
||||
pass
|
||||
if (not newobj) and newwire:
|
||||
|
||||
@@ -544,14 +544,18 @@ def get_svg(obj,
|
||||
p2 = get_proj(prx.p2, plane)
|
||||
p3 = get_proj(prx.p3, plane)
|
||||
arrowsize = obj.ViewObject.ArrowSize.Value/pointratio
|
||||
arrowlength = 4*obj.ViewObject.ArrowSize.Value
|
||||
halfarrowlength = 2 * arrowsize
|
||||
arrowangle = 2 * math.asin(halfarrowlength / prx.circle.Curve.Radius)
|
||||
if hasattr(obj.ViewObject, "FlipArrows") \
|
||||
and obj.ViewObject.FlipArrows:
|
||||
arrowangle = -arrowangle
|
||||
|
||||
_v1a = prx.circle.valueAt(prx.circle.FirstParameter
|
||||
+ arrowlength)
|
||||
+ arrowangle)
|
||||
_v1b = prx.circle.valueAt(prx.circle.FirstParameter)
|
||||
|
||||
_v2a = prx.circle.valueAt(prx.circle.LastParameter
|
||||
- arrowlength)
|
||||
- arrowangle)
|
||||
_v2b = prx.circle.valueAt(prx.circle.LastParameter)
|
||||
|
||||
u1 = get_proj(_v1a - _v1b, plane)
|
||||
@@ -559,11 +563,6 @@ def get_svg(obj,
|
||||
angle1 = -DraftVecUtils.angle(u1)
|
||||
angle2 = -DraftVecUtils.angle(u2)
|
||||
|
||||
if hasattr(obj.ViewObject, "FlipArrows"):
|
||||
if obj.ViewObject.FlipArrows:
|
||||
angle1 = angle1 + math.pi
|
||||
angle2 = angle2 + math.pi
|
||||
|
||||
svg += get_arrow(obj,
|
||||
obj.ViewObject.ArrowType,
|
||||
p2, arrowsize, stroke, linewidth,
|
||||
@@ -580,7 +579,7 @@ def get_svg(obj,
|
||||
t = prx.circle.tangentAt(prx.circle.FirstParameter
|
||||
+ _diff/2.0)
|
||||
t = get_proj(t, plane)
|
||||
tangle = DraftVecUtils.angle(t)
|
||||
tangle = -DraftVecUtils.angle(t)
|
||||
if (tangle <= -math.pi/2) or (tangle > math.pi/2):
|
||||
tangle = tangle + math.pi
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import FreeCAD as App
|
||||
import DraftVecUtils
|
||||
|
||||
from draftgeoutils.general import geomType
|
||||
from draftgeoutils.edges import findMidpoint
|
||||
|
||||
# Delay import of module until first use because it is heavy
|
||||
Part = lz.LazyLoader("Part", globals(), "Part")
|
||||
@@ -134,8 +135,7 @@ def arcFromSpline(edge):
|
||||
else:
|
||||
# circle
|
||||
p1 = edge.Vertexes[0].Point
|
||||
ml = edge.Length/2
|
||||
p2 = edge.valueAt(ml)
|
||||
p2 = findMidpoint(edge)
|
||||
ray = p2.sub(p1)
|
||||
ray.scale(0.5, 0.5, 0.5)
|
||||
center = p1.add(ray)
|
||||
|
||||
@@ -110,32 +110,58 @@ def is_coplanar(faces, tol=-1):
|
||||
isCoplanar = is_coplanar
|
||||
|
||||
|
||||
def bind(w1, w2):
|
||||
"""Bind 2 wires by their endpoints and returns a face."""
|
||||
if not w1 or not w2:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
def bind(w1, w2, per_segment=False):
|
||||
"""Bind 2 wires by their endpoints and returns a face.
|
||||
|
||||
if w1.isClosed() and w2.isClosed():
|
||||
d1 = w1.BoundBox.DiagonalLength
|
||||
d2 = w2.BoundBox.DiagonalLength
|
||||
if d1 > d2:
|
||||
# w2.reverse()
|
||||
return Part.Face([w1, w2])
|
||||
else:
|
||||
# w1.reverse()
|
||||
return Part.Face([w2, w1])
|
||||
else:
|
||||
If per_segment is True and the wires have the same number of edges, the
|
||||
wires are processed per segment: a separate face is created for each pair
|
||||
of edges (one from w1 and one from w2), and the faces are then fused. This
|
||||
avoids problems with walls based on wires that selfintersect, or that have
|
||||
a loop that ends in a T-connection (f.e. a wire shaped like a number 6).
|
||||
"""
|
||||
|
||||
def create_face(w1, w2):
|
||||
try:
|
||||
w3 = Part.LineSegment(w1.Vertexes[0].Point,
|
||||
w2.Vertexes[0].Point).toShape()
|
||||
w4 = Part.LineSegment(w1.Vertexes[-1].Point,
|
||||
w2.Vertexes[-1].Point).toShape()
|
||||
return Part.Face(Part.Wire(w1.Edges+[w3] + w2.Edges+[w4]))
|
||||
return Part.Face(Part.Wire(w1.Edges + [w3] + w2.Edges + [w4]))
|
||||
except Part.OCCError:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
|
||||
if not w1 or not w2:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
|
||||
if (per_segment
|
||||
and len(w1.Edges) > 1
|
||||
and len(w1.Edges) == len(w2.Edges)):
|
||||
faces = []
|
||||
for (edge1, edge2) in zip(w1.Edges, w2.Edges):
|
||||
face = create_face(edge1, edge2)
|
||||
if face is None:
|
||||
return None
|
||||
faces.append(face)
|
||||
# return concatenate(faces[0].fuse(faces[1:])) # Also works.
|
||||
return faces[0].fuse(faces[1:]).removeSplitter().Faces[0]
|
||||
elif w1.isClosed() and w2.isClosed():
|
||||
d1 = w1.BoundBox.DiagonalLength
|
||||
d2 = w2.BoundBox.DiagonalLength
|
||||
if d1 < d2:
|
||||
w1, w2 = w2, w1
|
||||
# return Part.Face(w1).cut(Part.Face(w2)).Faces[0] # Only works if wires do not self-intersect.
|
||||
try:
|
||||
face = Part.Face([w1, w2])
|
||||
face.fix(1e-7, 0, 1)
|
||||
return face
|
||||
except Part.OCCError:
|
||||
print("DraftGeomUtils: unable to bind wires")
|
||||
return None
|
||||
else:
|
||||
return create_face(w1, w2)
|
||||
|
||||
|
||||
def cleanFaces(shape):
|
||||
"""Remove inner edges from coplanar faces."""
|
||||
|
||||
@@ -107,7 +107,9 @@ def findIntersection(edge1, edge2,
|
||||
# First, check bound boxes
|
||||
if (isinstance(edge1, Part.Edge) and isinstance(edge2, Part.Edge)
|
||||
and (not infinite1) and (not infinite2)):
|
||||
if not edge1.BoundBox.intersect(edge2.BoundBox):
|
||||
bb1 = edge1.BoundBox
|
||||
bb1.enlarge(pow(10, -precision())) # enlarge one box to account for rounding errors
|
||||
if not bb1.intersect(edge2.BoundBox):
|
||||
return [] # bound boxes don't intersect
|
||||
|
||||
# First, try to use distToShape if possible
|
||||
@@ -117,7 +119,7 @@ def findIntersection(edge1, edge2,
|
||||
sol = []
|
||||
if round(dist, precision()) == 0:
|
||||
for p in pts:
|
||||
if p not in sol:
|
||||
if p[0] not in sol:
|
||||
sol.append(p[0])
|
||||
return sol
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import DraftVecUtils
|
||||
|
||||
from draftgeoutils.general import geomType, vec
|
||||
from draftgeoutils.geometry import get_normal
|
||||
from draftgeoutils.wires import isReallyClosed
|
||||
from draftgeoutils.intersections import wiresIntersect, connect
|
||||
|
||||
# Delay import of module until first use because it is heavy
|
||||
@@ -237,7 +238,7 @@ def offsetWire(wire, dvec, bind=False, occ=False,
|
||||
if norm is None:
|
||||
norm = App.Vector(0, 0, 1)
|
||||
|
||||
closed = wire.isClosed()
|
||||
closed = isReallyClosed(wire)
|
||||
nedges = []
|
||||
if occ:
|
||||
length = abs(dvec.Length)
|
||||
|
||||
@@ -32,7 +32,6 @@ import lazy_loader.lazy_loader as lz
|
||||
import FreeCAD as App
|
||||
import DraftVecUtils
|
||||
import WorkingPlane
|
||||
import FreeCAD as App
|
||||
|
||||
from draftgeoutils.general import geomType, vec, precision
|
||||
from draftgeoutils.geometry import get_normal
|
||||
@@ -157,26 +156,27 @@ def findWiresOld(edges):
|
||||
return result[1]
|
||||
|
||||
|
||||
def flattenWire(wire):
|
||||
"""Force a wire to get completely flat along its normal."""
|
||||
n = get_normal(wire)
|
||||
# for backward compatibility with previous getNormal implementation
|
||||
if n is None:
|
||||
n = App.Vector(0, 0, 1)
|
||||
def flattenWire(wire, origin=None, normal=None):
|
||||
"""Force a wire to be flat on a plane defined by an origin and a normal.
|
||||
|
||||
If origin or normal are None they are derived from the wire.
|
||||
"""
|
||||
if normal is None:
|
||||
normal = get_normal(wire)
|
||||
# for backward compatibility with previous getNormal implementation
|
||||
if normal is None:
|
||||
normal = App.Vector(0, 0, 1)
|
||||
if origin is None:
|
||||
origin = wire.Vertexes[0].Point
|
||||
|
||||
o = wire.Vertexes[0].Point
|
||||
plane = WorkingPlane.plane()
|
||||
plane.alignToPointAndAxis(o, n, 0)
|
||||
verts = [o]
|
||||
|
||||
for v in wire.Vertexes[1:]:
|
||||
verts.append(plane.projectPoint(v.Point))
|
||||
|
||||
plane.alignToPointAndAxis(origin, normal, 0)
|
||||
points = [plane.projectPoint(vert.Point) for vert in wire.Vertexes]
|
||||
if wire.isClosed():
|
||||
verts.append(o)
|
||||
w = Part.makePolygon(verts)
|
||||
points.append(points[0])
|
||||
new_wire = Part.makePolygon(points)
|
||||
|
||||
return w
|
||||
return new_wire
|
||||
|
||||
|
||||
def superWire(edgeslist, closed=False):
|
||||
@@ -270,10 +270,32 @@ def isReallyClosed(wire):
|
||||
return False
|
||||
|
||||
# If more than 1 edge, further test below
|
||||
v1 = wire.Edges[0].Vertexes[0].Point # v1 = wire.Vertexes[0].Point
|
||||
v2 = wire.Edges[length-1].Vertexes[1].Point # v2 = wire.Vertexes[-1].Point
|
||||
if DraftVecUtils.equals(v1, v2):
|
||||
return True
|
||||
e1 = wire.Edges[0]
|
||||
e2 = wire.Edges[length-1]
|
||||
|
||||
if DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[1].Point):
|
||||
if length == 2:
|
||||
return DraftVecUtils.equals(e1.Vertexes[1].Point, e2.Vertexes[0].Point)
|
||||
else:
|
||||
return True
|
||||
|
||||
if DraftVecUtils.equals(e1.Vertexes[1].Point, e2.Vertexes[0].Point):
|
||||
if length == 2:
|
||||
return DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[1].Point)
|
||||
else:
|
||||
return True
|
||||
|
||||
if DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point):
|
||||
if length == 2:
|
||||
return DraftVecUtils.equals(e1.Vertexes[1].Point, e2.Vertexes[1].Point)
|
||||
else:
|
||||
return True
|
||||
|
||||
if DraftVecUtils.equals(e1.Vertexes[1].Point, e2.Vertexes[1].Point):
|
||||
if length == 2:
|
||||
return DraftVecUtils.equals(e1.Vertexes[0].Point, e2.Vertexes[0].Point)
|
||||
else:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -432,8 +454,8 @@ def get_placement_perpendicular_to_wire(wire):
|
||||
|
||||
|
||||
def get_extended_wire(wire, offset_start, offset_end):
|
||||
"""Return a wire trimmed (negative offset) or extended (positive offset) at its first vertex, last vertex or both ends.
|
||||
|
||||
"""Return a wire trimmed (negative offset) or extended (positive offset) at its first vertex, last vertex or both ends.
|
||||
|
||||
get_extended_wire(wire, -100.0, 0.0) -> returns a copy of the wire with its first 100 mm removed
|
||||
get_extended_wire(wire, 0.0, 100.0) -> returns a copy of the wire extended by 100 mm after it's last vertex
|
||||
"""
|
||||
|
||||
@@ -1136,13 +1136,18 @@ class Snapper:
|
||||
# This should be in device-independent pixels
|
||||
return 32
|
||||
|
||||
def get_quarter_widget(self, mw):
|
||||
views = []
|
||||
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
|
||||
if w.inherits("SIM::Coin3D::Quarter::QuarterWidget"):
|
||||
views.append(w)
|
||||
return views
|
||||
|
||||
def device_pixel_ratio(self):
|
||||
device_pixel_ratio = 1
|
||||
mw = Gui.getMainWindow()
|
||||
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
|
||||
if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget":
|
||||
if int(QtCore.qVersion().split('.')[0]) > 4:
|
||||
device_pixel_ratio = w.devicePixelRatio()
|
||||
for w in self.get_quarter_widget(Gui.getMainWindow()):
|
||||
if int(QtCore.qVersion().split('.')[0]) > 4:
|
||||
device_pixel_ratio = w.devicePixelRatio()
|
||||
return device_pixel_ratio
|
||||
|
||||
def get_cursor_with_tail(self, base_icon_name, tail_icon_name=None):
|
||||
@@ -1174,16 +1179,12 @@ class Snapper:
|
||||
def setCursor(self, mode=None):
|
||||
"""Set or reset the cursor to the given mode or resets."""
|
||||
if self.selectMode:
|
||||
mw = Gui.getMainWindow()
|
||||
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
|
||||
if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget":
|
||||
w.unsetCursor()
|
||||
for w in self.get_quarter_widget(Gui.getMainWindow()):
|
||||
w.unsetCursor()
|
||||
self.cursorMode = None
|
||||
elif not mode:
|
||||
mw = Gui.getMainWindow()
|
||||
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
|
||||
if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget":
|
||||
w.unsetCursor()
|
||||
for w in self.get_quarter_widget(Gui.getMainWindow()):
|
||||
w.unsetCursor()
|
||||
self.cursorMode = None
|
||||
else:
|
||||
if mode != self.cursorMode:
|
||||
@@ -1192,10 +1193,8 @@ class Snapper:
|
||||
if not (mode == 'passive'):
|
||||
tail_icon_name = self.cursors[mode]
|
||||
cur = self.get_cursor_with_tail(base_icon_name, tail_icon_name)
|
||||
mw = Gui.getMainWindow()
|
||||
for w in mw.findChild(QtGui.QMdiArea).findChildren(QtGui.QWidget):
|
||||
if w.metaObject().className() == "SIM::Coin3D::Quarter::QuarterWidget":
|
||||
w.setCursor(cur)
|
||||
for w in self.get_quarter_widget(Gui.getMainWindow()):
|
||||
w.setCursor(cur)
|
||||
self.cursorMode = mode
|
||||
|
||||
def restack(self):
|
||||
|
||||
@@ -78,7 +78,7 @@ def make_clone(obj, delta=None, forcedraft=False):
|
||||
if utils.get_type(obj[0]) == "BuildingPart":
|
||||
cl = Arch.makeComponent()
|
||||
else:
|
||||
try: # new-style maek function
|
||||
try: # new-style make function
|
||||
cl = getattr(Arch, "make_" + obj[0].Proxy.Type.lower())()
|
||||
except Exception:
|
||||
try: # old-style make function
|
||||
@@ -100,11 +100,11 @@ def make_clone(obj, delta=None, forcedraft=False):
|
||||
except Exception:
|
||||
pass
|
||||
if App.GuiUp:
|
||||
gui_utils.format_object(cl,base)
|
||||
cl.ViewObject.DiffuseColor = base.ViewObject.DiffuseColor
|
||||
if utils.get_type(obj[0]) in ["Window","BuildingPart"]:
|
||||
ToDo.delay(Arch.recolorize,cl)
|
||||
gui_utils.select(cl)
|
||||
gui_utils.format_object(cl, base)
|
||||
# Workaround to trigger update of DiffuseColor:
|
||||
ToDo.delay(lambda col: setattr(cl.ViewObject, "DiffuseColor", col),
|
||||
cl.ViewObject.DiffuseColor)
|
||||
gui_utils.select(cl)
|
||||
return cl
|
||||
# fall back to Draft clone mode
|
||||
if not cl:
|
||||
@@ -112,19 +112,23 @@ def make_clone(obj, delta=None, forcedraft=False):
|
||||
cl.addExtension("Part::AttachExtensionPython")
|
||||
cl.Label = prefix + obj[0].Label
|
||||
Clone(cl)
|
||||
if App.GuiUp:
|
||||
ViewProviderClone(cl.ViewObject)
|
||||
cl.Objects = obj
|
||||
if delta:
|
||||
cl.Placement.move(delta)
|
||||
elif (len(obj) == 1) and hasattr(obj[0],"Placement"):
|
||||
cl.Placement = obj[0].Placement
|
||||
gui_utils.format_object(cl,obj[0])
|
||||
if hasattr(cl,"LongName") and hasattr(obj[0],"LongName"):
|
||||
cl.LongName = obj[0].LongName
|
||||
if App.GuiUp and (len(obj) > 1):
|
||||
cl.ViewObject.Proxy.resetColors(cl.ViewObject)
|
||||
gui_utils.select(cl)
|
||||
if App.GuiUp:
|
||||
ViewProviderClone(cl.ViewObject)
|
||||
gui_utils.format_object(cl, obj[0])
|
||||
if len(obj) > 1 or hasattr(obj[0], "Group"):
|
||||
cl.ViewObject.Proxy.resetColors(cl.ViewObject)
|
||||
# Workaround to trigger update of DiffuseColor:
|
||||
# Note: only works if obj contains 1 object.
|
||||
ToDo.delay(lambda col: setattr(cl.ViewObject, "DiffuseColor", col),
|
||||
cl.ViewObject.DiffuseColor)
|
||||
gui_utils.select(cl)
|
||||
return cl
|
||||
|
||||
|
||||
|
||||
@@ -60,9 +60,16 @@ class Point(DraftObject):
|
||||
import Part
|
||||
shape = Part.Vertex(App.Vector(0, 0, 0))
|
||||
obj.Shape = shape
|
||||
obj.Placement.Base = App.Vector(obj.X.Value,
|
||||
obj.Y.Value,
|
||||
obj.Z.Value)
|
||||
if obj.Placement.Base != App.Vector(obj.X, obj.Y, obj.Z):
|
||||
obj.Placement.Base = App.Vector(obj.X, obj.Y, obj.Z)
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
if prop == "Placement" \
|
||||
and obj.Placement.Base != App.Vector(obj.X, obj.Y, obj.Z):
|
||||
base = obj.Placement.Base
|
||||
obj.X = base.x
|
||||
obj.Y = base.y
|
||||
obj.Z = base.z
|
||||
|
||||
|
||||
# Alias for compatibility with v0.18 and earlier
|
||||
|
||||
@@ -112,13 +112,13 @@ class DraftModification(unittest.TestCase):
|
||||
"'{}' failed".format(operation))
|
||||
|
||||
def test_offset_open(self):
|
||||
"""Create a wire, then produce an offset copy."""
|
||||
"""Create an open wire, then produce an offset copy."""
|
||||
operation = "Draft Offset"
|
||||
_msg(" Test '{}'".format(operation))
|
||||
a = Vector(0, 2, 0)
|
||||
b = Vector(2, 4, 0)
|
||||
c = Vector(5, 2, 0)
|
||||
_msg(" Wire")
|
||||
_msg(" Open wire")
|
||||
_msg(" a={0}, b={1}".format(a, b))
|
||||
_msg(" c={0}".format(c))
|
||||
wire = Draft.make_wire([a, b, c])
|
||||
@@ -130,22 +130,52 @@ class DraftModification(unittest.TestCase):
|
||||
obj = Draft.offset(wire, offset, copy=True)
|
||||
self.assertTrue(obj, "'{}' failed".format(operation))
|
||||
|
||||
def test_offset_closed(self):
|
||||
"""Create a rectangle, then produce an offset copy."""
|
||||
def test_offset_closed_with_reversed_edge(self):
|
||||
"""Create a closed wire with a reversed edge, then produce an offset copy."""
|
||||
# Regression test for:
|
||||
# https://github.com/FreeCAD/FreeCAD/pull/5496
|
||||
operation = "Draft Offset"
|
||||
_msg(" Test '{}'".format(operation))
|
||||
length = 4
|
||||
width = 2
|
||||
_msg(" Rectangle")
|
||||
_msg(" Closed wire with reversed edge")
|
||||
a = Vector(0, 0, 0)
|
||||
b = Vector(10, 0, 0)
|
||||
c = Vector(10, 4, 0)
|
||||
d = Vector(0, 4, 0)
|
||||
edges = [Part.makeLine(a, b),
|
||||
Part.makeLine(b, c),
|
||||
Part.makeLine(c, d),
|
||||
Part.makeLine(a, d)]
|
||||
wire = Part.Wire(edges)
|
||||
obj = App.ActiveDocument.addObject("Part::Feature")
|
||||
obj.Shape = wire
|
||||
|
||||
offset = Vector(0, -1, 0)
|
||||
new = Draft.offset(obj, offset, copy=True)
|
||||
self.assertTrue(len(new.Points) == 4, "'{}' failed".format(operation))
|
||||
|
||||
def test_offset_rectangle_with_face(self):
|
||||
"""Create a rectangle with a face, then produce an offset copy."""
|
||||
# Regression test for:
|
||||
# https://github.com/FreeCAD/FreeCAD/pull/7670
|
||||
operation = "Draft Offset"
|
||||
_msg(" Test '{}'".format(operation))
|
||||
length = 10
|
||||
width = 4
|
||||
_msg(" Rectangle with face")
|
||||
_msg(" length={0}, width={1}".format(length, width))
|
||||
rect = Draft.make_rectangle(length, width)
|
||||
rect.MakeFace = True
|
||||
App.ActiveDocument.recompute()
|
||||
|
||||
offset = Vector(-1, -1, 0)
|
||||
offset = Vector(0, -1, 0)
|
||||
_msg(" Offset")
|
||||
_msg(" vector={}".format(offset))
|
||||
obj = Draft.offset(rect, offset, copy=True)
|
||||
self.assertTrue(obj, "'{}' failed".format(operation))
|
||||
App.ActiveDocument.recompute()
|
||||
obj_is_ok = (obj.Shape.CenterOfGravity == Vector(5, 2, 0)
|
||||
and obj.Length == 12
|
||||
and obj.Height == 6)
|
||||
self.assertTrue(obj_is_ok, "'{}' failed".format(operation))
|
||||
|
||||
def test_trim(self):
|
||||
"""Trim a line. NOT IMPLEMENTED."""
|
||||
|
||||
@@ -39,6 +39,9 @@ class ViewProviderBezCurve(ViewProviderWire):
|
||||
def __init__(self, vobj):
|
||||
super(ViewProviderBezCurve, self).__init__(vobj)
|
||||
|
||||
def setupContextMenu(self, vobj, menu):
|
||||
return
|
||||
|
||||
|
||||
# Alias for compatibility with v0.18 and earlier
|
||||
_ViewProviderBezCurve = ViewProviderBezCurve
|
||||
|
||||
@@ -39,6 +39,9 @@ class ViewProviderBSpline(ViewProviderWire):
|
||||
def __init__(self, vobj):
|
||||
super(ViewProviderBSpline, self).__init__(vobj)
|
||||
|
||||
def setupContextMenu(self, vobj, menu):
|
||||
return
|
||||
|
||||
|
||||
# Alias for compatibility with v0.18 and earlier
|
||||
_ViewProviderBSpline = ViewProviderBSpline
|
||||
|
||||
@@ -56,22 +56,28 @@ class ViewProviderClone:
|
||||
colors = []
|
||||
for o in groups.get_group_contents(vobj.Object.Objects):
|
||||
if o.isDerivedFrom("Part::Feature"):
|
||||
if len(o.ViewObject.DiffuseColor) > 1:
|
||||
if len(o.ViewObject.DiffuseColor) == len(o.Shape.Faces):
|
||||
colors.extend(o.ViewObject.DiffuseColor)
|
||||
else:
|
||||
c = o.ViewObject.ShapeColor
|
||||
c = (c[0],c[1],c[2],o.ViewObject.Transparency/100.0)
|
||||
colors += [c] * len(o.Shape.Faces) # TODO: verify this line
|
||||
c = (c[0], c[1], c[2], o.ViewObject.Transparency / 100.0)
|
||||
colors += [c] * len(o.Shape.Faces)
|
||||
elif o.hasExtension("App::GeoFeatureGroupExtension"):
|
||||
for so in vobj.Object.Group:
|
||||
for so in o.Group:
|
||||
if so.isDerivedFrom("Part::Feature"):
|
||||
if len(so.ViewObject.DiffuseColor) > 1:
|
||||
if len(so.ViewObject.DiffuseColor) == len(so.Shape.Faces):
|
||||
colors.extend(so.ViewObject.DiffuseColor)
|
||||
else:
|
||||
c = so.ViewObject.ShapeColor
|
||||
c = (c[0],c[1],c[2],so.ViewObject.Transparency/100.0)
|
||||
c = (c[0], c[1], c[2], so.ViewObject.Transparency / 100.0)
|
||||
colors += [c] * len(so.Shape.Faces)
|
||||
if colors:
|
||||
first_color = colors[0]
|
||||
for next_color in colors[1:]:
|
||||
if next_color != first_color:
|
||||
break
|
||||
else:
|
||||
colors = [first_color]
|
||||
vobj.DiffuseColor = colors
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ They inherit their behavior from the base Annotation viewprovider.
|
||||
# \ingroup draftviewproviders
|
||||
# \brief Provides the viewprovider code for the Dimension objects.
|
||||
|
||||
import math
|
||||
import pivy.coin as coin
|
||||
import lazy_loader.lazy_loader as lz
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
@@ -396,6 +397,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase):
|
||||
self.marksDimOvershoot = coin.SoSeparator()
|
||||
self.marksExtOvershoot = coin.SoSeparator()
|
||||
self.drawstyle = coin.SoDrawStyle()
|
||||
import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object).
|
||||
self.line = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
|
||||
self.coords = coin.SoCoordinate3()
|
||||
|
||||
@@ -958,6 +960,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase):
|
||||
self.marks = coin.SoSeparator()
|
||||
self.drawstyle = coin.SoDrawStyle()
|
||||
self.coords = coin.SoCoordinate3()
|
||||
import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object).
|
||||
self.arc = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
|
||||
|
||||
self.node = coin.SoGroup()
|
||||
@@ -1117,27 +1120,32 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase):
|
||||
self.coord2.point.setValue(p3)
|
||||
|
||||
# Calculate small chords to make arrows look better
|
||||
arrowlength = 4 * vobj.ArrowSize.Value
|
||||
u1 = (self.circle.valueAt(first + arrowlength)
|
||||
- self.circle.valueAt(first)).normalize()
|
||||
u2 = (self.circle.valueAt(last)
|
||||
- self.circle.valueAt(last - arrowlength)).normalize()
|
||||
if hasattr(vobj, "FlipArrows") and vobj.FlipArrows:
|
||||
u1 = u1.negative()
|
||||
u2 = u2.negative()
|
||||
if vobj.ArrowSize.Value !=0 \
|
||||
and hasattr(vobj, "ScaleMultiplier") \
|
||||
and vobj.ScaleMultiplier != 0:
|
||||
halfarrowlength = 2 * vobj.ArrowSize.Value * vobj.ScaleMultiplier
|
||||
arrowangle = 2 * math.asin(halfarrowlength / radius)
|
||||
|
||||
w2 = self.circle.Curve.Axis
|
||||
w1 = w2.negative()
|
||||
u1 = (self.circle.valueAt(first + arrowangle)
|
||||
- self.circle.valueAt(first)).normalize()
|
||||
u2 = (self.circle.valueAt(last)
|
||||
- self.circle.valueAt(last - arrowangle)).normalize()
|
||||
if hasattr(vobj, "FlipArrows") and vobj.FlipArrows:
|
||||
u1 = u1.negative()
|
||||
u2 = u2.negative()
|
||||
|
||||
v1 = w1.cross(u1)
|
||||
v2 = w2.cross(u2)
|
||||
_plane_rot_1 = DraftVecUtils.getPlaneRotation(u1, v1, w1)
|
||||
_plane_rot_2 = DraftVecUtils.getPlaneRotation(u2, v2, w2)
|
||||
q1 = App.Placement(_plane_rot_1).Rotation.Q
|
||||
q2 = App.Placement(_plane_rot_2).Rotation.Q
|
||||
w2 = self.circle.Curve.Axis
|
||||
w1 = w2.negative()
|
||||
|
||||
self.trans1.rotation.setValue((q1[0], q1[1], q1[2], q1[3]))
|
||||
self.trans2.rotation.setValue((q2[0], q2[1], q2[2], q2[3]))
|
||||
v1 = w1.cross(u1)
|
||||
v2 = w2.cross(u2)
|
||||
_plane_rot_1 = DraftVecUtils.getPlaneRotation(u1, v1, w1)
|
||||
_plane_rot_2 = DraftVecUtils.getPlaneRotation(u2, v2, w2)
|
||||
q1 = App.Placement(_plane_rot_1).Rotation.Q
|
||||
q2 = App.Placement(_plane_rot_2).Rotation.Q
|
||||
|
||||
self.trans1.rotation.setValue((q1[0], q1[1], q1[2], q1[3]))
|
||||
self.trans2.rotation.setValue((q2[0], q2[1], q2[2], q2[3]))
|
||||
|
||||
# Set text position and rotation
|
||||
self.tbase = midp
|
||||
@@ -1194,7 +1202,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase):
|
||||
self.remove_dim_arrows()
|
||||
self.draw_dim_arrows(vobj)
|
||||
|
||||
self.updateData(obj, "Start")
|
||||
self.updateData(obj, None)
|
||||
# obj.touch()
|
||||
|
||||
elif prop == "FontSize" and "ScaleMultiplier" in properties:
|
||||
@@ -1222,9 +1230,11 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase):
|
||||
elif (prop in ("ArrowSize", "ArrowType")
|
||||
and "ScaleMultiplier" in properties
|
||||
and hasattr(self, "node") and hasattr(self, "p2")):
|
||||
self.updateData(obj, None)
|
||||
self.remove_dim_arrows()
|
||||
self.draw_dim_arrows(vobj)
|
||||
# obj.touch()
|
||||
|
||||
else:
|
||||
self.updateData(obj, None)
|
||||
|
||||
|
||||
@@ -39,4 +39,8 @@ class ViewProviderFillet(ViewProviderWire):
|
||||
def __init__(self, vobj):
|
||||
super(ViewProviderFillet, self).__init__(vobj)
|
||||
|
||||
def setupContextMenu(self, vobj, menu):
|
||||
return
|
||||
|
||||
|
||||
## @}
|
||||
|
||||
@@ -207,6 +207,8 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
|
||||
self.drawstyle = coin.SoDrawStyle()
|
||||
self.drawstyle.style = coin.SoDrawStyle.LINES
|
||||
|
||||
import PartGui # Required for "SoBrepEdgeSet" (because a label is not a Part::FeaturePython object).
|
||||
|
||||
self.lcoords = coin.SoCoordinate3()
|
||||
self.line = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
|
||||
|
||||
|
||||
@@ -39,11 +39,13 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
import FreeCAD as App
|
||||
import FreeCADGui as Gui
|
||||
import DraftVecUtils
|
||||
import DraftGeomUtils
|
||||
import draftgeoutils.wires as wires
|
||||
import draftutils.utils as utils
|
||||
import draftutils.gui_utils as gui_utils
|
||||
|
||||
from draftutils.messages import _msg
|
||||
from draftutils.translate import translate
|
||||
|
||||
from draftviewproviders.view_base import ViewProviderDraft
|
||||
|
||||
|
||||
@@ -146,32 +148,43 @@ class ViewProviderWire(ViewProviderDraft):
|
||||
return [self.Object.Base,self.Object.Tool]
|
||||
return []
|
||||
|
||||
def setupContextMenu(self,vobj,menu):
|
||||
def setupContextMenu(self, vobj, menu):
|
||||
action1 = QtGui.QAction(QtGui.QIcon(":/icons/Draft_Edit.svg"),
|
||||
"Flatten this wire",
|
||||
translate("draft", "Flatten"),
|
||||
menu)
|
||||
QtCore.QObject.connect(action1,
|
||||
QtCore.SIGNAL("triggered()"),
|
||||
self.flatten)
|
||||
menu.addAction(action1)
|
||||
|
||||
def flatten(self):
|
||||
if hasattr(self,"Object"):
|
||||
if len(self.Object.Shape.Wires) == 1:
|
||||
fw = DraftGeomUtils.flattenWire(self.Object.Shape.Wires[0])
|
||||
points = [v.Point for v in fw.Vertexes]
|
||||
if len(points) == len(self.Object.Points):
|
||||
if points != self.Object.Points:
|
||||
App.ActiveDocument.openTransaction("Flatten wire")
|
||||
Gui.doCommand("FreeCAD.ActiveDocument." +
|
||||
self.Object.Name +
|
||||
".Points=" +
|
||||
str(points).replace("Vector", "FreeCAD.Vector").replace(" " , ""))
|
||||
App.ActiveDocument.commitTransaction()
|
||||
def flatten(self): # Only to be used for Draft_Wires.
|
||||
if not hasattr(self, "Object"):
|
||||
return
|
||||
|
||||
else:
|
||||
_flat = "This Wire is already flat"
|
||||
_msg(QT_TRANSLATE_NOOP("Draft", _flat))
|
||||
if hasattr(App, "DraftWorkingPlane"):
|
||||
App.DraftWorkingPlane.setup()
|
||||
origin = App.DraftWorkingPlane.position
|
||||
normal = App.DraftWorkingPlane.axis
|
||||
# Align the grid for visual feedback:
|
||||
if hasattr(Gui, "Snapper"):
|
||||
Gui.Snapper.setTrackers()
|
||||
else:
|
||||
origin = App.Vector(0, 0, 0)
|
||||
normal = App.Vector(0, 0, 1)
|
||||
|
||||
flat_wire = wires.flattenWire(self.Object.Shape.Wires[0],
|
||||
origin=origin,
|
||||
normal=normal)
|
||||
|
||||
doc = App.ActiveDocument
|
||||
doc.openTransaction(translate("draft", "Flatten"))
|
||||
|
||||
self.Object.Placement = App.Placement()
|
||||
self.Object.Points = [vert.Point for vert in flat_wire.Vertexes]
|
||||
self.Object.Closed = flat_wire.isClosed()
|
||||
|
||||
doc.recompute()
|
||||
doc.commitTransaction()
|
||||
|
||||
|
||||
# Alias for compatibility with v0.18 and earlier
|
||||
|
||||
@@ -73,7 +73,7 @@ class ViewProviderWorkingPlaneProxy:
|
||||
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
c = param.GetUnsigned("ColorHelpers",674321151)
|
||||
vobj.LineColor = (float((c>>24)&0xFF)/255.0,float((c>>16)&0xFF)/255.0,float((c>>8)&0xFF)/255.0,0.0)
|
||||
|
||||
|
||||
vobj.Proxy = self
|
||||
vobj.RestoreView = True
|
||||
vobj.RestoreState = True
|
||||
@@ -133,6 +133,7 @@ class ViewProviderWorkingPlaneProxy:
|
||||
self.drawstyle = coin.SoDrawStyle()
|
||||
self.drawstyle.style = coin.SoDrawStyle.LINES
|
||||
self.lcoords = coin.SoCoordinate3()
|
||||
import PartGui # Required for "SoBrepEdgeSet" (because a WorkingPlaneProxy is not a Part::FeaturePython object).
|
||||
ls = coin.SoType.fromName("SoBrepEdgeSet").createInstance()
|
||||
ls.coordIndex.setValues(0,28,[0,1,-1,2,3,4,5,-1,6,7,-1,8,9,10,11,-1,12,13,-1,14,15,16,17,-1,18,19,20,21])
|
||||
sep = coin.SoSeparator()
|
||||
|
||||
@@ -10,6 +10,7 @@ include_directories(
|
||||
${OCC_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
${XercesC_INCLUDE_DIRS}
|
||||
)
|
||||
link_directories(${OCC_LIBRARY_DIR})
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ include_directories(
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
${OCC_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${XercesC_INCLUDE_DIRS}
|
||||
)
|
||||
link_directories(${OCC_LIBRARY_DIR})
|
||||
|
||||
|
||||
+18
-19
@@ -22,25 +22,13 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include <SMESH_Version.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Interpreter.h>
|
||||
#include <CXX/Extensions.hxx>
|
||||
|
||||
#include <SMESH_Version.h>
|
||||
#include "FemMeshPy.h"
|
||||
#include "FemMesh.h"
|
||||
#include "FemMeshProperty.h"
|
||||
#include "FemAnalysis.h"
|
||||
#include "FemMeshObject.h"
|
||||
#include "FemMeshShapeObject.h"
|
||||
#include "FemMeshShapeNetgenObject.h"
|
||||
|
||||
#include "FemSetElementsObject.h"
|
||||
#include "FemSetFacesObject.h"
|
||||
#include "FemSetGeometryObject.h"
|
||||
#include "FemSetNodesObject.h"
|
||||
|
||||
#include "HypothesisPy.h"
|
||||
#include "FemConstraintBearing.h"
|
||||
#include "FemConstraintFixed.h"
|
||||
#include "FemConstraintForce.h"
|
||||
@@ -56,17 +44,28 @@
|
||||
#include "FemConstraintFluidBoundary.h"
|
||||
#include "FemConstraintTransform.h"
|
||||
#include "FemConstraintSpring.h"
|
||||
|
||||
#include "FemMesh.h"
|
||||
#include "FemMeshObject.h"
|
||||
#include "FemMeshProperty.h"
|
||||
#include "FemMeshPy.h"
|
||||
#include "FemMeshShapeObject.h"
|
||||
#include "FemMeshShapeNetgenObject.h"
|
||||
#include "FemResultObject.h"
|
||||
#include "FemSetElementsObject.h"
|
||||
#include "FemSetFacesObject.h"
|
||||
#include "FemSetGeometryObject.h"
|
||||
#include "FemSetNodesObject.h"
|
||||
#include "FemSolverObject.h"
|
||||
#include "HypothesisPy.h"
|
||||
|
||||
#ifdef FC_USE_VTK
|
||||
#include "FemPostPipeline.h"
|
||||
#include "FemPostFilter.h"
|
||||
#include "FemPostFunction.h"
|
||||
#include "PropertyPostDataObject.h"
|
||||
# include "FemPostFilter.h"
|
||||
# include "FemPostFunction.h"
|
||||
# include "FemPostPipeline.h"
|
||||
# include "PropertyPostDataObject.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Fem {
|
||||
extern PyObject* initModule();
|
||||
}
|
||||
|
||||
@@ -21,62 +21,48 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <cmath> //OvG: Required for log10
|
||||
# include <TopoDS.hxx>
|
||||
# include <BRepGProp_Face.hxx>
|
||||
# include <gp_Vec.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Cylinder.hxx>
|
||||
# include <gp_Ax3.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <GCPnts_AbscissaPoint.hxx>
|
||||
# include <Adaptor3d_IsoCurve.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
# include <BRepGProp.hxx>
|
||||
# include <TopoDS_Vertex.hxx>
|
||||
# include <BRepClass_FaceClassifier.hxx>
|
||||
# include <BRep_Tool.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <BRepGProp.hxx>
|
||||
# include <BRepGProp_Face.hxx>
|
||||
# include <ShapeAnalysis.hxx>
|
||||
# include <GeomAPI_ProjectPointOnSurf.hxx>
|
||||
# include <GeomAPI_IntCS.hxx>
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <BRepClass_FaceClassifier.hxx>
|
||||
# include <GCPnts_AbscissaPoint.hxx>
|
||||
# include <Geom_Line.hxx>
|
||||
# include <Geom_Plane.hxx>
|
||||
# include <GeomAPI_IntCS.hxx>
|
||||
# include <GeomAPI_ProjectPointOnSurf.hxx>
|
||||
# include <gp_Cylinder.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Pnt.hxx>
|
||||
# include <gp_Vec.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
# include <Precision.hxx>
|
||||
# include <Standard_Version.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# include <TopoDS_Vertex.hxx>
|
||||
# if OCC_VERSION_HEX < 0x070600
|
||||
# include <Adaptor3d_HSurface.hxx>
|
||||
# include <BRepAdaptor_HSurface.hxx>
|
||||
# include <Adaptor3d_HSurface.hxx>
|
||||
# include <BRepAdaptor_HSurface.hxx>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "FemConstraint.h"
|
||||
#include "FemTools.h"
|
||||
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include <App/OriginFeature.h>
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
|
||||
#include "FemConstraint.h"
|
||||
#include "FemTools.h"
|
||||
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
// maybe in the c++ standard later, older compiler don't have round()
|
||||
#if _MSC_VER <= 1700
|
||||
double round(double r) {
|
||||
return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070600
|
||||
using Adaptor3d_HSurface = Adaptor3d_Surface;
|
||||
using BRepAdaptor_HSurface = BRepAdaptor_Surface;
|
||||
|
||||
@@ -21,17 +21,16 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef FEM_CONSTRAINT_H
|
||||
#define FEM_CONSTRAINT_H
|
||||
|
||||
#include <Base/Vector3D.h>
|
||||
#include <App/FeaturePython.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/FeaturePython.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
#include <App/PropertyGeo.h>
|
||||
#include <Base/Vector3D.h>
|
||||
#include <Mod/Fem/FemGlobal.h>
|
||||
|
||||
|
||||
namespace Fem {
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,23 +21,18 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#endif
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
|
||||
#include "FemConstraintBearing.h"
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
@@ -64,7 +59,6 @@ App::DocumentObjectExecReturn *ConstraintBearing::execute(void)
|
||||
|
||||
void ConstraintBearing::onChanged(const App::Property* prop)
|
||||
{
|
||||
//Base::Console().Error("ConstraintBearing: onChanged %s\n", prop->getName());
|
||||
// Note: If we call this at the end, then the symbol is not oriented correctly initially
|
||||
// because the NormalDirection has not been calculated yet
|
||||
Constraint::onChanged(prop);
|
||||
|
||||
@@ -21,16 +21,15 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef FEM_CONSTRAINTBEARING_H
|
||||
#define FEM_CONSTRAINTBEARING_H
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
#include <App/PropertyGeo.h>
|
||||
|
||||
#include "FemConstraint.h"
|
||||
|
||||
|
||||
namespace Fem
|
||||
{
|
||||
|
||||
|
||||
@@ -21,21 +21,11 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#endif
|
||||
|
||||
#include "FemConstraintContact.h"
|
||||
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
PROPERTY_SOURCE(Fem::ConstraintContact, Fem::Constraint)
|
||||
|
||||
@@ -23,21 +23,11 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#endif
|
||||
|
||||
#include "FemConstraintDisplacement.h"
|
||||
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
PROPERTY_SOURCE(Fem::ConstraintDisplacement, Fem::Constraint)
|
||||
|
||||
@@ -21,30 +21,10 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <GCPnts_AbscissaPoint.hxx>
|
||||
#include <Adaptor3d_IsoCurve.hxx>
|
||||
#include <GProp_GProps.hxx>
|
||||
#include <BRepGProp.hxx>
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <BRepClass_FaceClassifier.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <Precision.hxx>
|
||||
#endif
|
||||
|
||||
#include "FemConstraintFixed.h"
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
#ifndef FEM_CONSTRAINTFIXED_H
|
||||
#define FEM_CONSTRAINTFIXED_H
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/PropertyGeo.h>
|
||||
|
||||
#include "FemConstraint.h"
|
||||
|
||||
|
||||
|
||||
@@ -21,23 +21,16 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Pln.hxx>
|
||||
#include <gp_Lin.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <BRepAdaptor_Surface.hxx>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <Precision.hxx>
|
||||
# include <Precision.hxx>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
|
||||
#include "FemConstraintFluidBoundary.h"
|
||||
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
using namespace Fem;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user