Add support for using a SpaceMouse to pan & zoom in the schematic editor.
This commit is contained in:
parent
e8a543f1ea
commit
1a9ef4bd0f
|
@ -44,35 +44,6 @@
|
|||
*/
|
||||
const wxChar* NL_3D_VIEWER_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_3D_VIEWER_PLUGIN" );
|
||||
|
||||
/**
|
||||
* Template to compare two floating point values for equality within a required epsilon.
|
||||
*
|
||||
* @param aFirst value to compare.
|
||||
* @param aSecond value to compare.
|
||||
* @param aEpsilon allowed error.
|
||||
* @return true if the values considered equal within the specified epsilon, otherwise false.
|
||||
*/
|
||||
template <class T>
|
||||
bool equals( T aFirst, T aSecond, T aEpsilon = static_cast<T>( FLT_EPSILON ) )
|
||||
{
|
||||
T diff = fabs( aFirst - aSecond );
|
||||
|
||||
if( diff < aEpsilon )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
aFirst = fabs( aFirst );
|
||||
aSecond = fabs( aSecond );
|
||||
T largest = aFirst > aSecond ? aFirst : aSecond;
|
||||
|
||||
if( diff <= largest * aEpsilon )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to compare two glm::mat<T> values for equality within a required epsilon.
|
||||
|
@ -245,13 +216,13 @@ void NL_3D_VIEWER_PLUGIN_IMPL::exportCommandsAndImages()
|
|||
streamBuffer->GetBufferSize() ),
|
||||
0 );
|
||||
|
||||
wxLogTrace( m_logTrace, "Adding image for : %s", name );
|
||||
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
||||
vImages.push_back( std::move( tdxImage ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( m_logTrace, "Inserting command: %s, description: %s, in category: %s", name,
|
||||
description, iter->first );
|
||||
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
||||
name, description, iter->first );
|
||||
|
||||
iter->second->push_back(
|
||||
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
||||
|
@ -681,7 +652,7 @@ long NL_3D_VIEWER_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const
|
|||
long NL_3D_VIEWER_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
// Use the right-handed coordinate system X-right, Z-up, Y-in (row vectors)
|
||||
matrix = { 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1 };
|
||||
matrix = { 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1 };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -255,6 +255,19 @@ void EDA_3D_VIEWER_FRAME::setupUIConditions()
|
|||
}
|
||||
|
||||
|
||||
void EDA_3D_VIEWER_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
|
||||
{
|
||||
KIWAY_PLAYER::handleIconizeEvent( aEvent );
|
||||
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
if( m_spaceMouse != nullptr && aEvent.IsIconized() )
|
||||
{
|
||||
m_spaceMouse->SetFocus( false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_VIEWER_FRAME::ReloadRequest()
|
||||
{
|
||||
// This will schedule a request to load later
|
||||
|
|
|
@ -120,6 +120,8 @@ public:
|
|||
protected:
|
||||
void setupUIConditions() override;
|
||||
|
||||
void handleIconizeEvent( wxIconizeEvent& aEvent ) override;
|
||||
|
||||
private:
|
||||
/// Called when user press the File->Exit
|
||||
void Exit3DFrame( wxCommandEvent& event );
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -8,6 +8,8 @@ KiCad EDA suite by the KiCad project or any third party, e.g. Linux distributor.
|
|||
|
||||
You are free to use the *sources* under the terms of their respective licenses.
|
||||
|
||||
Licensed under Apache License, Version 2.0
|
||||
- portions of code in libs/kimath/include/math/util.h
|
||||
Licensed under BOOSTv1:
|
||||
- libcontext [https://github.com/boostorg/context] in thirdparty/libcontext
|
||||
- clipper in thirdparty/clipper
|
||||
|
|
|
@ -107,6 +107,7 @@ BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
|
|||
EVT_MAXIMIZE( EDA_BASE_FRAME::OnMaximize )
|
||||
|
||||
EVT_SYS_COLOUR_CHANGED( EDA_BASE_FRAME::onSystemColorChange )
|
||||
EVT_ICONIZE( EDA_BASE_FRAME::onIconize )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
|
@ -1325,6 +1326,16 @@ void EDA_BASE_FRAME::onSystemColorChange( wxSysColourChangedEvent& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void EDA_BASE_FRAME::onIconize( wxIconizeEvent& aEvent )
|
||||
{
|
||||
// Call the handler
|
||||
handleIconizeEvent( aEvent );
|
||||
|
||||
// Skip the event.
|
||||
aEvent.Skip();
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
WXLRESULT EDA_BASE_FRAME::MSWWindowProc( WXUINT message, WXWPARAM wParam, WXLPARAM lParam )
|
||||
{
|
||||
|
|
|
@ -435,6 +435,13 @@ if( KICAD_SPICE )
|
|||
)
|
||||
endif()
|
||||
|
||||
if( KICAD_USE_3DCONNEXION )
|
||||
message( STATUS "Including 3Dconnexion SpaceMouse navigation support in eeschema" )
|
||||
add_subdirectory( ./navlib )
|
||||
target_link_libraries( eeschema_kiface PRIVATE eeschema_navlib)
|
||||
endif()
|
||||
|
||||
|
||||
set_target_properties( eeschema_kiface PROPERTIES
|
||||
# Decorate OUTPUT_NAME with PREFIX and SUFFIX, creating something like
|
||||
# _eeschema.so, _eeschema.dll, or _eeschema.kiface
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
if( KICAD_USE_3DCONNEXION )
|
||||
add_library(eeschema_navlib STATIC
|
||||
"nl_schematic_plugin.cpp"
|
||||
"nl_schematic_plugin_impl.cpp"
|
||||
)
|
||||
|
||||
# eeschema_navlib depends on make_lexer outputs in common
|
||||
add_dependencies( eeschema_navlib common )
|
||||
|
||||
# Find the 3DxWare SDK component 3DxWare::NlClient
|
||||
# find_package(TDxWare_SDK 4.0 REQUIRED COMPONENTS 3DxWare::Navlib)
|
||||
target_compile_definitions(eeschema_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
target_compile_options(eeschema_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_OPTIONS>
|
||||
)
|
||||
target_include_directories(eeschema_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:eeschema_kiface_objects,INCLUDE_DIRECTORIES>
|
||||
)
|
||||
target_link_libraries(eeschema_navlib
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_LINK_LIBRARIES>
|
||||
3DxWare::Navlib
|
||||
)
|
||||
else()
|
||||
add_library(eeschema_navlib STATIC
|
||||
"nl_schematic_plugin.cpp"
|
||||
)
|
||||
endif(KICAD_USE_3DCONNEXION)
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 3Dconnexion
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nl_schematic_plugin.h"
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
|
||||
#include "nl_schematic_plugin_impl.h"
|
||||
|
||||
|
||||
NL_SCHEMATIC_PLUGIN::NL_SCHEMATIC_PLUGIN() : m_impl( new NL_SCHEMATIC_PLUGIN_IMPL() )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NL_SCHEMATIC_PLUGIN::~NL_SCHEMATIC_PLUGIN()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
|
||||
void NL_SCHEMATIC_PLUGIN::SetFocus( bool focus )
|
||||
{
|
||||
m_impl->SetFocus( focus );
|
||||
}
|
||||
|
||||
|
||||
void NL_SCHEMATIC_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport )
|
||||
{
|
||||
m_impl->SetCanvas( aViewport );
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
NL_SCHEMATIC_PLUGIN::NL_SCHEMATIC_PLUGIN( EDA_DRAW_PANEL_GAL* aViewport )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void NL_SCHEMATIC_PLUGIN::SetFocus( bool focus )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void NL_SCHEMATIC_PLUGIN::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NL_SCHEMATIC_PLUGIN::~NL_SCHEMATIC_PLUGIN()
|
||||
{
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 3Dconnexion
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_schematic_plugin.h
|
||||
* @brief Declaration of the NL_SCHEMATIC_PLUGIN class
|
||||
*/
|
||||
|
||||
#ifndef NL_SCHEMATIC_PLUGIN_H_
|
||||
#define NL_SCHEMATIC_PLUGIN_H_
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_DRAW_PANEL_GAL;
|
||||
class NL_SCHEMATIC_PLUGIN_IMPL;
|
||||
|
||||
/**
|
||||
* The class that implements the public interface to the SpaceMouse plug-in.
|
||||
*/
|
||||
class NL_SCHEMATIC_PLUGIN
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_SCHEMATIC_PLUGIN.
|
||||
*/
|
||||
NL_SCHEMATIC_PLUGIN();
|
||||
|
||||
virtual ~NL_SCHEMATIC_PLUGIN();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the viewport controlled by the SpaceMouse.
|
||||
*
|
||||
* @param aViewport is the viewport to be navigated.
|
||||
*/
|
||||
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport );
|
||||
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed to this connexion.
|
||||
*
|
||||
* @param aFocus is true to set the connexion active.
|
||||
*/
|
||||
void SetFocus( bool aFocus );
|
||||
|
||||
private:
|
||||
NL_SCHEMATIC_PLUGIN_IMPL* m_impl;
|
||||
};
|
||||
|
||||
#endif // NL_SCHEMATIC_PLUGIN_H_
|
|
@ -0,0 +1,608 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 3Dconnexion
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nl_schematic_plugin_impl.h"
|
||||
|
||||
// KiCAD includes
|
||||
#include <sch_base_frame.h>
|
||||
#include <bitmaps.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
#include <view/view.h>
|
||||
#include <view/wx_view_controls.h>
|
||||
#include <tool/action_manager.h>
|
||||
#include <tool/tool_action.h>
|
||||
#include <tool/tool_manager.h>
|
||||
|
||||
// stdlib
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cfloat>
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/mstream.h>
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable the NL_SCHEMATIC_PLUGIN debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_NL_SCHEMATIC_PLUGIN" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* NL_SCHEMATIC_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_SCHEMATIC_PLUGIN" );
|
||||
|
||||
|
||||
NL_SCHEMATIC_PLUGIN_IMPL::NL_SCHEMATIC_PLUGIN_IMPL() :
|
||||
CNavigation3D( false, false ), m_viewport2D( nullptr ), m_isMoving( false )
|
||||
{
|
||||
PutProfileHint( "KiCAD Eeschema" );
|
||||
}
|
||||
|
||||
|
||||
NL_SCHEMATIC_PLUGIN_IMPL::~NL_SCHEMATIC_PLUGIN_IMPL()
|
||||
{
|
||||
EnableNavigation( false );
|
||||
}
|
||||
|
||||
|
||||
void NL_SCHEMATIC_PLUGIN_IMPL::SetCanvas( EDA_DRAW_PANEL_GAL* aViewport )
|
||||
{
|
||||
bool init = m_viewport2D == nullptr;
|
||||
|
||||
m_viewport2D = aViewport;
|
||||
|
||||
if( m_viewport2D != nullptr )
|
||||
{
|
||||
m_view = static_cast<KIGFX::SCH_VIEW*>( m_viewport2D->GetView() );
|
||||
m_viewportWidth = m_view->GetBoundary().GetWidth();
|
||||
|
||||
if( init )
|
||||
{
|
||||
// Use the default settings for the connexion to the 3DMouse navigation
|
||||
// They are use a single-threaded threading model and row vectors.
|
||||
EnableNavigation( true );
|
||||
|
||||
// Use the SpaceMouse internal timing source for the frame rate.
|
||||
PutFrameTimingSource( TimingSource::SpaceMouse );
|
||||
|
||||
exportCommandsAndImages();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NL_SCHEMATIC_PLUGIN_IMPL::SetFocus( bool aFocus )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "NL_SCHEMATIC_PLUGIN_IMPL::SetFocus %d" ), aFocus );
|
||||
NAV_3D::Write( navlib::focus_k, aFocus );
|
||||
}
|
||||
|
||||
// temporary store for the command categories
|
||||
typedef std::map<std::string, TDx::CCommandTreeNode*> CATEGORY_STORE;
|
||||
|
||||
|
||||
/**
|
||||
* Add a category to the store.
|
||||
*
|
||||
* The function adds category paths of the format "A.B" where B is a sub-category of A.
|
||||
*
|
||||
* @param aCategoryPath is the std::string representation of the category.
|
||||
* @param aCategoryStore is the CATEGORY_STORE instance to add to.
|
||||
* @return a CATEGORY_STORE::iterator where the category was added.
|
||||
*/
|
||||
static CATEGORY_STORE::iterator add_category( std::string aCategoryPath,
|
||||
CATEGORY_STORE& aCategoryStore )
|
||||
{
|
||||
using TDx::SpaceMouse::CCategory;
|
||||
|
||||
CATEGORY_STORE::iterator parent_iter = aCategoryStore.begin();
|
||||
std::string::size_type pos = aCategoryPath.find_last_of( '.' );
|
||||
|
||||
if( pos != std::string::npos )
|
||||
{
|
||||
std::string parentPath = aCategoryPath.substr( 0, pos );
|
||||
parent_iter = aCategoryStore.find( parentPath );
|
||||
|
||||
if( parent_iter == aCategoryStore.end() )
|
||||
{
|
||||
parent_iter = add_category( parentPath, aCategoryStore );
|
||||
}
|
||||
}
|
||||
|
||||
std::string name = aCategoryPath.substr( pos + 1 );
|
||||
std::unique_ptr<CCategory> categoryNode =
|
||||
std::make_unique<CCategory>( aCategoryPath.c_str(), name.c_str() );
|
||||
|
||||
CATEGORY_STORE::iterator iter = aCategoryStore.insert(
|
||||
aCategoryStore.end(), CATEGORY_STORE::value_type( aCategoryPath, categoryNode.get() ) );
|
||||
|
||||
parent_iter->second->push_back( std::move( categoryNode ) );
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
void NL_SCHEMATIC_PLUGIN_IMPL::exportCommandsAndImages()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "NL_SCHEMATIC_PLUGIN_IMPL::exportCommandsAndImages" ) );
|
||||
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
|
||||
if( actions.size() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using TDx::SpaceMouse::CCommand;
|
||||
using TDx::SpaceMouse::CCommandSet;
|
||||
|
||||
// The root action set node
|
||||
CCommandSet commandSet( "SCHEMATIC_EDITOR", "Schematic Editor" );
|
||||
|
||||
// Activate the command set
|
||||
NAV_3D::PutActiveCommands( commandSet.GetId() );
|
||||
|
||||
// temporary store for the categories
|
||||
CATEGORY_STORE categoryStore;
|
||||
|
||||
std::vector<TDx::CImage> vImages;
|
||||
|
||||
// add the action set to the category_store
|
||||
categoryStore.insert( categoryStore.end(), CATEGORY_STORE::value_type( ".", &commandSet ) );
|
||||
|
||||
std::list<TOOL_ACTION*>::const_iterator it;
|
||||
|
||||
for( it = actions.begin(); it != actions.end(); ++it )
|
||||
{
|
||||
const TOOL_ACTION* action = *it;
|
||||
std::string label = action->GetLabel().ToStdString();
|
||||
|
||||
if( label.empty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string name = action->GetName();
|
||||
|
||||
// Do no export commands for the 3DViewer app.
|
||||
|
||||
if( name.rfind( "3DViewer.", 0 ) == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string strCategory = action->GetToolName();
|
||||
CATEGORY_STORE::iterator iter = categoryStore.find( strCategory );
|
||||
|
||||
if( iter == categoryStore.end() )
|
||||
{
|
||||
iter = add_category( std::move( strCategory ), categoryStore );
|
||||
}
|
||||
|
||||
std::string description = action->GetDescription().ToStdString();
|
||||
|
||||
// Arbitrary 8-bit data stream
|
||||
wxMemoryOutputStream imageStream;
|
||||
|
||||
if( action->GetIcon() != BITMAPS::INVALID_BITMAP )
|
||||
{
|
||||
wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage();
|
||||
image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG );
|
||||
image.Destroy();
|
||||
|
||||
if( imageStream.GetSize() )
|
||||
{
|
||||
wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer();
|
||||
TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() );
|
||||
tdxImage.AssignImage( std::string( reinterpret_cast<const char*>(
|
||||
streamBuffer->GetBufferStart() ),
|
||||
streamBuffer->GetBufferSize() ),
|
||||
0 );
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
||||
vImages.push_back( std::move( tdxImage ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
||||
name, description, iter->first );
|
||||
|
||||
iter->second->push_back(
|
||||
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
||||
}
|
||||
|
||||
NAV_3D::AddCommandSet( commandSet );
|
||||
NAV_3D::AddImages( vImages );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetCameraMatrix( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
m_viewPosition = m_view->GetCenter();
|
||||
|
||||
double x = m_view->IsMirroredX() ? -1 : 1;
|
||||
double y = m_view->IsMirroredY() ? 1 : -1;
|
||||
|
||||
// x * y * z = 1 for a right-handed coordinate system.
|
||||
double z = x * y;
|
||||
|
||||
// Note: the connexion has been configured as row vectors, the coordinate system is defined in
|
||||
// NL_SCHEMATIC_PLUGIN_IMPL::GetCoordinateSystem and the front view in NL_SCHEMATIC_PLUGIN_IMPL::GetFrontView.
|
||||
matrix = { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, m_viewPosition.x, m_viewPosition.y, 0, 1 };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetPointerPosition( navlib::point_t& position ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
VECTOR2D mouse_pointer = m_viewport2D->GetViewControls()->GetMousePosition();
|
||||
|
||||
position.x = mouse_pointer.x;
|
||||
position.y = mouse_pointer.y;
|
||||
position.z = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetViewExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
double scale = m_viewport2D->GetGAL()->GetWorldScale();
|
||||
BOX2D box = m_view->GetViewport();
|
||||
|
||||
m_viewportWidth = box.GetWidth();
|
||||
|
||||
extents = navlib::box_t{ -box.GetWidth() / 2.0,
|
||||
-box.GetHeight() / 2.0,
|
||||
m_viewport2D->GetGAL()->GetMinDepth() / scale,
|
||||
box.GetWidth() / 2.0,
|
||||
box.GetHeight() / 2.0,
|
||||
m_viewport2D->GetGAL()->GetMaxDepth() / scale };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetIsViewPerspective( navlib::bool_t& perspective ) const
|
||||
{
|
||||
perspective = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& matrix )
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
long result = 0;
|
||||
VECTOR2D viewPos( matrix.m4x4[3][0], matrix.m4x4[3][1] );
|
||||
|
||||
if( !equals( m_view->GetCenter(), m_viewPosition,
|
||||
static_cast<VECTOR2D::coord_type>( FLT_EPSILON ) ) )
|
||||
{
|
||||
m_view->SetCenter( viewPos + m_view->GetCenter() - m_viewPosition );
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_view->SetCenter( viewPos );
|
||||
}
|
||||
|
||||
m_viewPosition = viewPos;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents )
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
long result = 0;
|
||||
|
||||
if( m_viewportWidth != m_view->GetViewport().GetWidth() )
|
||||
{
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
|
||||
double width = m_viewportWidth;
|
||||
m_viewportWidth = extents.max_x - extents.min_x;
|
||||
|
||||
double scale = width / m_viewportWidth * m_view->GetScale();
|
||||
m_view->SetScale( scale, m_view->GetCenter() );
|
||||
|
||||
if( !equals( m_view->GetScale(), scale, static_cast<double>( FLT_EPSILON ) ) )
|
||||
{
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetViewFOV( double fov )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetViewFrustum( const navlib::frustum_t& frustum )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
if( m_view == nullptr )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
BOX2I box = static_cast<SCH_BASE_FRAME*>( m_viewport2D->GetParent() )->GetDocumentExtents();
|
||||
box.Normalize();
|
||||
|
||||
double half_depth = 0.1 / m_viewport2D->GetGAL()->GetWorldScale();
|
||||
|
||||
if( box.GetWidth() == 0 && box.GetHeight() == 0 )
|
||||
{
|
||||
half_depth = 0;
|
||||
}
|
||||
|
||||
extents = { static_cast<double>( box.GetOrigin().x ),
|
||||
static_cast<double>( box.GetOrigin().y ),
|
||||
-half_depth,
|
||||
static_cast<double>( box.GetEnd().x ),
|
||||
static_cast<double>( box.GetEnd().y ),
|
||||
half_depth };
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
// The coordinate system is defined as x to the right, y down and z into the screen.
|
||||
matrix = { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const
|
||||
{
|
||||
matrix = { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 };
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetIsSelectionEmpty( navlib::bool_t& empty ) const
|
||||
{
|
||||
empty = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetIsViewRotatable( navlib::bool_t& isRotatable ) const
|
||||
{
|
||||
isRotatable = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetActiveCommand( std::string commandId )
|
||||
{
|
||||
if( commandId.empty() )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
TOOL_ACTION* context = nullptr;
|
||||
|
||||
for( std::list<TOOL_ACTION*>::const_iterator it = actions.begin(); it != actions.end(); it++ )
|
||||
{
|
||||
TOOL_ACTION* action = *it;
|
||||
std::string nm = action->GetName();
|
||||
|
||||
if( commandId == nm )
|
||||
{
|
||||
context = action;
|
||||
}
|
||||
}
|
||||
|
||||
if( context != nullptr )
|
||||
{
|
||||
wxWindow* parent = m_viewport2D->GetParent();
|
||||
|
||||
// Only allow command execution if the window is enabled. i.e. there is not a modal dialog
|
||||
// currently active.
|
||||
|
||||
if( parent->IsEnabled() )
|
||||
{
|
||||
TOOL_MANAGER* tool_manager = static_cast<SCH_BASE_FRAME*>( parent )->GetToolManager();
|
||||
|
||||
// Get the selection to use to test if the action is enabled
|
||||
SELECTION& sel = tool_manager->GetToolHolder()->GetCurrentSelection();
|
||||
|
||||
bool runAction = true;
|
||||
|
||||
if( const ACTION_CONDITIONS* aCond =
|
||||
tool_manager->GetActionManager()->GetCondition( *context ) )
|
||||
{
|
||||
runAction = aCond->enableCondition( sel );
|
||||
}
|
||||
|
||||
if( runAction )
|
||||
{
|
||||
tool_manager->RunAction( *context, true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetSettingsChanged( long change )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetMotionFlag( bool value )
|
||||
{
|
||||
m_isMoving = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetTransaction( long value )
|
||||
{
|
||||
if( value == 0L )
|
||||
{
|
||||
m_viewport2D->ForceRefresh();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetViewFOV( double& fov ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetViewFrustum( navlib::frustum_t& frustum ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetSelectionExtents( navlib::box_t& extents ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetSelectionTransform( navlib::matrix_t& transform ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetSelectionTransform( const navlib::matrix_t& matrix )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetPivotPosition( navlib::point_t& position ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::IsUserPivot( navlib::bool_t& userPivot ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetPivotPosition( const navlib::point_t& position )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetPivotVisible( navlib::bool_t& visible ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetPivotVisible( bool visible )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::GetHitLookAt( navlib::point_t& position ) const
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::no_data_available );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetHitAperture( double aperture )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetHitDirection( const navlib::vector_t& direction )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetHitLookFrom( const navlib::point_t& eye )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetHitSelectionOnly( bool onlySelection )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
||||
|
||||
|
||||
long NL_SCHEMATIC_PLUGIN_IMPL::SetCameraTarget( const navlib::point_t& position )
|
||||
{
|
||||
return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2022 3Dconnexion
|
||||
* Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file nl_schematic_plugin_impl.h
|
||||
* @brief Declaration of the NL_SCHEMATIC_PLUGIN_IMPL class
|
||||
*/
|
||||
|
||||
#ifndef NL_SCHEMATIC_PLUGIN_IMPL_H_
|
||||
#define NL_SCHEMATIC_PLUGIN_IMPL_H_
|
||||
|
||||
#if _WIN32
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0603
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// TDxWare SDK.
|
||||
#include <SpaceMouse/CNavigation3D.hpp>
|
||||
|
||||
// wx
|
||||
#include <wx/chartype.h>
|
||||
|
||||
// KiCAD
|
||||
#include <math/vector2d.h>
|
||||
|
||||
// stdlib
|
||||
#include <string>
|
||||
|
||||
// Forward declarations.
|
||||
class EDA_DRAW_PANEL_GAL;
|
||||
namespace KIGFX
|
||||
{
|
||||
class SCH_VIEW;
|
||||
}
|
||||
|
||||
// Convenience typedef.
|
||||
typedef TDx::SpaceMouse::Navigation3D::CNavigation3D NAV_3D;
|
||||
|
||||
/**
|
||||
* The class that implements the accessors and mutators required for
|
||||
* 3D navigation in an PCB_DRAW_PANEL_GAL using a SpaceMouse.
|
||||
*/
|
||||
class NL_SCHEMATIC_PLUGIN_IMPL : public NAV_3D
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Initializes a new instance of the NL_SCHEMATIC_PLUGIN_IMPL.
|
||||
*/
|
||||
NL_SCHEMATIC_PLUGIN_IMPL();
|
||||
|
||||
|
||||
virtual ~NL_SCHEMATIC_PLUGIN_IMPL();
|
||||
|
||||
|
||||
/**
|
||||
* Sets the viewport controlled by the SpaceMouse.
|
||||
*
|
||||
* @param aViewport is the viewport to be navigated.
|
||||
*/
|
||||
void SetCanvas( EDA_DRAW_PANEL_GAL* aViewport );
|
||||
|
||||
|
||||
/**
|
||||
* Set the connection to the 3Dconnexion driver to the focus state so that
|
||||
* 3DMouse data is routed here.
|
||||
*
|
||||
* @param aFocus is true to set the connection active.
|
||||
*/
|
||||
void SetFocus( bool aFocus );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Export the invocable actions and images to the 3Dconnexion UI.
|
||||
*/
|
||||
void exportCommandsAndImages();
|
||||
|
||||
long GetCameraMatrix( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetPointerPosition( navlib::point_t& aPosition ) const override;
|
||||
long GetViewExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetViewFOV( double& aFov ) const override;
|
||||
long GetViewFrustum( navlib::frustum_t& aFrustum ) const override;
|
||||
long GetIsViewPerspective( navlib::bool_t& aPerspective ) const override;
|
||||
long SetCameraMatrix( const navlib::matrix_t& aMatrix ) override;
|
||||
long SetViewExtents( const navlib::box_t& aExtents ) override;
|
||||
long SetViewFOV( double aFov ) override;
|
||||
long SetViewFrustum( const navlib::frustum_t& aFrustum ) override;
|
||||
long GetModelExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetSelectionExtents( navlib::box_t& aExtents ) const override;
|
||||
long GetSelectionTransform( navlib::matrix_t& aTransform ) const override;
|
||||
long GetIsSelectionEmpty( navlib::bool_t& aEmpty ) const override;
|
||||
long SetSelectionTransform( const navlib::matrix_t& aMatrix ) override;
|
||||
long GetPivotPosition( navlib::point_t& aPosition ) const override;
|
||||
long IsUserPivot( navlib::bool_t& aUserPivot ) const override;
|
||||
long SetPivotPosition( const navlib::point_t& aPosition ) override;
|
||||
long GetPivotVisible( navlib::bool_t& aVisible ) const override;
|
||||
long SetPivotVisible( bool aVisible ) override;
|
||||
long GetHitLookAt( navlib::point_t& aPosition ) const override;
|
||||
long SetHitAperture( double aAperture ) override;
|
||||
long SetHitDirection( const navlib::vector_t& aDirection ) override;
|
||||
long SetHitLookFrom( const navlib::point_t& aPosition ) override;
|
||||
long SetHitSelectionOnly( bool aSelectionOnly ) override;
|
||||
long SetActiveCommand( std::string aCommandId ) override;
|
||||
|
||||
long SetSettingsChanged( long aChangeNumber ) override;
|
||||
long SetMotionFlag( bool aValue ) override;
|
||||
long SetTransaction( long aValue ) override;
|
||||
long SetCameraTarget( const navlib::point_t& aPosition ) override;
|
||||
|
||||
long GetFrontView( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetCoordinateSystem( navlib::matrix_t& aMatrix ) const override;
|
||||
long GetIsViewRotatable( navlib::bool_t& isRotatable ) const override;
|
||||
|
||||
private:
|
||||
EDA_DRAW_PANEL_GAL* m_viewport2D;
|
||||
KIGFX::SCH_VIEW* m_view;
|
||||
bool m_isMoving;
|
||||
mutable double m_viewportWidth;
|
||||
mutable VECTOR2D m_viewPosition;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||
* "KI_TRACE_NL_SCHEMATIC_PLUGIN". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
};
|
||||
|
||||
#endif // NL_SCHEMATIC_PLUGIN_IMPL
|
|
@ -42,6 +42,9 @@
|
|||
#include <tools/ee_actions.h>
|
||||
#include <tools/ee_selection_tool.h>
|
||||
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
#include <navlib/nl_schematic_plugin.h>
|
||||
#endif
|
||||
|
||||
LIB_SYMBOL* SchGetLibSymbol( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable,
|
||||
SYMBOL_LIB* aCacheLib, wxWindow* aParent, bool aShowErrorMsg )
|
||||
|
@ -81,8 +84,9 @@ LIB_SYMBOL* SchGetLibSymbol( const LIB_ID& aLibId, SYMBOL_LIB_TABLE* aLibTable,
|
|||
SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindowType,
|
||||
const wxString& aTitle, const wxPoint& aPosition,
|
||||
const wxSize& aSize, long aStyle, const wxString& aFrameName ) :
|
||||
EDA_DRAW_FRAME( aKiway, aParent, aWindowType, aTitle, aPosition, aSize, aStyle, aFrameName ),
|
||||
m_base_frame_defaults( nullptr, "base_Frame_defaults" )
|
||||
EDA_DRAW_FRAME( aKiway, aParent, aWindowType, aTitle, aPosition, aSize, aStyle,
|
||||
aFrameName ),
|
||||
m_base_frame_defaults( nullptr, "base_Frame_defaults" )
|
||||
{
|
||||
createCanvas();
|
||||
|
||||
|
@ -300,6 +304,28 @@ void SCH_BASE_FRAME::createCanvas()
|
|||
}
|
||||
|
||||
|
||||
void SCH_BASE_FRAME::ActivateGalCanvas()
|
||||
{
|
||||
EDA_DRAW_FRAME::ActivateGalCanvas();
|
||||
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
try
|
||||
{
|
||||
if( !m_spaceMouse )
|
||||
{
|
||||
m_spaceMouse = std::make_unique<NL_SCHEMATIC_PLUGIN>();
|
||||
}
|
||||
|
||||
m_spaceMouse->SetCanvas( GetCanvas() );
|
||||
}
|
||||
catch( const std::system_error& e )
|
||||
{
|
||||
wxLogTrace( wxT( "KI_TRACE_NAVLIB" ), e.what() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SCH_BASE_FRAME::UpdateItem( EDA_ITEM* aItem, bool isAddOrDelete, bool aUpdateRtree )
|
||||
{
|
||||
EDA_ITEM* parent = aItem->GetParent();
|
||||
|
@ -471,3 +497,28 @@ COLOR4D SCH_BASE_FRAME::GetDrawBgColor() const
|
|||
return GetColorSettings()->GetColor( LAYER_SCHEMATIC_BACKGROUND );
|
||||
}
|
||||
|
||||
|
||||
void SCH_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent )
|
||||
{
|
||||
EDA_DRAW_FRAME::handleActivateEvent( aEvent );
|
||||
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
if( m_spaceMouse )
|
||||
{
|
||||
m_spaceMouse->SetFocus( aEvent.GetActive() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SCH_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
|
||||
{
|
||||
EDA_DRAW_FRAME::handleIconizeEvent( aEvent );
|
||||
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
if( m_spaceMouse && aEvent.IsIconized() )
|
||||
{
|
||||
m_spaceMouse->SetFocus( false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -58,6 +58,10 @@ class SYMBOL_LIB_TABLE;
|
|||
class EESCHEMA_SETTINGS;
|
||||
class SYMBOL_EDITOR_SETTINGS;
|
||||
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
class NL_SCHEMATIC_PLUGIN;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Load symbol from symbol library table.
|
||||
*
|
||||
|
@ -241,7 +245,13 @@ public:
|
|||
|
||||
COLOR_SETTINGS* GetColorSettings( bool aForceRefresh = false ) const override;
|
||||
|
||||
void ActivateGalCanvas() override;
|
||||
|
||||
protected:
|
||||
void handleActivateEvent( wxActivateEvent& aEvent ) override;
|
||||
|
||||
void handleIconizeEvent( wxIconizeEvent& aEvent ) override;
|
||||
|
||||
/**
|
||||
* Save Symbol Library Tables to disk.
|
||||
*
|
||||
|
@ -254,6 +264,11 @@ protected:
|
|||
/// These are only used by symbol_editor. Eeschema should be using the one inside
|
||||
/// the SCHEMATIC.
|
||||
SCHEMATIC_SETTINGS m_base_frame_defaults;
|
||||
|
||||
private:
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
std::unique_ptr<NL_SCHEMATIC_PLUGIN> m_spaceMouse;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SCH_BASE_FRAME_H_
|
||||
|
|
|
@ -606,6 +606,15 @@ protected:
|
|||
*/
|
||||
void onAutoSaveTimer( wxTimerEvent& aEvent );
|
||||
|
||||
|
||||
/**
|
||||
* Handle a window iconize event.
|
||||
*
|
||||
* @param aEvent is the data for the event.
|
||||
*/
|
||||
virtual void handleIconizeEvent( wxIconizeEvent& aEvent ) {}
|
||||
void onIconize( wxIconizeEvent& aEvent );
|
||||
|
||||
/**
|
||||
* Return the auto save status of the application.
|
||||
*
|
||||
|
|
|
@ -392,6 +392,8 @@ protected:
|
|||
|
||||
void handleActivateEvent( wxActivateEvent& aEvent ) override;
|
||||
|
||||
void handleIconizeEvent( wxIconizeEvent& aEvent ) override;
|
||||
|
||||
/**
|
||||
* Attempts to load \a aFootprintId from the footprint library table.
|
||||
*
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
*
|
||||
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
||||
*
|
||||
* The equals() method to compare two floating point values adapted from
|
||||
* AlmostEqualRelativeAndAbs() on
|
||||
* https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||
* (C) Bruce Dawson subject to the Apache 2.0 license.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
|
@ -32,6 +37,7 @@
|
|||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
* Helper to avoid directly including wx/log.h for the templated functions in kimath
|
||||
|
@ -113,4 +119,37 @@ int rescale( int aNumerator, int aValue, int aDenominator );
|
|||
template <>
|
||||
int64_t rescale( int64_t aNumerator, int64_t aValue, int64_t aDenominator );
|
||||
|
||||
|
||||
/**
|
||||
* Template to compare two floating point values for equality within a required epsilon.
|
||||
*
|
||||
* @param aFirst value to compare.
|
||||
* @param aSecond value to compare.
|
||||
* @param aEpsilon allowed error.
|
||||
* @return true if the values considered equal within the specified epsilon, otherwise false.
|
||||
*/
|
||||
template <class T>
|
||||
typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
|
||||
equals( T aFirst, T aSecond, T aEpsilon = std::numeric_limits<T>::epsilon() )
|
||||
{
|
||||
T diff = fabs( aFirst - aSecond );
|
||||
|
||||
if( diff < aEpsilon )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
aFirst = fabs( aFirst );
|
||||
aSecond = fabs( aSecond );
|
||||
T largest = aFirst > aSecond ? aFirst : aSecond;
|
||||
|
||||
if( diff <= largest * aEpsilon )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif // UTIL_H
|
||||
|
|
|
@ -573,6 +573,28 @@ const int LexicographicalCompare( const VECTOR2<T>& aA, const VECTOR2<T>& aB )
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template to compare two VECTOR2<T> values for equality within a required epsilon.
|
||||
*
|
||||
* @param aFirst value to compare.
|
||||
* @param aSecond value to compare.
|
||||
* @param aEpsilon allowed error.
|
||||
* @return true if the values considered equal within the specified epsilon, otherwise false.
|
||||
*/
|
||||
template <class T>
|
||||
typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
|
||||
equals( VECTOR2<T> const& aFirst, VECTOR2<T> const& aSecond,
|
||||
T aEpsilon = std::numeric_limits<T>::epsilon() )
|
||||
{
|
||||
if( !equals( aFirst.x, aSecond.x, aEpsilon ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return equals( aFirst.y, aSecond.y, aEpsilon );
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
std::ostream& operator<<( std::ostream& aStream, const VECTOR2<T>& aVector )
|
||||
{
|
||||
|
|
|
@ -42,55 +42,6 @@
|
|||
#include <wx/log.h>
|
||||
#include <wx/mstream.h>
|
||||
|
||||
/**
|
||||
* Template to compare two floating point values for equality within a required epsilon.
|
||||
*
|
||||
* @param aFirst value to compare.
|
||||
* @param aSecond value to compare.
|
||||
* @param aEpsilon allowed error.
|
||||
* @return true if the values considered equal within the specified epsilon, otherwise false.
|
||||
*/
|
||||
template <class T>
|
||||
bool equals( T aFirst, T aSecond, T aEpsilon = static_cast<T>( FLT_EPSILON ) )
|
||||
{
|
||||
T diff = fabs( aFirst - aSecond );
|
||||
|
||||
if( diff < aEpsilon )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
aFirst = fabs( aFirst );
|
||||
aSecond = fabs( aSecond );
|
||||
T largest = aFirst > aSecond ? aFirst : aSecond;
|
||||
|
||||
if( diff <= largest * aEpsilon )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template to compare two VECTOR2<T> values for equality within a required epsilon.
|
||||
*
|
||||
* @param aFirst value to compare.
|
||||
* @param aSecond value to compare.
|
||||
* @param aEpsilon allowed error.
|
||||
* @return true if the values considered equal within the specified epsilon, otherwise false.
|
||||
*/
|
||||
template <class T>
|
||||
bool equals( VECTOR2<T> const& aFirst, VECTOR2<T> const& aSecond,
|
||||
T aEpsilon = static_cast<T>( FLT_EPSILON ) )
|
||||
{
|
||||
if( !equals( aFirst.x, aSecond.x, aEpsilon ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return equals( aFirst.y, aSecond.y, aEpsilon );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag to enable the NL_PCBNEW_PLUGIN debug tracing.
|
||||
|
@ -129,7 +80,7 @@ NL_PCBNEW_PLUGIN_IMPL::~NL_PCBNEW_PLUGIN_IMPL()
|
|||
|
||||
void NL_PCBNEW_PLUGIN_IMPL::SetFocus( bool aFocus )
|
||||
{
|
||||
wxLogTrace( m_logTrace, "NL_PCBNEW_PLUGIN_IMPL::SetFocus %d", aFocus );
|
||||
wxLogTrace( m_logTrace, wxT( "NL_PCBNEW_PLUGIN_IMPL::SetFocus %d" ), aFocus );
|
||||
NAV_3D::Write( navlib::focus_k, aFocus );
|
||||
}
|
||||
|
||||
|
@ -178,7 +129,7 @@ static CATEGORY_STORE::iterator add_category( std::string aCategoryPath,
|
|||
|
||||
void NL_PCBNEW_PLUGIN_IMPL::exportCommandsAndImages()
|
||||
{
|
||||
wxLogTrace( m_logTrace, "NL_PCBNEW_PLUGIN_IMPL::exportCommandsAndImages" );
|
||||
wxLogTrace( m_logTrace, wxT( "NL_PCBNEW_PLUGIN_IMPL::exportCommandsAndImages" ) );
|
||||
|
||||
std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
|
||||
|
||||
|
@ -253,13 +204,13 @@ void NL_PCBNEW_PLUGIN_IMPL::exportCommandsAndImages()
|
|||
streamBuffer->GetBufferSize() ),
|
||||
0 );
|
||||
|
||||
wxLogTrace( m_logTrace, "Adding image for : %s", name );
|
||||
wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
|
||||
vImages.push_back( std::move( tdxImage ) );
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( m_logTrace, "Inserting command: %s, description: %s, in category: %s", name,
|
||||
description, iter->first );
|
||||
wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
|
||||
name, description, iter->first );
|
||||
|
||||
iter->second->push_back(
|
||||
CCommand( std::move( name ), std::move( label ), std::move( description ) ) );
|
||||
|
@ -349,7 +300,8 @@ long NL_PCBNEW_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& matrix )
|
|||
long result = 0;
|
||||
VECTOR2D viewPos( matrix.m4x4[3][0], matrix.m4x4[3][1] );
|
||||
|
||||
if( !equals( m_view->GetCenter(), m_viewPosition ) )
|
||||
if( !equals( m_view->GetCenter(), m_viewPosition,
|
||||
static_cast<VECTOR2D::coord_type>( FLT_EPSILON ) ) )
|
||||
{
|
||||
m_view->SetCenter( viewPos + m_view->GetCenter() - m_viewPosition );
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
|
@ -385,7 +337,7 @@ long NL_PCBNEW_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents )
|
|||
double scale = width / m_viewportWidth * m_view->GetScale();
|
||||
m_view->SetScale( scale, m_view->GetCenter() );
|
||||
|
||||
if( !equals( m_view->GetScale(), scale ) )
|
||||
if( !equals( m_view->GetScale(), scale, static_cast<double>( FLT_EPSILON ) ) )
|
||||
{
|
||||
result = navlib::make_result_code( navlib::navlib_errc::error );
|
||||
}
|
||||
|
|
|
@ -119,6 +119,19 @@ void PCB_BASE_FRAME::handleActivateEvent( wxActivateEvent& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void PCB_BASE_FRAME::handleIconizeEvent( wxIconizeEvent& aEvent )
|
||||
{
|
||||
EDA_DRAW_FRAME::handleIconizeEvent( aEvent );
|
||||
|
||||
#if defined( KICAD_USE_3DCONNEXION )
|
||||
if( m_spaceMouse != nullptr && aEvent.IsIconized() )
|
||||
{
|
||||
m_spaceMouse->SetFocus( false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_VIEWER_FRAME* PCB_BASE_FRAME::Get3DViewerFrame()
|
||||
{
|
||||
wxWindow* frame = FindWindowByName( QUALIFIED_VIEWER3D_FRAMENAME( this ) );
|
||||
|
|
Loading…
Reference in New Issue