Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b23b48b9a7 |
@@ -1,57 +0,0 @@
|
||||
# minimum clang-format 10
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: true
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: false
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: [ BOOST_FOREACH ]
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
Language: Cpp
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: Inner
|
||||
PointerAlignment: Left
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: Never
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: true
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++11
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
@@ -1,5 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
Checks: '-clang-diagnostic-*,clang-analyzer-*, bugprone-*, modernize-deprecated-headers, modernize-loop-convert, modernize-use-override, modernize-redundant-void-arg, modernize-use-emplace, modernize-use-noexcept, modernize-use-bool-literals, modernize-pass-by-value, modernize-use-equals-default, modernize-use-equals-delete, modernize-use-default-member-init, cppcoreguidelines-prefer-member-initializer, cppcoreguidelines-init-variables, cppcoreguidelines-pro-type-member-init'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: '.*'
|
||||
FormatStyle: 'file'
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
# Custom attribute to mark source files using KiCad C++ formatting
|
||||
[attr]kicad-cpp-source text=auto whitepace=tab-in-indent format.clang-format-kicad
|
||||
|
||||
# Custom attribute to mark KiCad's own CMake files
|
||||
[attr]kicad-cmake-source text=auto whitespace=tab-in-indent
|
||||
|
||||
# Custom attribute for auto-generated sources:
|
||||
# * Do not perform whitespace checking
|
||||
# * Do not format
|
||||
[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format-kicad
|
||||
|
||||
# By default, all C and C++ files conform to KiCad formatting,
|
||||
# unless overridden
|
||||
*.c kicad-cpp-source
|
||||
*.cpp kicad-cpp-source
|
||||
*.h kicad-cpp-source
|
||||
|
||||
*.cmake kicad-cmake-source
|
||||
*.txt kicad-cmake-source
|
||||
*.md text=auto
|
||||
|
||||
# Compiled bitmap sources
|
||||
bitmaps_png/cpp_*/*.cpp generated
|
||||
|
||||
# wxFormBuilder-generated files
|
||||
**/dialog*/*_base.cpp generated
|
||||
**/dialog*/*_base.h generated
|
||||
|
||||
# Lemon grammars
|
||||
common/libeval/grammar.c generated
|
||||
common/libeval/grammar.h generated
|
||||
|
||||
# Scripts
|
||||
*.sh text eol=lf
|
||||
*.bat text eol=crlf
|
||||
@@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Git "hook chain", used to execute multiple scripts per hook.
|
||||
# To use:
|
||||
# * create a directory called <hookname>.d
|
||||
# * add scripts to this directory (executable)
|
||||
# * ln -s hook-chain <hookname>
|
||||
#
|
||||
# Now the scripts in that directory should be called in order.
|
||||
#
|
||||
# Set $HOOKCHAIN_DEBUG to see the names of invoked scripts.
|
||||
#
|
||||
# Based on script by Oliver Reflalo:
|
||||
# https://stackoverflow.com/questions/8730514/chaining-git-hooks
|
||||
#
|
||||
|
||||
hookname=`basename $0`
|
||||
|
||||
# Temp file for stdin, cleared at exit
|
||||
FILE=`mktemp`
|
||||
trap 'rm -f $FILE' EXIT
|
||||
cat - > $FILE
|
||||
|
||||
# Git hooks directory (this dir)
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
# Execute hooks in the directory one by one
|
||||
for hook in $DIR/$hookname.d/*;
|
||||
do
|
||||
if [ -x "$hook" ]; then
|
||||
|
||||
if [ "$HOOKCHAIN_DEBUG" ]; then
|
||||
echo "Running hook $hook"
|
||||
fi
|
||||
|
||||
cat $FILE | $hook "$@"
|
||||
status=$?
|
||||
|
||||
if [ $status -ne 0 ]; then
|
||||
echo "Hook $hook failed with error code $status"
|
||||
echo "To commit anyway, use --no-verify"
|
||||
exit $status
|
||||
else
|
||||
if [ "$HOOKCHAIN_DEBUG" ]; then
|
||||
echo "Hook passed: $hook"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -1 +0,0 @@
|
||||
hook-chain
|
||||
@@ -1,91 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Runs clang-format on changed regions before commit.
|
||||
#
|
||||
# Remaining installation checks/instructions will be printed when you commit.
|
||||
#
|
||||
# Based on clang-format pre-commit hook by Alex Eagle
|
||||
# https://gist.github.com/alexeagle/c8ed91b14a407342d9a8e112b5ac7dab
|
||||
|
||||
# Set kicad.check-format to allow this hook to run
|
||||
# If not set, the hook always succeeds.
|
||||
|
||||
do_format=false
|
||||
|
||||
# Check if formatting is configured
|
||||
if [ "$(git config --get kicad.check-format)" = true ]; then
|
||||
do_format=true
|
||||
fi
|
||||
|
||||
# Older env variable method
|
||||
if [ ! -z "$KICAD_CHECK_FORMAT" ]; then
|
||||
do_format=true
|
||||
fi
|
||||
|
||||
if [ ! ${do_format} = true ]; then
|
||||
# No formatting required
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
check_clang_format() {
|
||||
if hash git-clang-format 2>/dev/null; then
|
||||
return
|
||||
else
|
||||
echo "SETUP ERROR: no git-clang-format executable found, or it is not executable"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_git_config() {
|
||||
if [[ "$(git config --get clangFormat.style)" != "file" ]]; then
|
||||
echo "SETUP ERROR: git config clangFormat.style is wrong (should be 'file'). Fix this with:"
|
||||
echo "git config clangFormat.style file"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_filtered_filenames()
|
||||
{
|
||||
format_attr='clang-format-kicad'
|
||||
|
||||
# command to get list of candidate files
|
||||
git_list_files='git diff --cached --name-only --diff-filter=ACM'
|
||||
|
||||
files=$(${git_list_files} |
|
||||
|
||||
# Filter for format-controlled files
|
||||
git check-attr --stdin format.${format_attr} |
|
||||
|
||||
# output only the file names
|
||||
grep ": set$" |
|
||||
cut -d: -f1)
|
||||
|
||||
echo ${files}
|
||||
}
|
||||
|
||||
check_clang_format
|
||||
check_git_config
|
||||
|
||||
files_to_check=$(get_filtered_filenames)
|
||||
|
||||
if [ -z "${files_to_check}" ]; then
|
||||
# No controlled files to check
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
git_clang_format_cmd="git clang-format -v --diff -- ${files_to_check}"
|
||||
|
||||
readonly out=$(${git_clang_format_cmd})
|
||||
|
||||
# In these cases, there is no formatting issues, so we succeed
|
||||
if [[ "$out" == *"no modified files to format"* ]]; then exit 0; fi
|
||||
if [[ "$out" == *"clang-format did not modify any files"* ]]; then exit 0; fi
|
||||
|
||||
# Any other case implies formatting results
|
||||
echo "ERROR: you need to run clang-format (e.g. using tools/check_coding.sh) on your commit"
|
||||
|
||||
# print the errors to show what's the issue
|
||||
${git_clang_format_cmd}
|
||||
|
||||
# fail the pre-commit
|
||||
exit 1
|
||||
@@ -1,2 +0,0 @@
|
||||
custom: "https://donate.kicad.org"
|
||||
community_bridge: kicad
|
||||
@@ -1,26 +0,0 @@
|
||||
name: 'Redirect PRs'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: opened
|
||||
|
||||
jobs:
|
||||
lockdown:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/repo-lockdown@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
pr-comment: >
|
||||
Thank you for offering to help improve KiCad.
|
||||
This repository is a one-way mirror that can not accept pull requests.
|
||||
Please submit your merge request to the official KiCad repository
|
||||
at https://gitlab.com/kicad/code/kicad/-/merge_requests
|
||||
While we know that _your_ PR is not spam, we mark it as such to dissuade
|
||||
the Hacktoberfest PRs. Please join us over at GitLab. You can even use
|
||||
your GitHub credentials to log in there without creating a new account.
|
||||
skip-closed-pr-comment: true
|
||||
pr-labels: 'spam'
|
||||
close-pr: true
|
||||
lock-pr: true
|
||||
pr-lock-reason: 'spam'
|
||||
+21
-83
@@ -1,38 +1,41 @@
|
||||
.downloads-by-cmake
|
||||
.gdb_history
|
||||
boost_root
|
||||
/Build*
|
||||
/build*
|
||||
/cmake-build-*
|
||||
.downloads-by-cmake
|
||||
Build*
|
||||
build*
|
||||
common/fp_lib_table_keywords.cpp
|
||||
common/drc_rules_keywords.cpp
|
||||
common/drc_rules_lexer.h
|
||||
common/netlist_keywords.*
|
||||
common/netlist_lexer.h
|
||||
common/pcb_plot_params_lexer.h
|
||||
common/drawing_sheet/drawing_sheet_reader_keywords.cpp
|
||||
common/page_layout/page_layout_reader_keywords.cpp
|
||||
common/lib_table_keywords.*
|
||||
common/gal/opengl/shader_src.h
|
||||
include/fp_lib_table_lexer.h
|
||||
include/lib_table_lexer.h
|
||||
include/netlist_lexer.h
|
||||
include/page_layout_reader_lexer.h
|
||||
eeschema/cmp_library_lexer.h
|
||||
eeschema/cmp_library_keywords.*
|
||||
eeschema/dialogs/dialog_bom_cfg_keywords.cpp
|
||||
eeschema/dialogs/dialog_bom_cfg_lexer.h
|
||||
common/template_fieldnames_keywords.cpp
|
||||
common/template_fieldnames_lexer.h
|
||||
eeschema/schematic_keywords.*
|
||||
eeschema/dialogs/dialog_bom_help_html.h
|
||||
eeschema/template_fieldnames_keywords.*
|
||||
eeschema/template_fieldnames_lexer.h
|
||||
pcbnew/dialogs/dialog_freeroute_exchange_help_html.h
|
||||
pcbnew/pcb_plot_params_keywords.cpp
|
||||
pcbnew/pcb_plot_params_lexer.h
|
||||
pcb_calculator/attenuators/bridget_tee_formula.h
|
||||
pcb_calculator/attenuators/pi_formula.h
|
||||
pcb_calculator/attenuators/splitter_formula.h
|
||||
pcb_calculator/attenuators/tee_formula.h
|
||||
Makefile
|
||||
CMakeUserPresets.json
|
||||
CMakeCache.txt
|
||||
.cache/
|
||||
auto_renamed_to_cpp
|
||||
Testing
|
||||
version.h
|
||||
config.h
|
||||
install_manifest.txt
|
||||
doxygen/out
|
||||
Documentation/doxygen
|
||||
Documentation/development/doxygen
|
||||
*.bak
|
||||
*.pyc
|
||||
common/pcb_plot_params_keywords.cpp
|
||||
@@ -46,27 +49,14 @@ new/sch_lib_table_keywords.cpp
|
||||
new/sch_lib_table_lexer.h
|
||||
new/sweet_keywords.cpp
|
||||
new/sweet_lexer.h
|
||||
bitmaps_png/png*
|
||||
bitmaps_png/tmp
|
||||
common/pcb_keywords.cpp
|
||||
include/pcb_lexer.h
|
||||
fp-info-cache
|
||||
qa/tests/output/**
|
||||
|
||||
# demo project auxiliary files
|
||||
# demo project auxillary files
|
||||
demos/**/*-bak
|
||||
demos/**/_autosave-*
|
||||
demos/**/fp-info-cache
|
||||
demos/**/~*.lck
|
||||
|
||||
# MacOS package info created by CMake
|
||||
bitmap2component/Info.plist
|
||||
cvpcb/Info.plist
|
||||
eeschema/Info.plist
|
||||
gerbview/Info.plist
|
||||
kicad/Info.plist
|
||||
pagelayout_editor/Info.plist
|
||||
pcb_calculator/Info.plist
|
||||
pcbnew/Info.plist
|
||||
|
||||
# editor/OS fluff
|
||||
.*.swp
|
||||
@@ -76,64 +66,12 @@ pcbnew/Info.plist
|
||||
*.png
|
||||
*.kiface
|
||||
*.o
|
||||
*.o.*
|
||||
*.a
|
||||
*.a.*
|
||||
*.cmake
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.old
|
||||
*.gch
|
||||
*.orig
|
||||
*.patch
|
||||
|
||||
# These CMake files are wanted
|
||||
!cmake/**/*.cmake
|
||||
|
||||
# Eclipse IDE
|
||||
.settings/
|
||||
.project
|
||||
.cproject
|
||||
.pydevproject
|
||||
__pycache__
|
||||
|
||||
# Visual Studio
|
||||
.vs/
|
||||
.editorconfig
|
||||
CMakeSettings.json
|
||||
.vscode/
|
||||
compile_commands.json
|
||||
/vcpkg_installed
|
||||
CMakePresets.json
|
||||
|
||||
# Sublime Text
|
||||
*.sublime-*
|
||||
|
||||
# KDevelop
|
||||
.kdev4/
|
||||
*.kdev4
|
||||
|
||||
# Qt Creator
|
||||
CMakeLists.txt.user
|
||||
*.autosave
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
i18n_status.svg
|
||||
i18n_status.csv
|
||||
|
||||
# Project local settings files and backups (in demos and qa tests)
|
||||
*.kicad_prl
|
||||
*-backups
|
||||
|
||||
# QA dataoutput
|
||||
qa/data/**/*.csv
|
||||
|
||||
# Don't actually ignore any of these files, since we need them in the tree
|
||||
!resources/linux/icons/hicolor/**/**/*
|
||||
!resources/linux/icons-nightly/hicolor/**/**/*
|
||||
!CMakeModules/**/*
|
||||
!resources/bitmaps_png/png/**/*
|
||||
|
||||
# Junk temp files generated by MSVC for resource files
|
||||
/resources/msw/RC*
|
||||
*.patch
|
||||
@@ -1,23 +0,0 @@
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- report
|
||||
|
||||
variables:
|
||||
DEFAULT_FEDORA_IMAGE: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:40
|
||||
|
||||
default:
|
||||
image:
|
||||
name: $DEFAULT_FEDORA_IMAGE
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
|
||||
include:
|
||||
- local: '/.gitlab/templates.yml'
|
||||
- local: '/.gitlab/Fedora-Linux-CI.yml'
|
||||
- local: '/.gitlab/Ubuntu-20.04-CI.yml'
|
||||
- local: '/.gitlab/Windows-CI.yml'
|
||||
- local: '/.gitlab/macOS-CI.yml'
|
||||
- local: '/.gitlab/coverity.yml'
|
||||
- local: '/.gitlab/linux-metadata-validate.yml'
|
||||
- local: '/.gitlab/doxygen.yml'
|
||||
- local: '/.gitlab/mr_formatting.yml'
|
||||
@@ -1,179 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Fedora and save the results
|
||||
##########################################################################
|
||||
.fedora_build_linux_base:
|
||||
stage: build
|
||||
# Don't tag until we have separate CI for MRs
|
||||
# tags:
|
||||
# - kicad-fedora
|
||||
image: $DEFAULT_FEDORA_IMAGE
|
||||
extends: .only_code
|
||||
interruptible: false
|
||||
cache:
|
||||
key: "cache-fedora-linux"
|
||||
paths:
|
||||
- ccache/
|
||||
before_script:
|
||||
# CCache Config
|
||||
- mkdir -p ccache
|
||||
- export CCACHE_BASEDIR=${PWD}
|
||||
- export CCACHE_DIR=${PWD}/ccache
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_BUILD_TYPE=QABUILD
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
-DKICAD_TEST_XML_OUTPUT=ON
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON
|
||||
-DKICAD_USE_CMAKE_FINDPROTOBUF=ON
|
||||
../../
|
||||
- ninja 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/3d-viewer/
|
||||
- build/linux/api/libkiapi.so*
|
||||
- build/linux/common/libkicommon.so*
|
||||
- build/linux/common/gal/libkigal.so*
|
||||
- build/linux/eeschema/_eeschema.kiface
|
||||
- build/linux/cvpcb/_cvpcb.kiface
|
||||
- build/linux/kicad/kicad-cli
|
||||
- build/linux/pcbnew/pcbnew.py
|
||||
- build/linux/pcbnew/_pcbnew.kiface
|
||||
- build/linux/pcbnew/_pcbnew.so
|
||||
- build/linux/qa/
|
||||
- build/linux/schemas/
|
||||
- build/linux/compilation_log.txt
|
||||
exclude:
|
||||
- build/linux/**/*.o
|
||||
- build/linux/**/*.a
|
||||
|
||||
# This split is to ensure we can always use our runner for our jobs
|
||||
fedora_build_linux_kicad:
|
||||
extends: .fedora_build_linux_base
|
||||
tags:
|
||||
- kicad-fedora
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_build_linux_public:
|
||||
extends: .fedora_build_linux_base
|
||||
tags:
|
||||
- saas-linux-medium-amd64
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
|
||||
# Upload the compilation log in an easily downloadable form
|
||||
.fedora_report_build_warn:
|
||||
stage: report
|
||||
extends: .only_code
|
||||
when: always
|
||||
script:
|
||||
- echo "Uploading compilation log"
|
||||
- cp build/linux/compilation_log.txt compilation_log.txt
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Build log'
|
||||
name: "build_log.txt"
|
||||
paths:
|
||||
- compilation_log.txt
|
||||
|
||||
fedora_report_build_warn_kicad:
|
||||
extends: .fedora_report_build_warn
|
||||
tags:
|
||||
- kicad-fedora
|
||||
needs:
|
||||
- job: fedora_build_linux_kicad
|
||||
artifacts: true
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_report_build_warn_public:
|
||||
extends: .fedora_report_build_warn
|
||||
needs:
|
||||
- job: fedora_build_linux_public
|
||||
artifacts: true
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
|
||||
# Report on the metrics of the code
|
||||
.fedora_report_metrics:
|
||||
stage: report
|
||||
extends: .only_code
|
||||
when: always
|
||||
script:
|
||||
- cat build/linux/compilation_log.txt | { grep "warning:" || test $? = 1; } | awk 'END{print "number_of_fedora_warnings "NR}' > metrics.txt
|
||||
- cat metrics.txt
|
||||
artifacts:
|
||||
reports:
|
||||
metrics: metrics.txt
|
||||
|
||||
fedora_report_metrics_kicad:
|
||||
extends: .fedora_report_metrics
|
||||
tags:
|
||||
- kicad-fedora
|
||||
needs:
|
||||
- job: fedora_build_linux_kicad
|
||||
artifacts: true
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_report_metrics_public:
|
||||
extends: .fedora_report_metrics
|
||||
needs:
|
||||
- job: fedora_build_linux_public
|
||||
artifacts: true
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
##########################################################################
|
||||
# Run the code unit tests.
|
||||
##########################################################################
|
||||
.fedora_qa:
|
||||
image: $DEFAULT_FEDORA_IMAGE
|
||||
extends:
|
||||
- .unit_test
|
||||
- .only_code
|
||||
before_script:
|
||||
- if [ "$TEST" == "cli" ] || [ "$TEST" == "python" ]; then python3 -m pip install -r qa/tests/requirements.txt; fi
|
||||
- if [ "$TEST" == "cli" ]; then sudo dnf -y install gerbv; fi
|
||||
parallel:
|
||||
matrix:
|
||||
# The name of the test without the qa_ prefix
|
||||
- TEST: [python, cli, common, gerbview, pcbnew, pns_regressions, eeschema, kimath, sexpr, kicad2step, spice, api]
|
||||
|
||||
fedora_qa_kicad:
|
||||
extends: .fedora_qa
|
||||
tags:
|
||||
- kicad-fedora
|
||||
needs:
|
||||
- job: fedora_build_linux_kicad
|
||||
artifacts: true
|
||||
only:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
|
||||
fedora_qa_public:
|
||||
extends: .fedora_qa
|
||||
needs:
|
||||
- job: fedora_build_linux_public
|
||||
artifacts: true
|
||||
except:
|
||||
variables:
|
||||
- $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
@@ -1,118 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Ubuntu 20.04 and save the results
|
||||
##########################################################################
|
||||
.ubuntu20.04_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-ubuntu20.04
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/ubuntu:20.04
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
interruptible: false
|
||||
cache:
|
||||
key: "cache-ubuntu20.04-linux"
|
||||
paths:
|
||||
- ccache/
|
||||
before_script:
|
||||
# CCache Config
|
||||
- mkdir -p ccache
|
||||
- export CCACHE_BASEDIR=${PWD}
|
||||
- export CCACHE_DIR=${PWD}/ccache
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_USE_OCC=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON
|
||||
../../
|
||||
- ninja 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/3d-viewer/
|
||||
- build/linux/pcbnew/pcbnew.py
|
||||
- build/linux/pcbnew/_pcbnew.kiface
|
||||
- build/linux/pcbnew/_pcbnew.so
|
||||
- build/linux/qa/
|
||||
- build/linux/compilation_log.txt
|
||||
exclude:
|
||||
- build/linux/**/*.o
|
||||
- build/linux/**/*.a
|
||||
|
||||
# Upload the compilation log in an easily downloadable form
|
||||
.ubuntu20.04_report_build_warn:
|
||||
stage: report
|
||||
when: always
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
script:
|
||||
- echo "Uploading compilation log"
|
||||
- cp build/linux/compilation_log.txt compilation_log.txt
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Build log'
|
||||
name: "build_log.txt"
|
||||
paths:
|
||||
- compilation_log.txt
|
||||
|
||||
# Report on the metrics of the code
|
||||
.ubuntu20.04_report_metrics:
|
||||
stage: report
|
||||
when: always
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
script:
|
||||
- cat build/linux/compilation_log.txt | { grep "warning:" || test $? = 1; } | awk 'END{print "number_of_ubuntu_20.04_warnings "NR}' > metrics.txt
|
||||
- cat metrics.txt
|
||||
artifacts:
|
||||
reports:
|
||||
metrics: metrics.txt
|
||||
|
||||
##########################################################################
|
||||
# Run the code unit tests.
|
||||
##########################################################################
|
||||
.ubuntu20.04_qa:
|
||||
extends:
|
||||
- .unit_test
|
||||
needs:
|
||||
- job: ubuntu20.04_build
|
||||
artifacts: true
|
||||
tags:
|
||||
- kicad-ubuntu20.04
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/ubuntu:20.04
|
||||
only:
|
||||
- branches@kicad/code/kicad
|
||||
- tags@kicad/code/kicad
|
||||
except:
|
||||
- schedules
|
||||
parallel:
|
||||
matrix:
|
||||
# The name of the test without the qa_ prefix
|
||||
- TEST: [python, common, gerbview, pcbnew, eeschema, kimath, sexpr, kicad2step, spice]
|
||||
@@ -1,47 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Windows and save the results
|
||||
##########################################################################
|
||||
win64_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-windows-ltsc2022
|
||||
interruptible: false
|
||||
image: registry.gitlab.com/kicad/kicad-ci/windows-build-image/ltsc2022-msvc:latest
|
||||
variables:
|
||||
# Switch the compressor to fastzip and reduce the compression level
|
||||
FF_USE_FASTZIP: "true"
|
||||
CACHE_COMPRESSION_LEVEL: "fast"
|
||||
cache:
|
||||
key: win64-vcpkg-$CI_COMMIT_REF_SLUG
|
||||
paths:
|
||||
- build\windows\vcpkg_installed
|
||||
- .vcpkgCache
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: never
|
||||
- if: $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
script:
|
||||
- C:\builder\build.ps1 -Env -Arch x64
|
||||
- $vcpkgCache=Join-Path -Path (Get-Location) -ChildPath ".vcpkgCache";$env:VCPKG_DEFAULT_BINARY_CACHE=$vcpkgCache;New-Item -ItemType Directory -Force -Path $vcpkgCache
|
||||
- mkdir -p build/windows -Force
|
||||
- cd build/windows
|
||||
- cmake `
|
||||
-G "Ninja" `
|
||||
-DCMAKE_TOOLCHAIN_FILE=C:\builder\vcpkg\scripts\buildsystems\vcpkg.cmake `
|
||||
-DCMAKE_BUILD_TYPE=Debug `
|
||||
-DKICAD_SCRIPTING_WXPYTHON=OFF `
|
||||
-DKICAD_USE_OCC=ON `
|
||||
-DKICAD_BUILD_PNS_DEBUG_TOOL=ON `
|
||||
-DKICAD_USE_3DCONNEXION=ON `
|
||||
-DVCPKG_BUILD_TYPE=debug `
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/windows/compilation_log.txt
|
||||
@@ -1,76 +0,0 @@
|
||||
# This script is responsible for configuring the coverity file from the cache
|
||||
# (e.g. extracting it or updating it if needed)
|
||||
.coverity_cache_prep: &coverity_cache_prep |
|
||||
echo "Downloading MD5 hash of current Coverity Scan version to compare against cache"
|
||||
curl --output cov-analysis-linux64.md5 https://scan.coverity.com/download/linux64 \
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN \
|
||||
--form md5=1
|
||||
echo " *cov-analysis-linux64.tgz" >> cov-analysis-linux64.md5
|
||||
(md5sum --ignore-missing -c cov-analysis-linux64.md5) || (
|
||||
echo "Downloading new Coverity Scan version"
|
||||
curl --output cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \
|
||||
--form project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN
|
||||
)
|
||||
echo "Extracting Coverity Scan"
|
||||
mkdir coverity/
|
||||
tar xzf cov-analysis-linux64.tgz --strip-components=1 -C coverity
|
||||
test -d coverity/bin
|
||||
|
||||
# This script is responsible for tar'ing and submitting the results of the build.
|
||||
# These results will be saved for 1 day if the build fails.
|
||||
.coverity_submit: &coverity_submit |
|
||||
echo "Creating tar file of scan results"
|
||||
export COV_INT_FILENAME=cov-int-$(date +"%Y%m%d%H%M").tar.gz
|
||||
tar cfz $COV_INT_FILENAME cov-int
|
||||
echo "Submitting scan results"
|
||||
s5cmd/s5cmd cp $COV_INT_FILENAME s3://$KICAD_CI_R2_BUCKET/coverity/
|
||||
export FILE_URL="$KICAD_CI_R2_PUBLIC_BASE/coverity/$COV_INT_FILENAME"
|
||||
export KICAD_VERSION=$(sed 's/[()]//g' kicad_build_version.txt)
|
||||
curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME \
|
||||
--form token=$COVERITY_SCAN_TOKEN \
|
||||
--form email=$GITLAB_USER_EMAIL \
|
||||
--form url="$FILE_URL" \
|
||||
--form version="$KICAD_VERSION" \
|
||||
--form description="$KICAD_VERSION / $CI_COMMIT_TITLE" 2>&1 \
|
||||
| tee curl-response.txt
|
||||
grep -q 'Build successfully submitted' curl-response.txt
|
||||
|
||||
|
||||
Coverity:
|
||||
tags:
|
||||
- coverity
|
||||
stage: build
|
||||
image: registry.gitlab.com/kicad/kicad-ci/source_containers/master/fedora:40
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_JOB_NAME == "coverity"
|
||||
cache:
|
||||
key: coverity
|
||||
paths:
|
||||
- cov-analysis-linux64.tgz
|
||||
before_script:
|
||||
- export COVERITY_SCAN_PROJECT_NAME="kicad"
|
||||
- test "$(git rev-parse --is-shallow-repository)" = "false" || (git fetch --unshallow)
|
||||
- git fetch origin
|
||||
- curl -LO https://github.com/peak/s5cmd/releases/download/v2.0.0/s5cmd_2.0.0_Linux-64bit.tar.gz
|
||||
- mkdir s5cmd
|
||||
- tar -xvf ./s5cmd_2.0.0_Linux-64bit.tar.gz -C s5cmd
|
||||
- export AWS_ACCESS_KEY_ID=$KICAD_CI_R2_KEY_ID
|
||||
- export AWS_SECRET_ACCESS_KEY=$KICAD_CI_R2_ACCESS_KEY
|
||||
- export S3_ENDPOINT_URL=$KICAD_CI_R2_ENDPOINT
|
||||
script:
|
||||
- *coverity_cache_prep
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_USE_CMAKE_FINDPROTOBUF=ON
|
||||
- coverity/bin/cov-build --dir cov-int make -j10
|
||||
- *coverity_submit
|
||||
artifacts:
|
||||
expire_in: 1 year
|
||||
expose_as: 'Coverity log'
|
||||
name: "coverity_log.txt"
|
||||
paths:
|
||||
- cov-int/build-log.txt
|
||||
@@ -1,15 +0,0 @@
|
||||
build_doxygen_docker:
|
||||
image: docker:stable
|
||||
services:
|
||||
- docker:dind
|
||||
stage: build
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULED_JOB_NAME == "doxygen"
|
||||
tags:
|
||||
- gitlab-org-docker
|
||||
before_script:
|
||||
- docker info
|
||||
- docker login -u gitlab-ci-token -p "$CI_JOB_TOKEN" "$CI_REGISTRY"
|
||||
script:
|
||||
- docker build -t "${CI_REGISTRY_IMAGE}/doxygen:$CI_COMMIT_BRANCH" -f ./doxygen/doxygen.Dockerfile .
|
||||
- docker push "${CI_REGISTRY_IMAGE}/doxygen:$CI_COMMIT_BRANCH"
|
||||
@@ -1,20 +0,0 @@
|
||||
<!-- --------Before Creating a New Issue-----------
|
||||
* Limit report to a single issue.
|
||||
* Search the issue tracker to verify the issue has not already been reported.
|
||||
* Complete all instructions between `template comment markers <>.
|
||||
* Keep report contents limited to the necessary information required to fix the issue.
|
||||
* When creating an issue against the stable version of KiCad, make sure the latest available stable version is installed as issues may have already been resolved in later stable versions. -->
|
||||
# Description
|
||||
<!-- What is the current behavior and what is the expected behavior? -->
|
||||
<!-- If the issue is visual/graphical, please attach screenshots of the problem. -->
|
||||
<!-- Add the issue details below this line and before the "Steps to reproduce" heading. -->
|
||||
|
||||
# Steps to reproduce
|
||||
<!-- If there are multiple steps to reproduce it or it is a visual issue, then providing a screen recording as an attachment to this report is recommended. -->
|
||||
<!-- If this issue is specific to a project, please attach the necessary files to this issue. -->
|
||||
<!-- Add the steps to reproduce using the numbers below -->
|
||||
<!-- Add new step numbers before the "KiCad Version" heading. -->
|
||||
1.
|
||||
|
||||
# KiCad Version
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
##########################################################################
|
||||
# Run a validation of the metadata files for Linux
|
||||
##########################################################################
|
||||
validate_linux_metadata:
|
||||
stage: test
|
||||
needs: []
|
||||
interruptible: false
|
||||
image: $DEFAULT_FEDORA_IMAGE
|
||||
# Due to bug https://github.com/hughsie/appstream-glib/issues/381, this doesn't think our description tag
|
||||
# is localized even though it actually is.
|
||||
allow_failure: true
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
changes:
|
||||
- resources/linux/**/*
|
||||
- qa/resources/linux/**/*
|
||||
- translation/**/*
|
||||
# Only build the metadata files in this CI job
|
||||
script:
|
||||
- mkdir -p build/linux
|
||||
- cd build/linux
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DKICAD_STDLIB_LIGHT_DEBUG=ON
|
||||
-DKICAD_SCRIPTING_WXPYTHON=ON
|
||||
-DKICAD_BUILD_I18N=ON
|
||||
../../
|
||||
- make metadata
|
||||
- cd ../../
|
||||
- ./qa/resources/linux/verifyMetadataFiles.sh ./ ./build/linux
|
||||
@@ -1,29 +0,0 @@
|
||||
##########################################################################
|
||||
# Build KiCad on Windows and save the results
|
||||
##########################################################################
|
||||
macos_build:
|
||||
stage: build
|
||||
tags:
|
||||
- kicad-macos
|
||||
interruptible: false
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
when: never
|
||||
- if: $CI_PROJECT_ROOT_NAMESPACE == "kicad"
|
||||
script:
|
||||
- mkdir -p build/macos
|
||||
- cd build/macos
|
||||
- cmake
|
||||
-G Ninja
|
||||
-DCMAKE_TOOLCHAIN_FILE=/Users/$USER/kicad-mac-builder/toolchain/kicad-mac-builder.cmake
|
||||
../../
|
||||
- cmake --build . 2>&1 | tee compilation_log.txt
|
||||
- cd ../../
|
||||
artifacts:
|
||||
# Only save the artifacts that are needed for running the tests in the next stage
|
||||
# and the compilation log. The entire build directory is too large to save as an
|
||||
# artifact.
|
||||
expire_in: 2 hrs
|
||||
when: always
|
||||
paths:
|
||||
- build/macos/compilation_log.txt
|
||||
@@ -1,27 +0,0 @@
|
||||
##########################################################################
|
||||
# Test the formatting in a merge request using clang-format
|
||||
##########################################################################
|
||||
# The variable CI_COMMIT_BEFORE_SHA is not available in normal merge requests
|
||||
# so we must build the commit hash ourselves, see:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/12850
|
||||
test_formatting:
|
||||
stage: test
|
||||
needs: []
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
allow_failure: true
|
||||
before_script:
|
||||
# We must manually add the KiCad remote to ensure it is named sensibly
|
||||
- git remote add product https://gitlab.com/kicad/code/kicad.git ||
|
||||
git remote set-url product https://gitlab.com/kicad/code/kicad.git
|
||||
- git remote add source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git ||
|
||||
git remote set-url source ${CI_MERGE_REQUEST_SOURCE_PROJECT_URL}.git
|
||||
- git fetch -n product
|
||||
- git fetch -n source
|
||||
# Get the SHAs of the commits
|
||||
- "TARGET_HEAD_SHA=$(git rev-parse product/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME})"
|
||||
- "SOURCE_HEAD_SHA=$(git rev-parse source/${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME})"
|
||||
- "MERGE_BASE_SHA=$(git merge-base ${TARGET_HEAD_SHA} ${SOURCE_HEAD_SHA})"
|
||||
script:
|
||||
- echo "Testing formatting from commit ${MERGE_BASE_SHA}"
|
||||
- ./tools/check_coding.sh --diff --ci --commit ${MERGE_BASE_SHA}
|
||||
@@ -1,37 +0,0 @@
|
||||
##########################################################################
|
||||
# This will allow the job to run whenever code events trigger it.
|
||||
##########################################################################
|
||||
.only_code:
|
||||
only:
|
||||
- master
|
||||
- branches
|
||||
- merge_requests
|
||||
- pushes
|
||||
except:
|
||||
- schedules
|
||||
|
||||
##########################################################################
|
||||
# Define a template for all the unit tests, since each one is run in a separate
|
||||
# job to make the display nicer.
|
||||
##########################################################################
|
||||
.unit_test:
|
||||
stage: test
|
||||
when: on_success
|
||||
variables:
|
||||
BOOST_TEST_LOGGER: 'JUNIT,warning,test_results.${TEST}.xml:HRF,message'
|
||||
CTEST_OUTPUT_ON_FAILURE: 1
|
||||
script:
|
||||
- cd build/linux/qa
|
||||
- ctest -R qa_${TEST}
|
||||
# GitLab supports displaying the results in the GUI through JUNIT artifacts
|
||||
# (https://docs.gitlab.com/ee/ci/junit_test_reports.html)
|
||||
# so we upload the JUNIT results.
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build/linux/qa/**/*.log
|
||||
- build/linux/qa/**/output/*
|
||||
- build/linux/qa/**/*.xml
|
||||
reports:
|
||||
junit:
|
||||
- build/linux/qa/**/*.xml
|
||||
+411
-192
@@ -2,8 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2022 CERN
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -25,40 +23,47 @@
|
||||
|
||||
#define GLM_FORCE_RADIANS
|
||||
|
||||
#include <mutex>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
#include <wx/datetime.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
|
||||
#include <boost/uuid/sha1.hpp>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/ext.hpp>
|
||||
|
||||
#include "common.h"
|
||||
#include "3d_cache.h"
|
||||
#include "3d_info.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "sg/scenegraph.h"
|
||||
#include "3d_filename_resolver.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
#include <advanced_config.h>
|
||||
#include <common.h> // For ExpandEnvVarSubstitutions
|
||||
#include <filename_resolver.h>
|
||||
#include <mmh3_hash.h>
|
||||
#include <paths.h>
|
||||
#include <pgm_base.h>
|
||||
#include <project.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <wx_filename.h>
|
||||
|
||||
|
||||
#define MASK_3D_CACHE "3D_CACHE"
|
||||
|
||||
static std::mutex mutex3D_cache;
|
||||
static wxCriticalSection lock3D_cache;
|
||||
|
||||
static bool isSHA1Same( const unsigned char* shaA, const unsigned char* shaB )
|
||||
{
|
||||
for( int i = 0; i < 20; ++i )
|
||||
if( shaA[i] != shaB[i] )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool checkTag( const char* aTag, void* aPluginMgrPtr )
|
||||
{
|
||||
if( nullptr == aTag || nullptr == aPluginMgrPtr )
|
||||
if( NULL == aTag || NULL == aPluginMgrPtr )
|
||||
return false;
|
||||
|
||||
S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
|
||||
@@ -66,58 +71,107 @@ static bool checkTag( const char* aTag, void* aPluginMgrPtr )
|
||||
return pp->CheckTag( aTag );
|
||||
}
|
||||
|
||||
static const wxString sha1ToWXString( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
unsigned char uc;
|
||||
unsigned char tmp;
|
||||
char sha1[41];
|
||||
int j = 0;
|
||||
|
||||
for( int i = 0; i < 20; ++i )
|
||||
{
|
||||
uc = aSHA1Sum[i];
|
||||
tmp = uc / 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
tmp = uc % 16;
|
||||
|
||||
if( tmp > 9 )
|
||||
tmp += 87;
|
||||
else
|
||||
tmp += 48;
|
||||
|
||||
sha1[j++] = tmp;
|
||||
}
|
||||
|
||||
sha1[j] = 0;
|
||||
|
||||
return wxString::FromUTF8Unchecked( sha1 );
|
||||
}
|
||||
|
||||
|
||||
class S3D_CACHE_ENTRY
|
||||
{
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetHash( const HASH_128& aHash );
|
||||
const wxString GetCacheBaseName();
|
||||
|
||||
wxDateTime modTime; // file modification time
|
||||
HASH_128 m_hash;
|
||||
std::string pluginInfo; // PluginName:Version string
|
||||
SCENEGRAPH* sceneData;
|
||||
S3DMODEL* renderData;
|
||||
|
||||
private:
|
||||
// prohibit assignment and default copy constructor
|
||||
S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source );
|
||||
S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source );
|
||||
|
||||
wxString m_CacheBaseName; // base name of cache file
|
||||
wxString m_CacheBaseName; // base name of cache file (a SHA1 digest)
|
||||
|
||||
public:
|
||||
S3D_CACHE_ENTRY();
|
||||
~S3D_CACHE_ENTRY();
|
||||
|
||||
void SetSHA1( const unsigned char* aSHA1Sum );
|
||||
const wxString GetCacheBaseName( void );
|
||||
|
||||
wxDateTime modTime; // file modification time
|
||||
unsigned char sha1sum[20];
|
||||
std::string pluginInfo; // PluginName:Version string
|
||||
SCENEGRAPH* sceneData;
|
||||
S3DMODEL* renderData;
|
||||
};
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
|
||||
{
|
||||
sceneData = nullptr;
|
||||
renderData = nullptr;
|
||||
m_hash.Clear();
|
||||
sceneData = NULL;
|
||||
renderData = NULL;
|
||||
memset( sha1sum, 0, 20 );
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
|
||||
{
|
||||
delete sceneData;
|
||||
if( NULL != sceneData )
|
||||
delete sceneData;
|
||||
|
||||
if( nullptr != renderData )
|
||||
if( NULL != renderData )
|
||||
S3D::Destroy3DModel( &renderData );
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE_ENTRY::SetHash( const HASH_128& aHash )
|
||||
void S3D_CACHE_ENTRY::SetSHA1( const unsigned char* aSHA1Sum )
|
||||
{
|
||||
m_hash = aHash;
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL passed for aSHA1Sum";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy( sha1sum, aSHA1Sum, 20 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName()
|
||||
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
|
||||
{
|
||||
if( m_CacheBaseName.empty() )
|
||||
m_CacheBaseName = m_hash.ToString();
|
||||
m_CacheBaseName = sha1ToWXString( sha1sum );
|
||||
|
||||
return m_CacheBaseName;
|
||||
}
|
||||
@@ -125,41 +179,45 @@ const wxString S3D_CACHE_ENTRY::GetCacheBaseName()
|
||||
|
||||
S3D_CACHE::S3D_CACHE()
|
||||
{
|
||||
m_FNResolver = new FILENAME_RESOLVER;
|
||||
m_project = nullptr;
|
||||
m_DirtyCache = false;
|
||||
m_FNResolver = new S3D_FILENAME_RESOLVER;
|
||||
m_Plugins = new S3D_PLUGIN_MANAGER;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
S3D_CACHE::~S3D_CACHE()
|
||||
{
|
||||
FlushCache();
|
||||
|
||||
delete m_FNResolver;
|
||||
delete m_Plugins;
|
||||
if( m_FNResolver )
|
||||
delete m_FNResolver;
|
||||
|
||||
if( m_Plugins )
|
||||
delete m_Plugins;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
S3D_CACHE_ENTRY** aCachePtr, const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = nullptr;
|
||||
*aCachePtr = NULL;
|
||||
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, aEmbeddedFiles );
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
||||
|
||||
if( full3Dpath.empty() )
|
||||
{
|
||||
// the model cannot be found; we cannot proceed
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aModelFile );
|
||||
return nullptr;
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] could not find model '%s'\n",
|
||||
aModelFile.GetData() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check cache if file is already loaded
|
||||
std::lock_guard<std::mutex> lock( mutex3D_cache );
|
||||
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
|
||||
wxCriticalSectionLocker lock( lock3D_cache );
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
if( mi != m_CacheMap.end() )
|
||||
@@ -168,39 +226,38 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePa
|
||||
|
||||
if( fname.FileExists() ) // Only check if file exists. If not, it will
|
||||
{ // use the same model in cache.
|
||||
bool reload = ADVANCED_CFG::GetCfg().m_Skip3DModelMemoryCache;
|
||||
bool reload = false;
|
||||
wxDateTime fmdate = fname.GetModificationTime();
|
||||
|
||||
if( fmdate != mi->second->modTime )
|
||||
{
|
||||
HASH_128 hashSum;
|
||||
getHash( full3Dpath, hashSum );
|
||||
unsigned char hashSum[20];
|
||||
getSHA1( full3Dpath, hashSum );
|
||||
mi->second->modTime = fmdate;
|
||||
|
||||
if( hashSum != mi->second->m_hash )
|
||||
if( !isSHA1Same( hashSum, mi->second->sha1sum ) )
|
||||
{
|
||||
mi->second->SetHash( hashSum );
|
||||
mi->second->SetSHA1( hashSum );
|
||||
reload = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( reload )
|
||||
{
|
||||
if( nullptr != mi->second->sceneData )
|
||||
if( NULL != mi->second->sceneData )
|
||||
{
|
||||
S3D::DestroyNode( mi->second->sceneData );
|
||||
mi->second->sceneData = nullptr;
|
||||
mi->second->sceneData = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != mi->second->renderData )
|
||||
if( NULL != mi->second->renderData )
|
||||
S3D::Destroy3DModel( &mi->second->renderData );
|
||||
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath,
|
||||
mi->second->pluginInfo );
|
||||
mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath, mi->second->pluginInfo );
|
||||
}
|
||||
}
|
||||
|
||||
if( nullptr != aCachePtr )
|
||||
if( NULL != aCachePtr )
|
||||
*aCachePtr = mi->second;
|
||||
|
||||
return mi->second->sceneData;
|
||||
@@ -211,35 +268,41 @@ SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePa
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
||||
{
|
||||
return load( aModelFile, aBasePath, nullptr, aEmbeddedFiles );
|
||||
return load( aModelFile );
|
||||
}
|
||||
|
||||
|
||||
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = nullptr;
|
||||
*aCachePtr = NULL;
|
||||
|
||||
HASH_128 hashSum;
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
unsigned char sha1sum[20];
|
||||
|
||||
if( !getHash( aFileName, hashSum ) || m_CacheDir.empty() )
|
||||
if( !getSHA1( aFileName, sha1sum ) || m_CacheDir.empty() )
|
||||
{
|
||||
// just in case we can't get a hash digest (for example, on access issues)
|
||||
// or we do not have a configured cache file directory, we create an
|
||||
// entry to prevent further attempts at loading the file
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.emplace( aFileName, ep ).second == false )
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] duplicate entry in map file; key = '";
|
||||
ostr << aFileName.ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
@@ -248,71 +311,119 @@ SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY**
|
||||
{
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( m_CacheMap.emplace( aFileName, ep ).second == false )
|
||||
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||
m_CacheList.push_back( ep );
|
||||
wxFileName fname( aFileName );
|
||||
ep->modTime = fname.GetModificationTime();
|
||||
|
||||
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||
( aFileName, ep ) ).second == false )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] duplicate entry in map file; key = '";
|
||||
ostr << aFileName.ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
m_CacheList.pop_back();
|
||||
delete ep;
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( aCachePtr )
|
||||
*aCachePtr = ep;
|
||||
|
||||
ep->SetHash( hashSum );
|
||||
ep->SetSHA1( sha1sum );
|
||||
|
||||
wxString bname = ep->GetCacheBaseName();
|
||||
wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
|
||||
&& loadCacheData( ep ) )
|
||||
if( wxFileName::FileExists( cachename ) && loadCacheData( ep ) )
|
||||
return ep->sceneData;
|
||||
|
||||
ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
|
||||
|
||||
if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
|
||||
if( NULL != ep->sceneData )
|
||||
saveCacheData( ep );
|
||||
|
||||
return ep->sceneData;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::getHash( const wxString& aFileName, HASH_128& aHash )
|
||||
bool S3D_CACHE::getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum )
|
||||
{
|
||||
if( aFileName.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] empty filename" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] empty filename";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
|
||||
#else
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
#endif
|
||||
if( NULL == aSHA1Sum )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aMD5Sum";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
if( nullptr == fp )
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
|
||||
#else
|
||||
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||
#endif
|
||||
|
||||
if( NULL == fp )
|
||||
return false;
|
||||
|
||||
MMH3_HASH dblock( 0xA1B2C3D4 );
|
||||
std::vector<char> block( 4096 );
|
||||
boost::uuids::detail::sha1 dblock;
|
||||
unsigned char block[4096];
|
||||
size_t bsize = 0;
|
||||
|
||||
while( ( bsize = fread( block.data(), 1, 4096, fp ) ) > 0 )
|
||||
dblock.add( block );
|
||||
while( ( bsize = fread( &block, 1, 4096, fp ) ) > 0 )
|
||||
dblock.process_bytes( block, bsize );
|
||||
|
||||
fclose( fp );
|
||||
aHash = dblock.digest();
|
||||
unsigned int digest[5];
|
||||
dblock.get_digest( digest );
|
||||
|
||||
// ensure MSB order
|
||||
for( int i = 0; i < 5; ++i )
|
||||
{
|
||||
int idx = i << 2;
|
||||
unsigned int tmp = digest[i];
|
||||
aSHA1Sum[idx+3] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+2] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx+1] = tmp & 0xff;
|
||||
tmp >>= 8;
|
||||
aSHA1Sum[idx] = tmp & 0xff;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -323,16 +434,17 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; no file hash available" ) );
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] cannot load cached model; no file hash available\n" );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
|
||||
wxString errmsg = "cannot load cached model; config directory unknown";
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s\n", errmsg.GetData() );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -341,16 +453,18 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( " * [3D model] cannot open file '%s'" ), fname.GetData() );
|
||||
wxString errmsg = "cannot open file";
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'\n",
|
||||
errmsg.GetData(), fname.GetData() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( nullptr != aCacheItem->sceneData )
|
||||
if( NULL != aCacheItem->sceneData )
|
||||
S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
|
||||
|
||||
aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
|
||||
|
||||
if( nullptr == aCacheItem->sceneData )
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -359,18 +473,30 @@ bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( nullptr == aCacheItem )
|
||||
if( NULL == aCacheItem )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * NULL passed for aCacheItem" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * NULL passed for aCacheItem";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( nullptr == aCacheItem->sceneData )
|
||||
if( NULL == aCacheItem->sceneData )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * aCacheItem has no valid scene data" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * aCacheItem has no valid scene data";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -379,16 +505,17 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
|
||||
if( bname.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; no file hash available" ) );
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] cannot load cached model; no file hash available\n" );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_CacheDir.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
|
||||
wxString errmsg = "cannot load cached model; config directory unknown";
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s\n", errmsg.GetData() );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -399,15 +526,16 @@ bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||
{
|
||||
if( !wxFileName::FileExists( fname ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( " * [3D model] path exists but is not a regular file '%s'" ), fname );
|
||||
wxString errmsg = _( "path exists but is not a regular file" );
|
||||
wxLogTrace( MASK_3D_CACHE, " * [3D model] %s '%s'\n", errmsg.GetData(),
|
||||
fname.ToUTF8() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
|
||||
aCacheItem->pluginInfo.c_str() );
|
||||
aCacheItem->pluginInfo.c_str() );
|
||||
}
|
||||
|
||||
|
||||
@@ -416,9 +544,14 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
if( !m_ConfigDir.empty() )
|
||||
return false;
|
||||
|
||||
wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), wxEmptyString );
|
||||
wxFileName cfgdir;
|
||||
|
||||
cfgdir.Normalize( FN_NORMALIZE_FLAGS );
|
||||
if( aConfigDir.StartsWith( "${" ) || aConfigDir.StartsWith( "$(" ) )
|
||||
cfgdir.Assign( ExpandEnvVarSubstitutions( aConfigDir ), "" );
|
||||
else
|
||||
cfgdir.Assign( aConfigDir, "" );
|
||||
|
||||
cfgdir.Normalize();
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
@@ -426,9 +559,14 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "failed to create 3D configuration directory" );
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n";
|
||||
errmsg = _( "config directory" );
|
||||
ostr << " * " << errmsg.ToUTF8() << " '";
|
||||
ostr << cfgdir.GetPath().ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -439,10 +577,15 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
// inform the file resolver of the config directory
|
||||
if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
|
||||
" * config directory: '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * could not set 3D Config Directory on filename resolver\n";
|
||||
ostr << " * config directory: '" << m_ConfigDir.ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
// 3D cache data must go to a user's cache directory;
|
||||
@@ -452,36 +595,113 @@ bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||
// 1. OSX: ~/Library/Caches/kicad/3d/
|
||||
// 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
|
||||
// 3. MSWin: AppData\Local\kicad\3d
|
||||
wxFileName cacheDir;
|
||||
cacheDir.AssignDir( PATHS::GetUserCachePath() );
|
||||
cacheDir.AppendDir( wxT( "3d" ) );
|
||||
wxString cacheDir;
|
||||
|
||||
if( !cacheDir.DirExists() )
|
||||
#if defined(_WIN32)
|
||||
wxStandardPaths::Get().UseAppInfo( wxStandardPaths::AppInfo_None );
|
||||
cacheDir = wxStandardPaths::Get().GetUserLocalDataDir();
|
||||
cacheDir.append( "\\kicad\\3d" );
|
||||
#elif defined(__APPLE)
|
||||
cacheDir = "${HOME}/Library/Caches/kicad/3d";
|
||||
#else // assume Linux
|
||||
cacheDir = ExpandEnvVarSubstitutions( "${XDG_CACHE_HOME}" );
|
||||
|
||||
if( cacheDir.empty() || cacheDir == "${XDG_CACHE_HOME}" )
|
||||
cacheDir = "${HOME}/.cache";
|
||||
|
||||
cacheDir.append( "/kicad/3d" );
|
||||
#endif
|
||||
|
||||
cacheDir = ExpandEnvVarSubstitutions( cacheDir );
|
||||
cfgdir.Assign( cacheDir, "" );
|
||||
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
|
||||
if( !cacheDir.DirExists() )
|
||||
if( !cfgdir.DirExists() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "failed to create 3D cache directory";
|
||||
ostr << " * " << errmsg.ToUTF8() << "\n";
|
||||
errmsg = "cache directory";
|
||||
ostr << " * " << errmsg.ToUTF8() << " '";
|
||||
ostr << cfgdir.GetPath().ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_CacheDir = cacheDir.GetPathWithSep();
|
||||
m_CacheDir = cfgdir.GetPathWithSep();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProject( PROJECT* aProject )
|
||||
wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
|
||||
{
|
||||
m_project = aProject;
|
||||
if( !m_ConfigDir.empty() || !createDefault )
|
||||
return m_ConfigDir;
|
||||
|
||||
// note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
|
||||
// code coupling; ideally the instantiating code should call
|
||||
// Set3DConfigDir() to set the directory rather than relying on this
|
||||
// directory remaining the same in future KiCad releases.
|
||||
wxFileName cfgpath;
|
||||
|
||||
// From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
|
||||
// Unix: ~ (the home directory)
|
||||
// Windows: "C:\Documents and Settings\username\Application Data"
|
||||
// Mac: ~/Library/Preferences
|
||||
cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
|
||||
|
||||
#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
|
||||
wxString envstr = ExpandEnvVarSubstitutions( "${XDG_CONFIG_HOME}" );
|
||||
|
||||
if( envstr.IsEmpty() || envstr == "${XDG_CONFIG_HOME}" )
|
||||
{
|
||||
// XDG_CONFIG_HOME is not set, so use the fallback
|
||||
cfgpath.AppendDir( wxT( ".config" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Override the assignment above with XDG_CONFIG_HOME
|
||||
cfgpath.AssignDir( envstr );
|
||||
}
|
||||
#endif
|
||||
|
||||
cfgpath.AppendDir( wxT( "kicad" ) );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||
}
|
||||
|
||||
if( !cfgpath.DirExists() )
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
wxString errmsg = "failed to create 3D configuration directory";
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * " << errmsg.ToUTF8();
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
|
||||
return wxT( "" );
|
||||
}
|
||||
|
||||
if( Set3DConfigDir( cfgpath.GetPath() ) )
|
||||
return m_ConfigDir;
|
||||
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
|
||||
{
|
||||
bool hasChanged = false;
|
||||
|
||||
if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
|
||||
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
|
||||
{
|
||||
m_CacheMap.clear();
|
||||
|
||||
@@ -506,16 +726,23 @@ bool S3D_CACHE::SetProject( PROJECT* aProject )
|
||||
void S3D_CACHE::SetProgramBase( PGM_BASE* aBase )
|
||||
{
|
||||
m_FNResolver->SetProgramBase( aBase );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FILENAME_RESOLVER* S3D_CACHE::GetResolver() noexcept
|
||||
wxString S3D_CACHE::GetProjectDir( void )
|
||||
{
|
||||
return m_FNResolver->GetProjectDir();
|
||||
}
|
||||
|
||||
|
||||
S3D_FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
|
||||
{
|
||||
return m_FNResolver;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters() const
|
||||
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
|
||||
{
|
||||
return m_Plugins->GetFileFilters();
|
||||
}
|
||||
@@ -537,32 +764,40 @@ void S3D_CACHE::FlushCache( bool closePlugins )
|
||||
|
||||
if( closePlugins )
|
||||
ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_CACHE::ClosePlugins()
|
||||
void S3D_CACHE::ClosePlugins( void )
|
||||
{
|
||||
if( m_Plugins )
|
||||
if( NULL != m_Plugins )
|
||||
m_Plugins->ClosePlugins();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles )
|
||||
S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName )
|
||||
{
|
||||
S3D_CACHE_ENTRY* cp = nullptr;
|
||||
SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, aEmbeddedFiles );
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
SCENEGRAPH* sp = load( aModelFileName, &cp );
|
||||
|
||||
if( !sp )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
if( !cp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_CACHE,
|
||||
wxT( "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] model loaded with no associated S3D_CACHE_ENTRY";
|
||||
wxLogTrace( MASK_3D_CACHE, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( cp->renderData )
|
||||
@@ -574,43 +809,27 @@ S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& a
|
||||
return mp;
|
||||
}
|
||||
|
||||
void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
|
||||
|
||||
wxString S3D_CACHE::GetModelHash( const wxString& aModelFileName )
|
||||
{
|
||||
wxDir dir;
|
||||
wxString fileSpec = wxT( "*.3dc" );
|
||||
wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
|
||||
size_t numFilesFound = 0;
|
||||
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFileName );
|
||||
|
||||
wxFileName thisFile;
|
||||
wxDateTime lastAccess, thresholdDate;
|
||||
wxDateSpan durationInDays;
|
||||
if( full3Dpath.empty() || !wxFileName::FileExists( full3Dpath ) )
|
||||
return wxEmptyString;
|
||||
|
||||
// Calc the threshold date above which we delete cache files
|
||||
durationInDays.SetDays( aNumDaysOld );
|
||||
thresholdDate = wxDateTime::Now() - durationInDays;
|
||||
// check cache if file is already loaded
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi;
|
||||
mi = m_CacheMap.find( full3Dpath );
|
||||
|
||||
// If the cache directory can be found and opened, then we'll try and clean it up
|
||||
if( dir.Open( m_CacheDir ) )
|
||||
{
|
||||
thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
|
||||
if( mi != m_CacheMap.end() )
|
||||
return mi->second->GetCacheBaseName();
|
||||
|
||||
// Get a list of all the ".3dc" files in the cache directory
|
||||
numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
|
||||
// a cache item does not exist; search the Filename->Cachename map
|
||||
S3D_CACHE_ENTRY* cp = NULL;
|
||||
checkCache( full3Dpath, &cp );
|
||||
|
||||
for( unsigned int i = 0; i < numFilesFound; i++ )
|
||||
{
|
||||
// Completes path to specific file so we can get its "last access" date
|
||||
thisFile.SetFullName( fileList[i] );
|
||||
if( NULL != cp )
|
||||
return cp->GetCacheBaseName();
|
||||
|
||||
// Only get "last access" time to compare against. Don't need the other 2 timestamps.
|
||||
if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
|
||||
{
|
||||
if( lastAccess.IsEarlierThan( thresholdDate ) )
|
||||
{
|
||||
// This file is older than the threshold so delete it
|
||||
wxRemoveFile( thisFile.GetFullPath() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
+141
-129
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,146 +23,79 @@
|
||||
|
||||
/**
|
||||
* @file 3d_cache.h
|
||||
* defines the display data cache manager for 3D models
|
||||
*/
|
||||
|
||||
#ifndef CACHE_3D_H
|
||||
#define CACHE_3D_H
|
||||
|
||||
#include "3d_info.h"
|
||||
#include <core/typeinfo.h>
|
||||
#include "string_utils.h"
|
||||
#include <hash_128.h>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
#include <project.h>
|
||||
#include <wx/string.h>
|
||||
#include "str_rsort.h"
|
||||
#include "3d_filename_resolver.h"
|
||||
#include "3d_info.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
class EMBEDDED_FILES;
|
||||
class PGM_BASE;
|
||||
class S3D_CACHE;
|
||||
class S3D_CACHE_ENTRY;
|
||||
class SCENEGRAPH;
|
||||
class FILENAME_RESOLVER;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class S3D_PLUGIN_MANAGER;
|
||||
|
||||
|
||||
/**
|
||||
* Cache for storing the 3D shapes. This cache is able to be stored as a project
|
||||
* element (since it inherits from PROJECT::_ELEM).
|
||||
*/
|
||||
class S3D_CACHE : public PROJECT::_ELEM
|
||||
class S3D_CACHE
|
||||
{
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
PROJECT::ELEM ProjectElementType() noexcept override
|
||||
{
|
||||
return PROJECT::ELEM::S3DCACHE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration directory to be used by the model manager for storing 3D
|
||||
* model manager configuration data and the model cache.
|
||||
*
|
||||
* The config directory may only be set once in the lifetime of the object.
|
||||
*
|
||||
* @param aConfigDir is the configuration directory to use for 3D model manager data
|
||||
* @return true on success
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Set the current project's working directory; this affects the model search path.
|
||||
*/
|
||||
bool SetProject( PROJECT* aProject );
|
||||
|
||||
/**
|
||||
* Set the filename resolver's pointer to the application's PGM_BASE instance.
|
||||
*
|
||||
* The pointer is used to extract the local environment variables.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Attempt to load the scene data for a model.
|
||||
*
|
||||
* It will consult the internal cache list and load from cache if possible before invoking
|
||||
* the load() function of the available plugins. The model may fail to load if, for example,
|
||||
* the plugin does not support rendering of the 3D model.
|
||||
|
||||
*
|
||||
* @param aModelFile is the partial or full path to the model to be loaded.
|
||||
* @param aBasePath is the path to search for any relative files
|
||||
* @param aEmbeddedFiles is a pointer to the embedded files list.
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles );
|
||||
|
||||
FILENAME_RESOLVER* GetResolver() noexcept;
|
||||
|
||||
/**
|
||||
* Return the list of file filters retrieved from the plugins.
|
||||
*
|
||||
* This will contain at least the default "All Files (*.*)|*.*"
|
||||
*
|
||||
* @return a pointer to the filter list.
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters() const;
|
||||
|
||||
/**
|
||||
* Free all data in the cache and by default closes all plugins.
|
||||
*/
|
||||
void FlushCache( bool closePlugins = true );
|
||||
|
||||
/**
|
||||
* Unload plugins to free memory.
|
||||
*/
|
||||
void ClosePlugins();
|
||||
|
||||
/**
|
||||
* Attempt to load the scene data for a model and to translate it into an S3D_MODEL
|
||||
* structure for display by a renderer.
|
||||
*
|
||||
* @param aModelFileName is the full path to the model to be loaded.
|
||||
* @param aBasePath is the path to search for any relative files.
|
||||
* @param aEmbeddedFiles is a pointer to the embedded files list.
|
||||
* @return is a pointer to the render data or NULL if not available.
|
||||
*/
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName, const wxString& aBasePath,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles );
|
||||
|
||||
/**
|
||||
* Delete up old cache files in cache directory.
|
||||
*
|
||||
* Deletes ".3dc" files in the cache directory that are older than \a aNumDaysOld.
|
||||
*
|
||||
* @param aNumDaysOld is age threshold to delete ".3dc" cache files.
|
||||
*/
|
||||
void CleanCacheDir( int aNumDaysOld );
|
||||
|
||||
private:
|
||||
/**
|
||||
* Find or create cache entry for file name
|
||||
/// cache entries
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
|
||||
/// mapping of file names to cache names and data
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString > m_CacheMap;
|
||||
|
||||
/// object to resolve file names
|
||||
S3D_FILENAME_RESOLVER* m_FNResolver;
|
||||
|
||||
/// plugin manager
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
|
||||
/// set true if the cache needs to be updated
|
||||
bool m_DirtyCache;
|
||||
|
||||
/// 3D cache directory
|
||||
wxString m_CacheDir;
|
||||
|
||||
/// base configuration path for 3D items
|
||||
wxString m_ConfigDir;
|
||||
|
||||
/// current KiCad project dir
|
||||
wxString m_ProjDir;
|
||||
|
||||
/** Find or create cache entry for file name
|
||||
*
|
||||
* Searches the cache list for the given filename and retrieves the cache data; a cache
|
||||
* entry is created if one does not already exist.
|
||||
* Searches the cache list for the given filename and retrieves
|
||||
* the cache data; a cache entry is created if one does not
|
||||
* already exist.
|
||||
*
|
||||
* @param aFileName is the file name (full or partial path).
|
||||
* @param aCachePtr is an optional return address for cache entry pointer.
|
||||
* @return SCENEGRAPH object associated with file name or NULL on error.
|
||||
* @param[in] aFileName file name (full or partial path)
|
||||
* @param[out] aCachePtr optional return address for cache entry pointer
|
||||
* @return SCENEGRAPH object associated with file name
|
||||
* @retval NULL on error
|
||||
*/
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = nullptr );
|
||||
SCENEGRAPH* checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/**
|
||||
* Calculate the SHA1 hash of the given file.
|
||||
* Function getSHA1
|
||||
* calculates the SHA1 hash of the given file
|
||||
*
|
||||
* @param aFileName file name (full path).
|
||||
* @param aHash a 128 bit hash to hold the hash.
|
||||
* @return true on success, otherwise false.
|
||||
* @param[in] aFileName file name (full path)
|
||||
* @param[out] aSHA1Sum a 20 byte character array to hold the SHA1 hash
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
bool getHash( const wxString& aFileName, HASH_128& aHash );
|
||||
bool getSHA1( const wxString& aFileName, unsigned char* aSHA1Sum );
|
||||
|
||||
// load scene data from a cache file
|
||||
bool loadCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
@@ -172,23 +104,103 @@ private:
|
||||
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||
|
||||
// the real load function (can supply a cache entry pointer to member functions)
|
||||
SCENEGRAPH* load( const wxString& aModelFile, const wxString& aBasePath,
|
||||
S3D_CACHE_ENTRY** aCachePtr = nullptr,
|
||||
const EMBEDDED_FILES* aEmbeddedFiles = nullptr );
|
||||
SCENEGRAPH* load( const wxString& aModelFile, S3D_CACHE_ENTRY** aCachePtr = NULL );
|
||||
|
||||
/// Cache entries.
|
||||
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||
public:
|
||||
S3D_CACHE();
|
||||
virtual ~S3D_CACHE();
|
||||
|
||||
/// Mapping of file names to cache names and data.
|
||||
std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString > m_CacheMap;
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* Sets the configuration directory to be used by the
|
||||
* model manager for storing 3D model manager configuration
|
||||
* data and the model cache. The config directory may only be
|
||||
* set once in the lifetime of the object.
|
||||
*
|
||||
* @param aConfigDir is the configuration directory to use
|
||||
* for 3D model manager data
|
||||
* @return true on success
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
FILENAME_RESOLVER* m_FNResolver;
|
||||
/**
|
||||
* Function Get3DConfigDir
|
||||
* returns the current 3D configuration directory on
|
||||
* success, otherwise it returns wxEmptyString. If the
|
||||
* directory was not previously set via Set3DConfigDir()
|
||||
* then a default is used which is based on kicad's
|
||||
* configuration directory code as of September 2015.
|
||||
*/
|
||||
wxString Get3DConfigDir( bool createDefault = false );
|
||||
|
||||
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current project's working directory; this
|
||||
* affects the model search path
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir );
|
||||
|
||||
PROJECT* m_project;
|
||||
wxString m_CacheDir;
|
||||
wxString m_ConfigDir; ///< base configuration path for 3D items.
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets the filename resolver's pointer to the application's
|
||||
* PGM_BASE instance; the pointer is used to extract the
|
||||
* local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
/**
|
||||
* Function GetProjectDir
|
||||
* returns the current project's working directory
|
||||
*/
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function Load
|
||||
* attempts to load the scene data for a model; it will consult the
|
||||
* internal cache list and load from cache if possible before invoking
|
||||
* the load() function of the available plugins.
|
||||
*
|
||||
* @param aModelFile [in] is the partial or full path to the model to be loaded
|
||||
* @return true if the model was successfully loaded, otherwise false.
|
||||
* The model may fail to load if, for example, the plugin does not
|
||||
* support rendering of the 3D model.
|
||||
*/
|
||||
SCENEGRAPH* Load( const wxString& aModelFile );
|
||||
|
||||
S3D_FILENAME_RESOLVER* GetResolver( void );
|
||||
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters retrieved from the plugins;
|
||||
* this will contain at least the default "All Files (*.*)|*.*"
|
||||
*
|
||||
* @return a pointer to the filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
/**
|
||||
* Function FlushCache
|
||||
* frees all data in the cache and by default closes all plugins
|
||||
*/
|
||||
void FlushCache( bool closePlugins = true );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* unloads plugins to free memory
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function GetModel
|
||||
* attempts to load the scene data for a model and to translate it
|
||||
* into an S3D_MODEL structure for display by a renderer
|
||||
*
|
||||
* @param aModelFileName is the full path to the model to be loaded
|
||||
* @return is a pointer to the render data or NULL if not available
|
||||
*/
|
||||
S3DMODEL* GetModel( const wxString& aModelFileName );
|
||||
|
||||
wxString GetModelHash( const wxString& aModelFileName );
|
||||
};
|
||||
|
||||
#endif // CACHE_3D_H
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <common.h>
|
||||
#include <pgm_base.h>
|
||||
#include "3d_cache_wrapper.h"
|
||||
|
||||
static wxCriticalSection lock3D_wrapper;
|
||||
|
||||
CACHE_WRAPPER::CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CACHE_WRAPPER::~CACHE_WRAPPER()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir )
|
||||
{
|
||||
wxCriticalSectionLocker lock( lock3D_wrapper );
|
||||
CACHE_WRAPPER* cw = (CACHE_WRAPPER*) GetElem( ELEM_3DCACHE );
|
||||
S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
// check that we get the expected type of object or NULL
|
||||
wxASSERT( !cw || cache );
|
||||
|
||||
if( !cw )
|
||||
{
|
||||
cw = new CACHE_WRAPPER;
|
||||
cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||
|
||||
wxFileName cfgpath;
|
||||
cfgpath.AssignDir( GetKicadConfigPath() );
|
||||
cfgpath.AppendDir( wxT( "3d" ) );
|
||||
cache->SetProgramBase( &Pgm() );
|
||||
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||
SetElem( ELEM_3DCACHE, cw );
|
||||
updateProjDir = true;
|
||||
}
|
||||
|
||||
if( updateProjDir )
|
||||
cache->SetProjectDir( GetProjectPath() );
|
||||
|
||||
return cache;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_WRAPPER_3D_H
|
||||
#define CACHE_WRAPPER_3D_H
|
||||
|
||||
#include <project.h>
|
||||
#include "3d_cache.h"
|
||||
|
||||
class CACHE_WRAPPER : public S3D_CACHE, public PROJECT::_ELEM
|
||||
{
|
||||
public:
|
||||
CACHE_WRAPPER();
|
||||
virtual ~CACHE_WRAPPER();
|
||||
};
|
||||
|
||||
#endif // CACHE_WRAPPER_3D_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_filename_resolver.h
|
||||
* provides an extensible class to resolve 3D model paths. Initially
|
||||
* the legacy behavior will be implemented and an incomplete path
|
||||
* would be checked against the project directory or the KISYS3DMOD
|
||||
* environment variable. In the future a configurable set of search
|
||||
* paths may be specified.
|
||||
*/
|
||||
|
||||
#ifndef FILENAME_RESOLVER_3D_H
|
||||
#define FILENAME_RESOLVER_3D_H
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <wx/string.h>
|
||||
#include "str_rsort.h"
|
||||
|
||||
class PGM_BASE;
|
||||
|
||||
struct S3D_ALIAS
|
||||
{
|
||||
wxString m_alias; // alias to the base path
|
||||
wxString m_pathvar; // base path as stored in the config file
|
||||
wxString m_pathexp; // expanded base path
|
||||
wxString m_description; // description of the aliased path
|
||||
};
|
||||
|
||||
class S3D_FILENAME_RESOLVER
|
||||
{
|
||||
private:
|
||||
wxString m_ConfigDir; // 3D configuration directory
|
||||
std::list< S3D_ALIAS > m_Paths; // list of base paths to search from
|
||||
int m_errflags;
|
||||
PGM_BASE* m_pgm;
|
||||
wxString m_curProjDir;
|
||||
|
||||
/**
|
||||
* Function createPathList
|
||||
* builds the path list using available information such as
|
||||
* KISYS3DMOD and the 3d_path_list configuration file. Invalid
|
||||
* paths are silently discarded and removed from the configuration
|
||||
* file.
|
||||
*
|
||||
* @return true if at least one valid path was found
|
||||
*/
|
||||
bool createPathList( void );
|
||||
|
||||
/**
|
||||
* Function addPath
|
||||
* checks that a path is valid and adds it to the search list
|
||||
*
|
||||
* @param aPath is the alias set to be checked and added
|
||||
* @return true if aPath is valid
|
||||
*/
|
||||
bool addPath( const S3D_ALIAS& aPath );
|
||||
|
||||
/**
|
||||
* Function readPathList
|
||||
* reads a list of path names from a configuration file
|
||||
*
|
||||
* @return true if a file was found and contained at least
|
||||
* one valid path
|
||||
*/
|
||||
bool readPathList( void );
|
||||
|
||||
/**
|
||||
* Function writePathList
|
||||
* writes the current path list to a configuration file
|
||||
*
|
||||
* @return true if the path list was not empty and was
|
||||
* successfully written to the configuration file
|
||||
*/
|
||||
bool writePathList( void );
|
||||
|
||||
/**
|
||||
* Function checkEnvVarPath
|
||||
* checks the ${ENV_VAR} component of a path and adds
|
||||
* it to the resolver's path list if it is not yet in
|
||||
* the list
|
||||
*/
|
||||
void checkEnvVarPath( const wxString& aPath );
|
||||
|
||||
public:
|
||||
S3D_FILENAME_RESOLVER();
|
||||
|
||||
/**
|
||||
* Function Set3DConfigDir
|
||||
* sets the user's configuration directory
|
||||
* for 3D models.
|
||||
*
|
||||
* @param aConfigDir
|
||||
* @return true if the call succeeds (directory exists)
|
||||
*/
|
||||
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||
|
||||
/**
|
||||
* Function SetProjectDir
|
||||
* sets the current KiCad project directory as the first
|
||||
* entry in the model path list
|
||||
*
|
||||
* @param[in] aProjDir current project directory
|
||||
* @param[out] flgChanged optional, set to true if directory was changed
|
||||
* @retval true success
|
||||
* @retval false failure
|
||||
*/
|
||||
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL );
|
||||
wxString GetProjectDir( void );
|
||||
|
||||
/**
|
||||
* Function SetProgramBase
|
||||
* sets a pointer to the application's PGM_BASE instance;
|
||||
* the pointer is used to extract the local env vars.
|
||||
*/
|
||||
void SetProgramBase( PGM_BASE* aBase );
|
||||
|
||||
|
||||
/**
|
||||
* Function UpdatePathList
|
||||
* clears the current path list and substitutes the given path
|
||||
* list, updating the path configuration file on success.
|
||||
*/
|
||||
bool UpdatePathList( std::vector< S3D_ALIAS >& aPathList );
|
||||
|
||||
/**
|
||||
* Function ResolvePath
|
||||
* determines the full path of the given file name. In the future
|
||||
* remote files may be supported, in which case it is best to
|
||||
* require a full URI in which case ResolvePath should check that
|
||||
* the URI conforms to RFC-2396 and related documents and copies
|
||||
* aFileName into aResolvedName if the URI is valid.
|
||||
*/
|
||||
wxString ResolvePath( const wxString& aFileName );
|
||||
|
||||
/**
|
||||
* Function ShortenPath
|
||||
* produces a relative path based on the existing
|
||||
* search directories or returns the same path if
|
||||
* the path is not a superset of an existing search path.
|
||||
*
|
||||
* @param aFullPathName is an absolute path to shorten
|
||||
* @return the shortened path or aFullPathName
|
||||
*/
|
||||
wxString ShortenPath( const wxString& aFullPathName );
|
||||
|
||||
/**
|
||||
* Function GetPaths
|
||||
* returns a pointer to the internal path list; the items in:load
|
||||
*
|
||||
* the list can be used to set up the list of search paths
|
||||
* available to a 3D file browser.
|
||||
*
|
||||
* @return pointer to the internal path list
|
||||
*/
|
||||
const std::list< S3D_ALIAS >* GetPaths( void );
|
||||
|
||||
/**
|
||||
* Function SplitAlias
|
||||
* returns true if the given name contains an alias and
|
||||
* populates the string anAlias with the alias and aRelPath
|
||||
* with the relative path.
|
||||
*/
|
||||
bool SplitAlias( const wxString& aFileName, wxString& anAlias, wxString& aRelPath );
|
||||
|
||||
/**
|
||||
* Function ValidateName
|
||||
* returns true if the given path is a valid aliased relative path.
|
||||
* If the path contains an alias then hasAlias is set true.
|
||||
*/
|
||||
bool ValidateFileName( const wxString& aFileName, bool& hasAlias );
|
||||
|
||||
/**
|
||||
* Function GetKicadPaths
|
||||
* returns a list of path environment variables local to Kicad;
|
||||
* this list always includes KISYS3DMOD even if it is not
|
||||
* defined locally.
|
||||
*/
|
||||
bool GetKicadPaths( std::list< wxString >& paths );
|
||||
};
|
||||
|
||||
#endif // FILENAME_RESOLVER_3D_H
|
||||
@@ -5,7 +5,7 @@
|
||||
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2015 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
|
||||
@@ -36,12 +36,12 @@
|
||||
#include <wx/string.h>
|
||||
#include <plugins/3dapi/sg_base.h>
|
||||
|
||||
class FP_3DMODEL;
|
||||
class MODULE_3D_SETTINGS;
|
||||
|
||||
struct S3D_INFO
|
||||
{
|
||||
S3D_INFO();
|
||||
S3D_INFO( const FP_3DMODEL& aModel );
|
||||
S3D_INFO( const MODULE_3D_SETTINGS& aModel );
|
||||
|
||||
SGPOINT m_Scale; ///< scaling factors for the 3D footprint shape
|
||||
SGPOINT m_Rotation; ///< an X,Y,Z rotation (unit = degrees) for the 3D shape
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -27,35 +26,29 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <wx/config.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/dynlib.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <paths.h>
|
||||
#include <wx_filename.h>
|
||||
#include "common.h"
|
||||
#include "pgm_base.h"
|
||||
#include "3d_plugin_dir.h"
|
||||
#include "3d_plugin_manager.h"
|
||||
#include "plugins/3d/3d_plugin.h"
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
#include "plugins/ldr/3d/pluginldr3D.h"
|
||||
|
||||
|
||||
/**
|
||||
* Flag to enable 3D plugin manager debug tracing.
|
||||
*
|
||||
* Use "KI_TRACE_EDA_3D_VIEWER" to enable.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
#define MASK_3D_PLUGINMGR "3D_PLUGIN_MANAGER"
|
||||
|
||||
|
||||
S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
// create the initial file filter list entry
|
||||
m_FileFilters.emplace_back( _( "All Files" ) + wxT( " (*.*)|*.*" ) );
|
||||
m_FileFilters.push_back( _( "All Files (*.*)|*.*" ) );
|
||||
|
||||
// discover and load plugins
|
||||
loadPlugins();
|
||||
@@ -65,19 +58,19 @@ S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
{
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator sM = m_ExtMap.begin();
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::const_iterator eM = m_ExtMap.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * Extension [plugin name]:\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * Extension [plugin name]:\n" );
|
||||
|
||||
while( sM != eM )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " + '%s' [%s]\n" ), sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s' [%s]\n", sM->first.GetData(),
|
||||
sM->second->GetKicadPluginName() );
|
||||
++sM;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * No plugins available\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No plugins available\n" );
|
||||
}
|
||||
|
||||
|
||||
@@ -86,19 +79,21 @@ S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||
/// list of file filters
|
||||
std::list< wxString >::const_iterator sFF = m_FileFilters.begin();
|
||||
std::list< wxString >::const_iterator eFF = m_FileFilters.end();
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * File filters:\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * File filters:\n" );
|
||||
|
||||
while( sFF != eFF )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " + '%s'\n" ), (*sFF).GetData() );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " + '%s'\n", (*sFF).GetData() );
|
||||
++sFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * No file filters available\n" ) );
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * No file filters available\n" );
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,87 +110,93 @@ S3D_PLUGIN_MANAGER::~S3D_PLUGIN_MANAGER()
|
||||
}
|
||||
|
||||
m_Plugins.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
{
|
||||
std::list<wxString> searchpaths;
|
||||
std::list<wxString> pluginlist;
|
||||
wxFileName fn;
|
||||
std::list< wxString > searchpaths;
|
||||
std::list< wxString > pluginlist;
|
||||
wxFileName fn;
|
||||
|
||||
#ifndef __WXMAC__
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
|
||||
#ifdef DEBUG
|
||||
// set up to work from the build directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.AppendDir( wxT("..") );
|
||||
fn.AppendDir( wxT("plugins") );
|
||||
fn.AppendDir( wxT("3d") );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// add subdirectories too
|
||||
wxDir debugPluginDir;
|
||||
wxString subdir;
|
||||
|
||||
debugPluginDir.Open( testpath );
|
||||
|
||||
if( debugPluginDir.IsOpened() &&
|
||||
debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
{
|
||||
// set up to work from the build directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.AppendDir( wxT( ".." ) );
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// add subdirectories too
|
||||
wxDir debugPluginDir;
|
||||
wxString subdir;
|
||||
|
||||
debugPluginDir.Open( testpath );
|
||||
|
||||
if( debugPluginDir.IsOpened()
|
||||
&& debugPluginDir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
|
||||
{
|
||||
while( debugPluginDir.GetNext( &subdir ) )
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
|
||||
while( debugPluginDir.GetNext( &subdir ) )
|
||||
checkPluginPath( testpath + subdir, searchpaths );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fn.AssignDir( PATHS::GetStockPlugins3DPath() );
|
||||
#ifndef _WIN32
|
||||
// multiarch friendly determination of the plugin directory: the executable dir
|
||||
// is first determined via wxStandardPaths::Get().GetExecutablePath() and then
|
||||
// the CMAKE_INSTALL_LIBDIR path is appended relative to the executable dir.
|
||||
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
fn.RemoveLastDir();
|
||||
wxString tfname = fn.GetPathWithSep();
|
||||
tfname.Append( wxString::FromUTF8Unchecked( PLUGINDIR ) );
|
||||
fn.Assign( tfname, "");
|
||||
fn.AppendDir( "kicad" );
|
||||
#else
|
||||
// on windows the plugins directory is within the executable's directory
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
#endif
|
||||
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
|
||||
// checks plugin directory relative to executable path
|
||||
checkPluginPath( std::string( fn.GetPathWithSep().ToUTF8() ), searchpaths );
|
||||
|
||||
// check for per-user third party plugins
|
||||
// note: GetUserDataDir() gives '.pcbnew' rather than '.kicad' since it uses the exe name;
|
||||
fn.Assign( wxStandardPaths::Get().GetUserDataDir(), "" );
|
||||
fn.RemoveLastDir();
|
||||
#ifdef _WIN32
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
#else
|
||||
fn.AppendDir( wxT( ".kicad" ) );
|
||||
#endif
|
||||
fn.AppendDir( wxT( "plugins" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
#else
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
// Exe will be at <build_dir>/pcbnew/pcbnew.app/Contents/MacOS/pcbnew for standalone
|
||||
// Plugin will be at <build_dir>/kicad/KiCad.app/Contents/PlugIns/3d
|
||||
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||
|
||||
if( fn.GetName() == wxT( "kicad" ) )
|
||||
{
|
||||
fn.AppendDir( wxT( ".." ) ); // Contents
|
||||
}
|
||||
else
|
||||
{
|
||||
fn.AppendDir( wxT( ".." ) ); // Contents
|
||||
fn.AppendDir( wxT( ".." ) ); // pcbnew.app
|
||||
fn.AppendDir( wxT( ".." ) ); // pcbnew
|
||||
fn.AppendDir( wxT( ".." ) ); // Build root
|
||||
fn.AppendDir( wxT( "kicad" ) );
|
||||
fn.AppendDir( wxT( "KiCad.app" ) );
|
||||
fn.AppendDir( wxT( "Contents" ) );
|
||||
}
|
||||
// Search path on OS X is
|
||||
// (1) User ~/Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadUserDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (2) Machine /Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
// (3) Bundle kicad.app/Contents/PlugIns/3d
|
||||
fn.Assign( Pgm().GetExecutablePath() );
|
||||
fn.AppendDir( wxT( "Contents" ) );
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
|
||||
fn.AppendDir( wxT( "PlugIns" ) );
|
||||
fn.AppendDir( wxT( "3d" ) );
|
||||
fn.MakeAbsolute();
|
||||
|
||||
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||
checkPluginPath( testpath, searchpaths );
|
||||
|
||||
// Also check when running KiCad manager from build dir
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search path on OS X is
|
||||
// (1) Machine /Library/Application Support/kicad/PlugIns/3d
|
||||
checkPluginPath( PATHS::GetOSXKicadMachineDataDir() + wxT( "/PlugIns/3d" ), searchpaths );
|
||||
|
||||
// (2) Bundle kicad.app/Contents/PlugIns/3d
|
||||
fn.AssignDir( PATHS::GetStockPlugins3DPath() );
|
||||
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||
}
|
||||
#endif
|
||||
|
||||
std::list< wxString >::iterator sPL = searchpaths.begin();
|
||||
@@ -203,9 +204,14 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
while( sPL != ePL )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] searching path: '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, (*sPL).ToUTF8() );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << " * [DEBUG] searching path: '" << (*sPL).ToUTF8() << "'";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
listPlugins( *sPL, pluginlist );
|
||||
++sPL;
|
||||
}
|
||||
@@ -222,21 +228,32 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
|
||||
if( pp->Open( sPL->ToUTF8() ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] adding plugin" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] adding plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
m_Plugins.push_back( pp );
|
||||
int nf = pp->GetNFilters();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] adding %d filters" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, nf );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nf << " filters";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nf; ++i )
|
||||
{
|
||||
char const* cp = pp->GetFileFilter( i );
|
||||
|
||||
if( cp )
|
||||
addFilterString( cp );
|
||||
addFilterString( wxString::FromUTF8Unchecked( cp ) );
|
||||
}
|
||||
|
||||
addExtensionMap( pp );
|
||||
@@ -246,24 +263,39 @@ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] deleting plugin" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] deleting plugin";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
delete pp;
|
||||
}
|
||||
|
||||
++sPL;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [DEBUG] plugins loaded" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||
ostr << "* [DEBUG] plugins loaded";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath, std::list< wxString >& aPluginList )
|
||||
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// list potential plugins given a search path
|
||||
wxString nameFilter; // filter for user-loadable libraries (aka footprints)
|
||||
|
||||
wxString nameFilter; // filter for user-loadable libraries (aka modules)
|
||||
wxString lName; // stores name of enumerated files
|
||||
wxString fName; // full name of file
|
||||
wxDir wd;
|
||||
@@ -282,7 +314,7 @@ void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath, std::list< wxString
|
||||
// Per definition a loadable "xxx.bundle" is similar to an "xxx.app" app
|
||||
// bundle being a folder with some special content in it. We obviously don't
|
||||
// want to have that here for our loadable module, so just use ".so".
|
||||
nameFilter.Append( wxS( ".so" ) );
|
||||
nameFilter.Append( ".so" );
|
||||
#endif
|
||||
|
||||
wxString lp = wd.GetNameWithSep();
|
||||
@@ -300,20 +332,27 @@ void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath, std::list< wxString
|
||||
}
|
||||
|
||||
wd.Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
std::list< wxString >& aPluginList )
|
||||
std::list< wxString >& aPluginList )
|
||||
{
|
||||
// check the existence of a plugin name and add it to the list
|
||||
|
||||
if( aPath.empty() || !wxFileName::FileExists( aPath ) )
|
||||
return;
|
||||
|
||||
wxFileName path( ExpandEnvVarSubstitutions( aPath, nullptr ) );
|
||||
wxFileName path;
|
||||
|
||||
path.Normalize( FN_NORMALIZE_FLAGS );
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ) );
|
||||
else
|
||||
path.Assign( aPath );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
// determine if the path is already in the list
|
||||
wxString wxpath = path.GetFullPath();
|
||||
@@ -328,34 +367,37 @@ void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||
++bl;
|
||||
}
|
||||
|
||||
// prevent loading non-plugin dlls
|
||||
if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
|
||||
{
|
||||
if( !path.GetName().StartsWith( "s3d_plugin" )
|
||||
&& !path.GetName().StartsWith( "libs3d_plugin" ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aPluginList.push_back( wxpath );
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * [INFO] found 3D plugin '%s'\n" ), wxpath.GetData() );
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] found 3D plugin '%s'\n",
|
||||
wxpath.GetData() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
std::list< wxString >& aSearchList )
|
||||
std::list< wxString >& aSearchList )
|
||||
{
|
||||
// check the existence of a path and add it to the path search list
|
||||
if( aPath.empty() )
|
||||
return;
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( " * [INFO] checking if valid plugin directory '%s'\n" ),
|
||||
aPath.GetData() );
|
||||
#ifdef DEBUG
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, " * [INFO] checking for 3D plugins in '%s'\n",
|
||||
aPath.GetData() );
|
||||
#endif
|
||||
|
||||
wxFileName path;
|
||||
path.AssignDir( aPath );
|
||||
path.Normalize( FN_NORMALIZE_FLAGS );
|
||||
|
||||
if( aPath.StartsWith( "${" ) || aPath.StartsWith( "$(" ) )
|
||||
path.Assign( ExpandEnvVarSubstitutions( aPath ), "" );
|
||||
else
|
||||
path.Assign( aPath, "" );
|
||||
|
||||
path.Normalize();
|
||||
|
||||
if( !wxFileName::DirExists( path.GetFullPath() ) )
|
||||
return;
|
||||
@@ -374,6 +416,8 @@ void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||
}
|
||||
|
||||
aSearchList.push_back( wxpath );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -402,13 +446,19 @@ void S3D_PLUGIN_MANAGER::addFilterString( const wxString& aFilterString )
|
||||
void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
{
|
||||
// add entries to the extension map
|
||||
if( nullptr == aPlugin )
|
||||
if( NULL == aPlugin )
|
||||
return;
|
||||
|
||||
int nExt = aPlugin->GetNExtensions();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [INFO] adding %d extensions" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, nExt );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] adding " << nExt << " extensions";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
for( int i = 0; i < nExt; ++i )
|
||||
{
|
||||
@@ -416,18 +466,20 @@ void S3D_PLUGIN_MANAGER::addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin )
|
||||
wxString ws;
|
||||
|
||||
if( cp )
|
||||
ws = wxString( cp );
|
||||
ws = wxString::FromUTF8Unchecked( cp );
|
||||
|
||||
if( !ws.empty() )
|
||||
{
|
||||
m_ExtMap.emplace( ws, aPlugin );
|
||||
m_ExtMap.insert( std::pair< const wxString, KICAD_PLUGIN_LDR_3D* >( ws, aPlugin ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const noexcept
|
||||
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
|
||||
{
|
||||
return &m_FileFilters;
|
||||
}
|
||||
@@ -436,26 +488,18 @@ std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const no
|
||||
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::string& aPluginInfo )
|
||||
{
|
||||
wxFileName raw( aFileName );
|
||||
wxString ext_to_find = raw.GetExt();
|
||||
wxString ext = raw.GetExt();
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef WIN32
|
||||
// note: plugins only have a lowercase filter within Windows; including an uppercase
|
||||
// filter will result in duplicate file entries and should be avoided.
|
||||
ext_to_find.MakeLower();
|
||||
#endif
|
||||
|
||||
// .gz files are compressed versions that may have additional information in the previous
|
||||
// extension.
|
||||
if( ext_to_find == wxT( "gz" ) )
|
||||
{
|
||||
wxFileName second( raw.GetName() );
|
||||
ext_to_find = second.GetExt() + wxT( ".gz" );
|
||||
}
|
||||
ext.LowerCase();
|
||||
#endif
|
||||
|
||||
std::pair < std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator,
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator > items;
|
||||
|
||||
items = m_ExtMap.equal_range( ext_to_find );
|
||||
items = m_ExtMap.equal_range( ext );
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* >::iterator sL = items.first;
|
||||
|
||||
while( sL != items.second )
|
||||
@@ -464,7 +508,7 @@ SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::str
|
||||
{
|
||||
SCENEGRAPH* sp = sL->second->Load( aFileName.ToUTF8() );
|
||||
|
||||
if( nullptr != sp )
|
||||
if( NULL != sp )
|
||||
{
|
||||
sL->second->GetPluginInfo( aPluginInfo );
|
||||
return sp;
|
||||
@@ -474,7 +518,7 @@ SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName, std::str
|
||||
++sL;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -483,20 +527,28 @@ void S3D_PLUGIN_MANAGER::ClosePlugins( void )
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator sP = m_Plugins.begin();
|
||||
std::list< KICAD_PLUGIN_LDR_3D* >::iterator eP = m_Plugins.end();
|
||||
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, wxT( "%s:%s:%d * [INFO] closing %d extensions" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, static_cast<int>( m_Plugins.size() ) );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] closing " << m_Plugins.size() << " plugins";
|
||||
wxLogTrace( MASK_3D_PLUGINMGR, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
while( sP != eP )
|
||||
{
|
||||
(*sP)->Close();
|
||||
++sP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D_PLUGIN_MANAGER::CheckTag( const char* aTag )
|
||||
{
|
||||
if( nullptr == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
if( NULL == aTag || aTag[0] == 0 || m_Plugins.empty() )
|
||||
return false;
|
||||
|
||||
std::string tname = aTag;
|
||||
@@ -519,7 +571,8 @@ bool S3D_PLUGIN_MANAGER::CheckTag( const char* aTag )
|
||||
ptag.clear();
|
||||
(*pS)->GetPluginInfo( ptag );
|
||||
|
||||
// if the plugin name matches then the version must also match
|
||||
// if the plugin name matches then the version
|
||||
// must also match
|
||||
if( !ptag.compare( 0, pname.size(), pname ) )
|
||||
{
|
||||
if( ptag.compare( tname ) )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -41,35 +40,16 @@ class SCENEGRAPH;
|
||||
|
||||
class S3D_PLUGIN_MANAGER
|
||||
{
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/**
|
||||
* Return the list of file filters; this will contain at least the default
|
||||
* "All Files (*.*)|*.*" and the file filters supported by any available plugins.
|
||||
*
|
||||
* @return a pointer to the internal filter list.
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const noexcept;
|
||||
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
|
||||
|
||||
/**
|
||||
* Iterate through all discovered plugins and closes them to reclaim memory.
|
||||
*
|
||||
* The individual plugins will be automatically reloaded as calls are made to load
|
||||
* specific models.
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Check the given tag and returns true if the plugin named in the tag is not loaded
|
||||
* or the plugin is loaded and the version matches.
|
||||
*/
|
||||
bool CheckTag( const char* aTag );
|
||||
|
||||
private:
|
||||
/// list of discovered plugins
|
||||
std::list< KICAD_PLUGIN_LDR_3D* > m_Plugins;
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* > m_ExtMap;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
|
||||
/// load plugins
|
||||
void loadPlugins( void );
|
||||
|
||||
@@ -88,14 +68,36 @@ private:
|
||||
/// add entries to the extension map
|
||||
void addExtensionMap( KICAD_PLUGIN_LDR_3D* aPlugin );
|
||||
|
||||
/// list of discovered plugins
|
||||
std::list< KICAD_PLUGIN_LDR_3D* > m_Plugins;
|
||||
public:
|
||||
S3D_PLUGIN_MANAGER();
|
||||
virtual ~S3D_PLUGIN_MANAGER();
|
||||
|
||||
/// mapping of extensions to available plugins
|
||||
std::multimap< const wxString, KICAD_PLUGIN_LDR_3D* > m_ExtMap;
|
||||
/**
|
||||
* Function GetFileFilters
|
||||
* returns the list of file filters; this will contain at least
|
||||
* the default "All Files (*.*)|*.*" and the file filters supported
|
||||
* by any available plugins
|
||||
*
|
||||
* @return a pointer to the internal filter list
|
||||
*/
|
||||
std::list< wxString > const* GetFileFilters( void ) const;
|
||||
|
||||
/// list of file filters
|
||||
std::list< wxString > m_FileFilters;
|
||||
SCENEGRAPH* Load3DModel( const wxString& aFileName, std::string& aPluginInfo );
|
||||
|
||||
/**
|
||||
* Function ClosePlugins
|
||||
* iterates through all discovered plugins and closes them to
|
||||
* reclaim memory. The individual plugins will be automatically
|
||||
* reloaded as calls are made to load specific models.
|
||||
*/
|
||||
void ClosePlugins( void );
|
||||
|
||||
/**
|
||||
* Function CheckTag
|
||||
* checks the given tag and returns true if the plugin named in the tag
|
||||
* is not loaded or the plugin is loaded and the version matches
|
||||
*/
|
||||
bool CheckTag( const char* aTag );
|
||||
};
|
||||
|
||||
#endif // PLUGIN_MANAGER_3D_H
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <wx/filename.h>
|
||||
|
||||
#include "3d_info.h"
|
||||
#include "3d_cache.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include "dlg_3d_pathconfig.h"
|
||||
#include "dlg_select_3dmodel.h"
|
||||
|
||||
|
||||
bool S3D::Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel )
|
||||
{
|
||||
if( NULL == aModel )
|
||||
return false;
|
||||
|
||||
DLG_SELECT_3DMODEL* dm = new DLG_SELECT_3DMODEL( aParent, aCache, aModel,
|
||||
prevModelSelectDir, prevModelWildcard );
|
||||
|
||||
if( wxID_OK == dm->ShowModal() )
|
||||
{
|
||||
delete dm;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dm;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver )
|
||||
{
|
||||
DLG_3D_PATH_CONFIG* dp = new DLG_3D_PATH_CONFIG( aParent, aResolver );
|
||||
|
||||
if( wxID_OK == dp->ShowModal() )
|
||||
{
|
||||
delete dp;
|
||||
return true;
|
||||
}
|
||||
|
||||
delete dp;
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef CACHE_DIALOGS_3D_H
|
||||
#define CACHE_DIALOGS_3D_H
|
||||
|
||||
#include <wx/window.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard, MODULE_3D_SETTINGS* aModel );
|
||||
|
||||
bool Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||
}
|
||||
|
||||
#endif // CACHE_DIALOGS_3D_H
|
||||
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <wx/msgdlg.h>
|
||||
#include <pgm_base.h>
|
||||
#include <html_messagebox.h>
|
||||
#include "3d_cache/dialogs/dlg_3d_pathconfig.h"
|
||||
#include "3d_cache/3d_filename_resolver.h"
|
||||
|
||||
DLG_3D_PATH_CONFIG::DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver ) :
|
||||
DLG_3D_PATH_CONFIG_BASE( aParent ), m_resolver( aResolver )
|
||||
{
|
||||
initDialog();
|
||||
|
||||
GetSizer()->SetSizeHints( this );
|
||||
Centre();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::initDialog()
|
||||
{
|
||||
m_Aliases->EnableEditing( true );
|
||||
|
||||
// Gives a min width to each column, when the user drags a column
|
||||
m_Aliases->SetColMinimalWidth( 0, 80 );
|
||||
m_Aliases->SetColMinimalWidth( 1, 300 );
|
||||
m_Aliases->SetColMinimalWidth( 2, 120 );
|
||||
m_Aliases->SetColMinimalAcceptableWidth( 80 );
|
||||
|
||||
// Set column sizes to this min value
|
||||
m_Aliases->SetColSize( 0, 80 );
|
||||
m_Aliases->SetColSize( 1, 300 );
|
||||
m_Aliases->SetColSize( 2, 120 );
|
||||
|
||||
m_EnvVars->SetColMinimalWidth( 0, 80 );
|
||||
m_EnvVars->SetColMinimalWidth( 1, 300 );
|
||||
m_EnvVars->SetColMinimalAcceptableWidth( 80 );
|
||||
m_EnvVars->SetColSize( 0, 80 );
|
||||
m_EnvVars->SetColSize( 1, 300 );
|
||||
|
||||
if( m_resolver )
|
||||
{
|
||||
updateEnvVars();
|
||||
|
||||
// prohibit these characters in the alias names: []{}()%~<>"='`;:.,&?/\|$
|
||||
m_aliasValidator.SetStyle( wxFILTER_EXCLUDE_CHAR_LIST );
|
||||
m_aliasValidator.SetCharExcludes( wxT( "{}[]()%~<>\"='`;:.,&?/\\|$" ) );
|
||||
|
||||
const std::list< S3D_ALIAS >* rpaths = m_resolver->GetPaths();
|
||||
std::list< S3D_ALIAS >::const_iterator rI = rpaths->begin();
|
||||
std::list< S3D_ALIAS >::const_iterator rE = rpaths->end();
|
||||
size_t listsize = rpaths->size();
|
||||
size_t listidx = 0;
|
||||
|
||||
while( rI != rE && ( (*rI).m_alias.StartsWith( "${" ) || (*rI).m_alias.StartsWith( "$(" ) ) )
|
||||
{
|
||||
++listidx;
|
||||
++rI;
|
||||
}
|
||||
|
||||
if( listidx < listsize )
|
||||
m_curdir = (*rI).m_pathexp;
|
||||
else
|
||||
return;
|
||||
|
||||
listsize = listsize - listidx - m_Aliases->GetNumberRows();
|
||||
|
||||
// note: if the list allocation fails we have bigger problems
|
||||
// and there is no point in trying to notify the user here
|
||||
if( listsize > 0 && !m_Aliases->InsertRows( 0, listsize ) )
|
||||
return;
|
||||
|
||||
int nitems = 0;
|
||||
wxGridCellTextEditor* pEdAlias;
|
||||
|
||||
while( rI != rE )
|
||||
{
|
||||
m_Aliases->SetCellValue( nitems, 0, rI->m_alias );
|
||||
|
||||
if( 0 == nitems )
|
||||
{
|
||||
m_Aliases->SetCellEditor( nitems, 0, new wxGridCellTextEditor );
|
||||
pEdAlias = (wxGridCellTextEditor*) m_Aliases->GetCellEditor( nitems, 0 );
|
||||
pEdAlias->SetValidator( m_aliasValidator );
|
||||
pEdAlias->DecRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
pEdAlias->IncRef();
|
||||
m_Aliases->SetCellEditor( nitems, 0, pEdAlias );
|
||||
}
|
||||
|
||||
m_Aliases->SetCellValue( nitems, 1, rI->m_pathvar );
|
||||
m_Aliases->SetCellValue( nitems++, 2, rI->m_description );
|
||||
|
||||
// TODO: implement a wxGridCellEditor which invokes a wxDirDialog
|
||||
|
||||
++rI;
|
||||
}
|
||||
|
||||
m_Aliases->AutoSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DLG_3D_PATH_CONFIG::TransferDataFromWindow()
|
||||
{
|
||||
if( NULL == m_resolver )
|
||||
{
|
||||
wxMessageBox( _( "[BUG] No valid resolver; data will not be updated" ),
|
||||
_( "Update 3D search path list" ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<S3D_ALIAS> alist;
|
||||
S3D_ALIAS alias;
|
||||
|
||||
int ni = m_Aliases->GetNumberRows();
|
||||
|
||||
if( ni <= 0 )
|
||||
{
|
||||
// note: UI usability: we should ask a user if they're sure they
|
||||
// want to clear the entire path list
|
||||
m_resolver->UpdatePathList( alist );
|
||||
return true;
|
||||
}
|
||||
|
||||
for( int i = 0; i < ni; ++i )
|
||||
{
|
||||
alias.m_alias = m_Aliases->GetCellValue( i, 0 );
|
||||
alias.m_pathvar = m_Aliases->GetCellValue( i, 1 );
|
||||
alias.m_description = m_Aliases->GetCellValue( i, 2 );
|
||||
|
||||
if( !alias.m_alias.empty() && !alias.m_pathvar.empty() )
|
||||
alist.push_back( alias );
|
||||
|
||||
}
|
||||
|
||||
return m_resolver->UpdatePathList( alist );
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnAddAlias( wxCommandEvent& event )
|
||||
{
|
||||
int ni = m_Aliases->GetNumberRows();
|
||||
|
||||
if( m_Aliases->InsertRows( ni, 1 ) )
|
||||
{
|
||||
wxGridCellTextEditor* pEdAlias;
|
||||
pEdAlias = (wxGridCellTextEditor*) m_Aliases->GetCellEditor( 0, 0 );
|
||||
m_Aliases->SetCellEditor( ni, 0, pEdAlias );
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
m_Aliases->AutoSize();
|
||||
Fit();
|
||||
|
||||
// TODO: set the editors on any newly created rows
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnDelAlias( wxCommandEvent& event )
|
||||
{
|
||||
wxArrayInt sel = m_Aliases->GetSelectedRows();
|
||||
|
||||
if( sel.empty() )
|
||||
{
|
||||
wxMessageBox( _( "No entry selected" ), _( "Delete alias entry" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( sel.size() > 1 )
|
||||
{
|
||||
wxMessageBox( _( "Multiple entries selected; please\nselect only one entry" ),
|
||||
_( "Delete alias entry" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_Aliases->GetNumberRows() > 1 )
|
||||
{
|
||||
int ni = sel.front();
|
||||
m_Aliases->DeleteRows( ni, 1 );
|
||||
|
||||
if( ni >= m_Aliases->GetNumberRows() )
|
||||
ni = m_Aliases->GetNumberRows() - 1;
|
||||
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
m_Aliases->AutoSize();
|
||||
Fit();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Aliases->SetCellValue( 0, 0, wxEmptyString );
|
||||
m_Aliases->SetCellValue( 0, 1, wxEmptyString );
|
||||
m_Aliases->SetCellValue( 0, 2, wxEmptyString );
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnAliasMoveUp( wxCommandEvent& event )
|
||||
{
|
||||
wxArrayInt sel = m_Aliases->GetSelectedRows();
|
||||
|
||||
if( sel.empty() )
|
||||
{
|
||||
wxMessageBox( _( "No entry selected" ), _( "Move alias up" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( sel.size() > 1 )
|
||||
{
|
||||
wxMessageBox( _( "Multiple entries selected; please\nselect only one entry" ),
|
||||
_( "Move alias up" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
int ci = sel.front();
|
||||
|
||||
if( ci > 0 )
|
||||
{
|
||||
S3D_ALIAS al0;
|
||||
al0.m_alias = m_Aliases->GetCellValue( ci, 0 );
|
||||
al0.m_pathvar = m_Aliases->GetCellValue( ci, 1 );
|
||||
al0.m_description = m_Aliases->GetCellValue( ci, 2 );
|
||||
|
||||
int ni = ci - 1;
|
||||
m_Aliases->SetCellValue( ci, 0, m_Aliases->GetCellValue( ni, 0 ) );
|
||||
m_Aliases->SetCellValue( ci, 1, m_Aliases->GetCellValue( ni, 1 ) );
|
||||
m_Aliases->SetCellValue( ci, 2, m_Aliases->GetCellValue( ni, 2 ) );
|
||||
|
||||
m_Aliases->SetCellValue( ni, 0, al0.m_alias );
|
||||
m_Aliases->SetCellValue( ni, 1, al0.m_pathvar );
|
||||
m_Aliases->SetCellValue( ni, 2, al0.m_description );
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnAliasMoveDown( wxCommandEvent& event )
|
||||
{
|
||||
wxArrayInt sel = m_Aliases->GetSelectedRows();
|
||||
|
||||
if( sel.empty() )
|
||||
{
|
||||
wxMessageBox( _( "No entry selected" ), _( "Move alias down" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( sel.size() > 1 )
|
||||
{
|
||||
wxMessageBox( _( "Multiple entries selected; please\nselect only one entry" ),
|
||||
_( "Move alias down" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
int ni = m_Aliases->GetNumberRows() - 1;
|
||||
int ci = sel.front();
|
||||
|
||||
if( ci < ni )
|
||||
{
|
||||
S3D_ALIAS al0;
|
||||
al0.m_alias = m_Aliases->GetCellValue( ci, 0 );
|
||||
al0.m_pathvar = m_Aliases->GetCellValue( ci, 1 );
|
||||
al0.m_description = m_Aliases->GetCellValue( ci, 2 );
|
||||
|
||||
ni = ci + 1;
|
||||
m_Aliases->SetCellValue( ci, 0, m_Aliases->GetCellValue( ni, 0 ) );
|
||||
m_Aliases->SetCellValue( ci, 1, m_Aliases->GetCellValue( ni, 1 ) );
|
||||
m_Aliases->SetCellValue( ci, 2, m_Aliases->GetCellValue( ni, 2 ) );
|
||||
|
||||
m_Aliases->SetCellValue( ni, 0, al0.m_alias );
|
||||
m_Aliases->SetCellValue( ni, 1, al0.m_pathvar );
|
||||
m_Aliases->SetCellValue( ni, 2, al0.m_description );
|
||||
m_Aliases->SelectRow( ni, false );
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnConfigEnvVar( wxCommandEvent& event )
|
||||
{
|
||||
Pgm().ConfigurePaths( this );
|
||||
updateEnvVars();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::updateEnvVars( void )
|
||||
{
|
||||
if( !m_resolver )
|
||||
return;
|
||||
|
||||
std::list< wxString > epaths;
|
||||
|
||||
m_resolver->GetKicadPaths( epaths );
|
||||
size_t nitems = epaths.size();
|
||||
size_t nrows = m_EnvVars->GetNumberRows();
|
||||
bool resize = nrows != nitems; // true after adding/removing env vars
|
||||
|
||||
if( nrows > nitems )
|
||||
{
|
||||
size_t ni = nrows - nitems;
|
||||
m_EnvVars->DeleteRows( 0, ni );
|
||||
}
|
||||
else if( nrows < nitems )
|
||||
{
|
||||
size_t ni = nitems - nrows;
|
||||
m_EnvVars->InsertRows( 0, ni );
|
||||
}
|
||||
|
||||
int j = 0;
|
||||
|
||||
for( const auto& i : epaths )
|
||||
{
|
||||
wxString val = ExpandEnvVarSubstitutions( i );
|
||||
m_EnvVars->SetCellValue( j, 0, i );
|
||||
m_EnvVars->SetCellValue( j, 1, val );
|
||||
m_EnvVars->SetReadOnly( j, 0, true );
|
||||
m_EnvVars->SetReadOnly( j, 1, true );
|
||||
wxGridCellAttr* ap = m_EnvVars->GetOrCreateCellAttr( j, 0 );
|
||||
ap->SetReadOnly( true );
|
||||
ap->SetBackgroundColour( *wxLIGHT_GREY );
|
||||
m_EnvVars->SetRowAttr( j, ap );
|
||||
++j;
|
||||
}
|
||||
|
||||
m_EnvVars->AutoSize();
|
||||
|
||||
// Resizing the full dialog is sometimes needed for a clean display
|
||||
// i.e. when adding/removing Kicad environment variables
|
||||
if( resize )
|
||||
GetSizer()->SetSizeHints( this );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_3D_PATH_CONFIG::OnHelp( wxCommandEvent& event )
|
||||
{
|
||||
wxString msg = _( "Enter the name and path for each 3D alias variable.<br>KiCad "
|
||||
"environment variables and their values are shown for "
|
||||
"reference only and cannot be edited." );
|
||||
msg << "<br><br><b>";
|
||||
msg << _( "Alias names may not contain any of the characters " );
|
||||
msg << "{}[]()%~<>\"='`;:.,&?/\\|$";
|
||||
msg << "</b>";
|
||||
|
||||
HTML_MESSAGE_BOX dlg( GetParent(), _( "Environment Variable Help" ) );
|
||||
dlg.AddHTML_Text( msg );
|
||||
dlg.ShowModal();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DLG_3D_PATHCONFIG_H
|
||||
#define DLG_3D_PATHCONFIG_H
|
||||
|
||||
#include <wx/valtext.h>
|
||||
#include "dlg_3d_pathconfig_base.h"
|
||||
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
|
||||
class DLG_3D_PATH_CONFIG : public DLG_3D_PATH_CONFIG_BASE
|
||||
{
|
||||
private:
|
||||
S3D_FILENAME_RESOLVER* m_resolver;
|
||||
wxString m_curdir;
|
||||
wxTextValidator m_aliasValidator;
|
||||
|
||||
void initDialog();
|
||||
|
||||
void OnAddAlias( wxCommandEvent& event ) override;
|
||||
void OnDelAlias( wxCommandEvent& event ) override;
|
||||
void OnAliasMoveUp( wxCommandEvent& event ) override;
|
||||
void OnAliasMoveDown( wxCommandEvent& event ) override;
|
||||
void OnConfigEnvVar( wxCommandEvent& event ) override;
|
||||
void OnHelp( wxCommandEvent& event ) override;
|
||||
|
||||
public:
|
||||
DLG_3D_PATH_CONFIG( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
private:
|
||||
void updateEnvVars( void );
|
||||
};
|
||||
|
||||
#endif // DLG_3D_PATHCONFIG_H
|
||||
@@ -0,0 +1,162 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 22 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dlg_3d_pathconfig_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DLG_3D_PATH_CONFIG_BASE::DLG_3D_PATH_CONFIG_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bSizerMain;
|
||||
bSizerMain = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer5;
|
||||
bSizer5 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_EnvVars = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_EnvVars->CreateGrid( 1, 2 );
|
||||
m_EnvVars->EnableEditing( true );
|
||||
m_EnvVars->EnableGridLines( true );
|
||||
m_EnvVars->EnableDragGridSize( false );
|
||||
m_EnvVars->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_EnvVars->SetColSize( 0, 150 );
|
||||
m_EnvVars->SetColSize( 1, 300 );
|
||||
m_EnvVars->EnableDragColMove( false );
|
||||
m_EnvVars->EnableDragColSize( true );
|
||||
m_EnvVars->SetColLabelSize( 30 );
|
||||
m_EnvVars->SetColLabelValue( 0, _("Name") );
|
||||
m_EnvVars->SetColLabelValue( 1, _("Path") );
|
||||
m_EnvVars->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Rows
|
||||
m_EnvVars->EnableDragRowSize( true );
|
||||
m_EnvVars->SetRowLabelSize( 80 );
|
||||
m_EnvVars->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_EnvVars->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
m_EnvVars->SetMinSize( wxSize( 250,100 ) );
|
||||
|
||||
bSizer5->Add( m_EnvVars, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_btnEnvCfg = new wxButton( this, wxID_ANY, _("Configure Environment Variables"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizer5->Add( m_btnEnvCfg, 0, wxALIGN_CENTER|wxALL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizer5, 0, wxEXPAND, 5 );
|
||||
|
||||
m_staticline2 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizerMain->Add( m_staticline2, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
wxBoxSizer* bSizerGrid;
|
||||
bSizerGrid = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_Aliases = new wxGrid( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
|
||||
// Grid
|
||||
m_Aliases->CreateGrid( 1, 3 );
|
||||
m_Aliases->EnableEditing( true );
|
||||
m_Aliases->EnableGridLines( true );
|
||||
m_Aliases->EnableDragGridSize( false );
|
||||
m_Aliases->SetMargins( 0, 0 );
|
||||
|
||||
// Columns
|
||||
m_Aliases->SetColSize( 0, 80 );
|
||||
m_Aliases->SetColSize( 1, 300 );
|
||||
m_Aliases->SetColSize( 2, 120 );
|
||||
m_Aliases->EnableDragColMove( false );
|
||||
m_Aliases->EnableDragColSize( true );
|
||||
m_Aliases->SetColLabelSize( 30 );
|
||||
m_Aliases->SetColLabelValue( 0, _("Alias") );
|
||||
m_Aliases->SetColLabelValue( 1, _("Path") );
|
||||
m_Aliases->SetColLabelValue( 2, _("Description") );
|
||||
m_Aliases->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Rows
|
||||
m_Aliases->AutoSizeRows();
|
||||
m_Aliases->EnableDragRowSize( false );
|
||||
m_Aliases->SetRowLabelSize( 80 );
|
||||
m_Aliases->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
|
||||
|
||||
// Label Appearance
|
||||
|
||||
// Cell Defaults
|
||||
m_Aliases->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_TOP );
|
||||
m_Aliases->SetMinSize( wxSize( -1,150 ) );
|
||||
|
||||
bSizerGrid->Add( m_Aliases, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizerGrid, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerButtons;
|
||||
bSizerButtons = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_btnAddAlias = new wxButton( this, wxID_ANY, _("Add Alias"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnAddAlias, 0, wxALL, 5 );
|
||||
|
||||
m_btnDelAlias = new wxButton( this, wxID_ANY, _("Remove Alias"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnDelAlias, 0, wxALL, 5 );
|
||||
|
||||
m_btnMoveUp = new wxButton( this, wxID_ANY, _("Move Up"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnMoveUp, 0, wxALL, 5 );
|
||||
|
||||
m_btnMoveDown = new wxButton( this, wxID_ANY, _("Move Down"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
bSizerButtons->Add( m_btnMoveDown, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( bSizerButtons, 0, wxALIGN_CENTER_HORIZONTAL, 5 );
|
||||
|
||||
m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizerMain->Add( m_staticline1, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
m_sdbSizer2 = new wxStdDialogButtonSizer();
|
||||
m_sdbSizer2OK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizer2->AddButton( m_sdbSizer2OK );
|
||||
m_sdbSizer2Cancel = new wxButton( this, wxID_CANCEL );
|
||||
m_sdbSizer2->AddButton( m_sdbSizer2Cancel );
|
||||
m_sdbSizer2Help = new wxButton( this, wxID_HELP );
|
||||
m_sdbSizer2->AddButton( m_sdbSizer2Help );
|
||||
m_sdbSizer2->Realize();
|
||||
|
||||
bSizerMain->Add( m_sdbSizer2, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizerMain );
|
||||
this->Layout();
|
||||
bSizerMain->Fit( this );
|
||||
|
||||
this->Centre( wxBOTH );
|
||||
|
||||
// Connect Events
|
||||
m_btnEnvCfg->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnConfigEnvVar ), NULL, this );
|
||||
m_btnAddAlias->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAddAlias ), NULL, this );
|
||||
m_btnDelAlias->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnDelAlias ), NULL, this );
|
||||
m_btnMoveUp->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveUp ), NULL, this );
|
||||
m_btnMoveDown->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveDown ), NULL, this );
|
||||
m_sdbSizer2Help->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnHelp ), NULL, this );
|
||||
}
|
||||
|
||||
DLG_3D_PATH_CONFIG_BASE::~DLG_3D_PATH_CONFIG_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
m_btnEnvCfg->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnConfigEnvVar ), NULL, this );
|
||||
m_btnAddAlias->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAddAlias ), NULL, this );
|
||||
m_btnDelAlias->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnDelAlias ), NULL, this );
|
||||
m_btnMoveUp->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveUp ), NULL, this );
|
||||
m_btnMoveDown->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnAliasMoveDown ), NULL, this );
|
||||
m_sdbSizer2Help->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DLG_3D_PATH_CONFIG_BASE::OnHelp ), NULL, this );
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Nov 22 2017)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __DLG_3D_PATHCONFIG_BASE_H__
|
||||
#define __DLG_3D_PATHCONFIG_BASE_H__
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
#include "dialog_shim.h"
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class DLG_3D_PATH_CONFIG_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class DLG_3D_PATH_CONFIG_BASE : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxGrid* m_EnvVars;
|
||||
wxButton* m_btnEnvCfg;
|
||||
wxStaticLine* m_staticline2;
|
||||
wxGrid* m_Aliases;
|
||||
wxButton* m_btnAddAlias;
|
||||
wxButton* m_btnDelAlias;
|
||||
wxButton* m_btnMoveUp;
|
||||
wxButton* m_btnMoveDown;
|
||||
wxStaticLine* m_staticline1;
|
||||
wxStdDialogButtonSizer* m_sdbSizer2;
|
||||
wxButton* m_sdbSizer2OK;
|
||||
wxButton* m_sdbSizer2Cancel;
|
||||
wxButton* m_sdbSizer2Help;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void OnConfigEnvVar( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnAddAlias( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnDelAlias( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnAliasMoveUp( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnAliasMoveDown( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnHelp( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
DLG_3D_PATH_CONFIG_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("3D Search Path Configuration"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DLG_3D_PATH_CONFIG_BASE();
|
||||
|
||||
};
|
||||
|
||||
#endif //__DLG_3D_PATHCONFIG_BASE_H__
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017-2018 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
#include <set>
|
||||
#include "dlg_select_3dmodel.h"
|
||||
#include "project.h"
|
||||
#include "3d_cache/3d_info.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include "3d_cache_dialogs.h"
|
||||
#include <3d_model_viewer/c3d_model_viewer.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <pcbnew/class_module.h>
|
||||
|
||||
#define ID_FILE_TREE ( wxID_LAST + 1 )
|
||||
#define ID_SET_DIR ( ID_FILE_TREE + 1 )
|
||||
#define ID_CFG_PATHS ( ID_SET_DIR + 1 )
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE( DLG_SELECT_3DMODEL, DIALOG_SHIM )
|
||||
EVT_DIRCTRL_SELECTIONCHANGED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnSelectionChanged )
|
||||
EVT_DIRCTRL_FILEACTIVATED( ID_FILE_TREE, DLG_SELECT_3DMODEL::OnFileActivated )
|
||||
EVT_CHOICE( ID_SET_DIR, DLG_SELECT_3DMODEL::SetRootDir )
|
||||
EVT_BUTTON( ID_CFG_PATHS, DLG_SELECT_3DMODEL::Cfg3DPaths )
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
DLG_SELECT_3DMODEL::DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE_3D_SETTINGS* aModelItem, wxString& prevModelSelectDir, int& prevModelWildcard ) :
|
||||
DIALOG_SHIM( aParent, wxID_ANY, _( "Select 3D Model" ), wxDefaultPosition,
|
||||
wxSize( 500,200 ), wxCAPTION | wxRESIZE_BORDER | wxCLOSE_BOX
|
||||
| wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxSYSTEM_MENU ),
|
||||
m_model( aModelItem ), m_cache( aCacheManager ), m_previousDir( prevModelSelectDir ),
|
||||
m_previousFilterIndex( prevModelWildcard )
|
||||
{
|
||||
SetSizeHints( wxSize( 500,200 ), wxDefaultSize );
|
||||
|
||||
if( NULL != m_cache )
|
||||
m_resolver = m_cache->GetResolver();
|
||||
else
|
||||
m_resolver = NULL;
|
||||
|
||||
wxBoxSizer* bSizer0 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizer1 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizer2 = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
// set to NULL to avoid segfaults when m_FileTree is instantiated
|
||||
// and wxGenericDirCtrl events are posted
|
||||
m_modelViewer = NULL;
|
||||
dirChoices = NULL;
|
||||
|
||||
m_FileTree = new wxGenericDirCtrl( this, ID_FILE_TREE, prevModelSelectDir, wxDefaultPosition,
|
||||
wxSize( 300,100 ), wxDIRCTRL_3D_INTERNAL | wxDIRCTRL_EDIT_LABELS
|
||||
| wxDIRCTRL_SELECT_FIRST | wxDIRCTRL_SHOW_FILTERS|wxSUNKEN_BORDER, wxEmptyString, 0 );
|
||||
|
||||
|
||||
m_FileTree->ShowHidden( false );
|
||||
m_FileTree->SetMinSize( wxSize( 300, 400 ) );
|
||||
m_FileTree->SetLabel( wxT( "3D_MODEL_SELECTOR" ) );
|
||||
|
||||
bSizer2->Add( m_FileTree, 1, wxEXPAND | wxALL, 5 );
|
||||
bSizer1->Add( bSizer2, 3, wxEXPAND, 5 );
|
||||
|
||||
m_modelViewer = new C3D_MODEL_VIEWER( this, COGL_ATT_LIST::GetAttributesList( true ), m_cache );
|
||||
m_modelViewer->SetMinSize( wxSize( 500, 400 ) );
|
||||
|
||||
bSizer1->Add( m_modelViewer, 5, wxEXPAND | wxALL | wxCENTER, 5 );
|
||||
|
||||
// create the filter list
|
||||
if( NULL != m_cache )
|
||||
{
|
||||
std::list< wxString > const* fl = m_cache->GetFileFilters();
|
||||
std::list< wxString >::const_iterator sL = fl->begin();
|
||||
std::list< wxString >::const_iterator eL = fl->end();
|
||||
wxString filter;
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
filter.Append( *sL );
|
||||
|
||||
++sL;
|
||||
|
||||
if( sL != eL )
|
||||
filter.Append( wxT( "|" ) );
|
||||
}
|
||||
|
||||
if( !filter.empty() )
|
||||
m_FileTree->SetFilter( filter );
|
||||
else
|
||||
m_FileTree->SetFilter( wxT( "*.*" ) );
|
||||
|
||||
if( prevModelWildcard >= 0 && prevModelWildcard < (int)fl->size() )
|
||||
m_FileTree->SetFilterIndex( prevModelWildcard );
|
||||
else
|
||||
{
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_FileTree->SetFilter( wxT( "*.*" ) );
|
||||
prevModelWildcard = 0;
|
||||
m_FileTree->SetFilterIndex( 0 );
|
||||
}
|
||||
|
||||
// Add the path choice box and config button
|
||||
wxBoxSizer* hboxDirChoice = new wxBoxSizer( wxHORIZONTAL );
|
||||
dirChoices = new wxChoice( this, ID_SET_DIR, wxDefaultPosition, wxSize( 320, 20 ) );
|
||||
dirChoices->SetMinSize( wxSize( 320, 12 ) );
|
||||
|
||||
wxStaticText* stDirChoice = new wxStaticText( this, -1, _( "Paths:" ) );
|
||||
wxButton* cfgPaths = new wxButton( this, ID_CFG_PATHS, _( "Configure Paths" ) );
|
||||
hboxDirChoice->Add( stDirChoice, 0, wxALL | wxCENTER, 5 );
|
||||
hboxDirChoice->Add( dirChoices, 1, wxEXPAND | wxALL, 5 );
|
||||
hboxDirChoice->Add( cfgPaths, 0, wxALL, 5 );
|
||||
|
||||
wxButton* btn_OK = new wxButton( this, wxID_OK, _( "OK" ) );
|
||||
wxButton* btn_Cancel = new wxButton( this, wxID_CANCEL, _( "Cancel" ) );
|
||||
|
||||
wxStdDialogButtonSizer* hSizer1 = new wxStdDialogButtonSizer();
|
||||
hSizer1->AddButton( btn_OK );
|
||||
hSizer1->AddButton( btn_Cancel );
|
||||
hSizer1->Realize();
|
||||
|
||||
bSizer0->Add( bSizer1, 1, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hboxDirChoice, 0, wxALL | wxEXPAND, 5 );
|
||||
bSizer0->Add( hSizer1, 0, wxALL | wxEXPAND, 5 );
|
||||
|
||||
updateDirChoiceList();
|
||||
|
||||
SetSizerAndFit( bSizer0 );
|
||||
Layout();
|
||||
Centre( wxBOTH );
|
||||
|
||||
m_modelViewer->Refresh();
|
||||
m_modelViewer->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
bool DLG_SELECT_3DMODEL::TransferDataFromWindow()
|
||||
{
|
||||
if( NULL == m_model || NULL == m_FileTree )
|
||||
return true;
|
||||
|
||||
m_model->m_Scale.x = 1.0;
|
||||
m_model->m_Scale.y = 1.0;
|
||||
m_model->m_Scale.z = 1.0;
|
||||
|
||||
m_model->m_Rotation.x = 0.0;
|
||||
m_model->m_Rotation.y = 0.0;
|
||||
m_model->m_Rotation.z = 0.0;
|
||||
|
||||
m_model->m_Offset = m_model->m_Rotation;
|
||||
m_model->m_Filename.clear();
|
||||
|
||||
wxString name = m_FileTree->GetFilePath();
|
||||
|
||||
if( name.empty() )
|
||||
return true;
|
||||
|
||||
m_previousDir = m_FileTree->GetPath();
|
||||
m_previousFilterIndex = m_FileTree->GetFilterIndex();
|
||||
|
||||
// file selection mode: retrieve the filename and specify a
|
||||
// path relative to one of the config paths
|
||||
wxFileName fname = m_FileTree->GetFilePath();
|
||||
fname.Normalize();
|
||||
m_model->m_Filename = m_resolver->ShortenPath( fname.GetFullPath() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnSelectionChanged( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::OnFileActivated( wxTreeEvent& event )
|
||||
{
|
||||
if( m_modelViewer )
|
||||
m_modelViewer->Set3DModel( m_FileTree->GetFilePath() );
|
||||
|
||||
event.Skip();
|
||||
SetEscapeId( wxID_OK );
|
||||
Close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::SetRootDir( wxCommandEvent& event )
|
||||
{
|
||||
if( m_FileTree )
|
||||
m_FileTree->SetPath( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::Cfg3DPaths( wxCommandEvent& event )
|
||||
{
|
||||
if( S3D::Configure3DPaths( this, m_resolver ) )
|
||||
updateDirChoiceList();
|
||||
}
|
||||
|
||||
|
||||
void DLG_SELECT_3DMODEL::updateDirChoiceList( void )
|
||||
{
|
||||
if( NULL == m_FileTree || NULL == m_resolver || NULL == dirChoices )
|
||||
return;
|
||||
|
||||
std::list< S3D_ALIAS > const* md = m_resolver->GetPaths();
|
||||
std::list< S3D_ALIAS >::const_iterator sL = md->begin();
|
||||
std::list< S3D_ALIAS >::const_iterator eL = md->end();
|
||||
std::set< wxString > cl;
|
||||
wxString prjDir;
|
||||
|
||||
// extract the current project dir
|
||||
if( sL != eL )
|
||||
{
|
||||
prjDir = sL->m_pathexp;
|
||||
++sL;
|
||||
}
|
||||
|
||||
while( sL != eL )
|
||||
{
|
||||
if( !sL->m_pathexp.empty() && sL->m_pathexp.compare( prjDir ) )
|
||||
cl.insert( sL->m_pathexp );
|
||||
|
||||
++sL;
|
||||
}
|
||||
|
||||
if( !cl.empty() )
|
||||
{
|
||||
dirChoices->Clear();
|
||||
|
||||
if( !prjDir.empty() )
|
||||
dirChoices->Append( prjDir );
|
||||
|
||||
std::set< wxString >::const_iterator sI = cl.begin();
|
||||
std::set< wxString >::const_iterator eI = cl.end();
|
||||
|
||||
while( sI != eI )
|
||||
{
|
||||
dirChoices->Append( *sI );
|
||||
++sI;
|
||||
}
|
||||
|
||||
dirChoices->Select( 0 );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2018 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file dlg_select_3dmodel.h
|
||||
* creates a dialog to select 3D model files
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DLG_SELECT_3DMODEL_H
|
||||
#define DLG_SELECT_3DMODEL_H
|
||||
|
||||
#include <wx/event.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/dirctrl.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/frame.h>
|
||||
|
||||
#include <dialog_shim.h>
|
||||
|
||||
class MODULE_3D_SETTINGS;
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class C3D_MODEL_VIEWER;
|
||||
|
||||
class DLG_SELECT_3DMODEL : public DIALOG_SHIM
|
||||
{
|
||||
private:
|
||||
MODULE_3D_SETTINGS* m_model; // data for the selected model
|
||||
S3D_CACHE* m_cache; // cache manager
|
||||
S3D_FILENAME_RESOLVER* m_resolver; // 3D filename resolver
|
||||
|
||||
wxString& m_previousDir;
|
||||
int& m_previousFilterIndex;
|
||||
|
||||
wxGenericDirCtrl* m_FileTree;
|
||||
C3D_MODEL_VIEWER* m_modelViewer;
|
||||
wxChoice* dirChoices;
|
||||
|
||||
void updateDirChoiceList( void );
|
||||
|
||||
public:
|
||||
DLG_SELECT_3DMODEL( wxWindow* aParent, S3D_CACHE* aCacheManager, MODULE_3D_SETTINGS* aModelItem,
|
||||
wxString& prevModelSelectDir, int& prevModelWildcard );
|
||||
|
||||
bool TransferDataFromWindow() override;
|
||||
void OnSelectionChanged( wxTreeEvent& event );
|
||||
void OnFileActivated( wxTreeEvent& event );
|
||||
void SetRootDir( wxCommandEvent& event );
|
||||
void Cfg3DPaths( wxCommandEvent& event );
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
#endif // DLG_SELECT_3DMODEL_H
|
||||
@@ -0,0 +1,353 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jan 12 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PANEL_PREV_3D_BASE::PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
|
||||
{
|
||||
wxBoxSizer* bSizermain;
|
||||
bSizermain = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
wxBoxSizer* bSizerLeft;
|
||||
bSizerLeft = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxBoxSizer* bSizerScale;
|
||||
bSizerScale = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticTextScale = new wxStaticText( this, wxID_ANY, _("Scale"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextScale->Wrap( -1 );
|
||||
bSizerScale->Add( m_staticTextScale, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerScale;
|
||||
fgSizerScale = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerScale->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerScale->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText1 = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText1, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xscale = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( xscale, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXscale = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinXscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText2 = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText2->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yscale = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( yscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_spinYscale = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinYscale, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText3 = new wxStaticText( this, wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText3->Wrap( -1 );
|
||||
fgSizerScale->Add( m_staticText3, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
zscale = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerScale->Add( zscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZscale = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerScale->Add( m_spinZscale, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bSizerScale->Add( fgSizerScale, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( bSizerScale, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerRotation;
|
||||
bSizerRotation = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticTextRot = new wxStaticText( this, wxID_ANY, _("Rotation (degrees)"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextRot->Wrap( -1 );
|
||||
bSizerRotation->Add( m_staticTextRot, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerRotate;
|
||||
fgSizerRotate = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerRotate->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerRotate->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText11 = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText11->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText11, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xrot = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifdef __WXGTK__
|
||||
if ( !xrot->HasFlag( wxTE_MULTILINE ) )
|
||||
{
|
||||
xrot->SetMaxLength( 9 );
|
||||
}
|
||||
#else
|
||||
xrot->SetMaxLength( 9 );
|
||||
#endif
|
||||
fgSizerRotate->Add( xrot, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXrot = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinXrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText21 = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText21->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText21, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yrot = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifdef __WXGTK__
|
||||
if ( !yrot->HasFlag( wxTE_MULTILINE ) )
|
||||
{
|
||||
yrot->SetMaxLength( 9 );
|
||||
}
|
||||
#else
|
||||
yrot->SetMaxLength( 9 );
|
||||
#endif
|
||||
fgSizerRotate->Add( yrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_spinYrot = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinYrot, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText31 = new wxStaticText( this, wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText31->Wrap( -1 );
|
||||
fgSizerRotate->Add( m_staticText31, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
zrot = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
#ifdef __WXGTK__
|
||||
if ( !zrot->HasFlag( wxTE_MULTILINE ) )
|
||||
{
|
||||
zrot->SetMaxLength( 9 );
|
||||
}
|
||||
#else
|
||||
zrot->SetMaxLength( 9 );
|
||||
#endif
|
||||
fgSizerRotate->Add( zrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxLEFT, 5 );
|
||||
|
||||
m_spinZrot = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerRotate->Add( m_spinZrot, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM, 5 );
|
||||
|
||||
|
||||
bSizerRotation->Add( fgSizerRotate, 0, wxEXPAND|wxRIGHT|wxLEFT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( bSizerRotation, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerOffset;
|
||||
bSizerOffset = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticTextOffset = new wxStaticText( this, wxID_ANY, _("Offset"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticTextOffset->Wrap( -1 );
|
||||
bSizerOffset->Add( m_staticTextOffset, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxFlexGridSizer* fgSizerOffset;
|
||||
fgSizerOffset = new wxFlexGridSizer( 0, 3, 0, 0 );
|
||||
fgSizerOffset->SetFlexibleDirection( wxBOTH );
|
||||
fgSizerOffset->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_staticText12 = new wxStaticText( this, wxID_ANY, _("X:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText12->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText12, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
xoff = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( xoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinXoffset = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinXoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText22 = new wxStaticText( this, wxID_ANY, _("Y:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText22->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText22, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
yoff = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( yoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP, 5 );
|
||||
|
||||
m_spinYoffset = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinYoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
m_staticText32 = new wxStaticText( this, wxID_ANY, _("Z:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText32->Wrap( -1 );
|
||||
fgSizerOffset->Add( m_staticText32, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
zoff = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
fgSizerOffset->Add( zoff, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5 );
|
||||
|
||||
m_spinZoffset = new wxSpinButton( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS|wxSP_VERTICAL );
|
||||
fgSizerOffset->Add( m_spinZoffset, 0, wxALIGN_CENTER_VERTICAL, 5 );
|
||||
|
||||
|
||||
bSizerOffset->Add( fgSizerOffset, 0, wxEXPAND|wxLEFT|wxRIGHT, 10 );
|
||||
|
||||
|
||||
bSizerLeft->Add( bSizerOffset, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerLeft, 0, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizerRight;
|
||||
bSizerRight = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_SizerPanelView = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
|
||||
bSizerRight->Add( m_SizerPanelView, 1, wxEXPAND, 5 );
|
||||
|
||||
wxBoxSizer* bSizer3DButtons;
|
||||
bSizer3DButtons = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_fgSizerButtons = new wxFlexGridSizer( 0, 4, 0, 0 );
|
||||
m_fgSizerButtons->AddGrowableCol( 0 );
|
||||
m_fgSizerButtons->AddGrowableCol( 1 );
|
||||
m_fgSizerButtons->AddGrowableCol( 2 );
|
||||
m_fgSizerButtons->AddGrowableCol( 3 );
|
||||
m_fgSizerButtons->SetFlexibleDirection( wxBOTH );
|
||||
m_fgSizerButtons->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
|
||||
|
||||
m_bpvISO = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_bpvISO->SetToolTip( _("Change to isometric perspective") );
|
||||
|
||||
m_fgSizerButtons->Add( m_bpvISO, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvLeft = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvLeft, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvFront = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvFront, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvTop = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvTop, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpUpdate = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_bpUpdate->SetToolTip( _("Reload board and 3D models") );
|
||||
|
||||
m_fgSizerButtons->Add( m_bpUpdate, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvRight = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvRight, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvBack = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvBack, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bpvBottom = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
|
||||
m_fgSizerButtons->Add( m_bpvBottom, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( m_fgSizerButtons, 6, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizer3DButtons->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizerRight->Add( bSizer3DButtons, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
|
||||
bSizermain->Add( bSizerRight, 1, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bSizermain );
|
||||
this->Layout();
|
||||
bSizermain->Fit( this );
|
||||
|
||||
// Connect Events
|
||||
xscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Connect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvFront->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvTop->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpUpdate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
m_bpvRight->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvBack->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvBottom->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
}
|
||||
|
||||
PANEL_PREV_3D_BASE::~PANEL_PREV_3D_BASE()
|
||||
{
|
||||
// Disconnect Events
|
||||
xscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
xscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinXscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
yscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinYscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelScale ), NULL, this );
|
||||
zscale->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementScale ), NULL, this );
|
||||
m_spinZscale->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementScale ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
xrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinXrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
yrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinYrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelRot ), NULL, this );
|
||||
zrot->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementRot ), NULL, this );
|
||||
m_spinZrot->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementRot ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
xoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinXoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
yoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinYoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( PANEL_PREV_3D_BASE::onMouseWheelOffset ), NULL, this );
|
||||
zoff->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( PANEL_PREV_3D_BASE::updateOrientation ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEDOWN, wxSpinEventHandler( PANEL_PREV_3D_BASE::onDecrementOffset ), NULL, this );
|
||||
m_spinZoffset->Disconnect( wxEVT_SCROLL_LINEUP, wxSpinEventHandler( PANEL_PREV_3D_BASE::onIncrementOffset ), NULL, this );
|
||||
m_bpvISO->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DISO ), NULL, this );
|
||||
m_bpvLeft->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DLeft ), NULL, this );
|
||||
m_bpvFront->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DFront ), NULL, this );
|
||||
m_bpvTop->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DTop ), NULL, this );
|
||||
m_bpUpdate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DUpdate ), NULL, this );
|
||||
m_bpvRight->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DRight ), NULL, this );
|
||||
m_bpvBack->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBack ), NULL, this );
|
||||
m_bpvBottom->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PREV_3D_BASE::View3DBottom ), NULL, this );
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,110 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version Jan 12 2018)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO *NOT* EDIT THIS FILE!
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __PANEL_PREV_3D_BASE_H__
|
||||
#define __PANEL_PREV_3D_BASE_H__
|
||||
|
||||
#include <wx/artprov.h>
|
||||
#include <wx/xrc/xmlres.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/spinbutt.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Class PANEL_PREV_3D_BASE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class PANEL_PREV_3D_BASE : public wxPanel
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxStaticText* m_staticTextScale;
|
||||
wxStaticText* m_staticText1;
|
||||
wxTextCtrl* xscale;
|
||||
wxSpinButton* m_spinXscale;
|
||||
wxStaticText* m_staticText2;
|
||||
wxTextCtrl* yscale;
|
||||
wxSpinButton* m_spinYscale;
|
||||
wxStaticText* m_staticText3;
|
||||
wxTextCtrl* zscale;
|
||||
wxSpinButton* m_spinZscale;
|
||||
wxStaticText* m_staticTextRot;
|
||||
wxStaticText* m_staticText11;
|
||||
wxTextCtrl* xrot;
|
||||
wxSpinButton* m_spinXrot;
|
||||
wxStaticText* m_staticText21;
|
||||
wxTextCtrl* yrot;
|
||||
wxSpinButton* m_spinYrot;
|
||||
wxStaticText* m_staticText31;
|
||||
wxTextCtrl* zrot;
|
||||
wxSpinButton* m_spinZrot;
|
||||
wxStaticText* m_staticTextOffset;
|
||||
wxStaticText* m_staticText12;
|
||||
wxTextCtrl* xoff;
|
||||
wxSpinButton* m_spinXoffset;
|
||||
wxStaticText* m_staticText22;
|
||||
wxSpinButton* m_spinYoffset;
|
||||
wxStaticText* m_staticText32;
|
||||
wxTextCtrl* zoff;
|
||||
wxSpinButton* m_spinZoffset;
|
||||
wxBoxSizer* m_SizerPanelView;
|
||||
wxFlexGridSizer* m_fgSizerButtons;
|
||||
wxBitmapButton* m_bpvISO;
|
||||
wxBitmapButton* m_bpvLeft;
|
||||
wxBitmapButton* m_bpvFront;
|
||||
wxBitmapButton* m_bpvTop;
|
||||
wxBitmapButton* m_bpUpdate;
|
||||
wxBitmapButton* m_bpvRight;
|
||||
wxBitmapButton* m_bpvBack;
|
||||
wxBitmapButton* m_bpvBottom;
|
||||
|
||||
// Virtual event handlers, overide them in your derived class
|
||||
virtual void onMouseWheelScale( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void updateOrientation( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementScale( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelRot( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementRot( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onMouseWheelOffset( wxMouseEvent& event ) { event.Skip(); }
|
||||
virtual void onDecrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void onIncrementOffset( wxSpinEvent& event ) { event.Skip(); }
|
||||
virtual void View3DISO( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DLeft( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DFront( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DTop( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DUpdate( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DRight( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBack( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void View3DBottom( wxCommandEvent& event ) { event.Skip(); }
|
||||
|
||||
|
||||
public:
|
||||
wxTextCtrl* yoff;
|
||||
|
||||
PANEL_PREV_3D_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
|
||||
~PANEL_PREV_3D_BASE();
|
||||
|
||||
};
|
||||
|
||||
#endif //__PANEL_PREV_3D_BASE_H__
|
||||
@@ -0,0 +1,693 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 2015-2018 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.cpp
|
||||
*/
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
#include <common_ogl/cogl_att_list.h>
|
||||
#include <cstdlib>
|
||||
#include <limits.h>
|
||||
#include <bitmaps.h>
|
||||
|
||||
#include <wx/valnum.h>
|
||||
#include <wx/tglbtn.h>
|
||||
|
||||
#include "project.h"
|
||||
#include "panel_prev_model.h"
|
||||
#include <class_board.h>
|
||||
|
||||
|
||||
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE* aModuleCopy,
|
||||
COLORS_DESIGN_SETTINGS *aColors,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentInfoList ) :
|
||||
PANEL_PREV_3D_BASE( aParent, wxID_ANY )
|
||||
{
|
||||
initPanel();
|
||||
|
||||
// Initialize the color settings to draw the board and the footprint
|
||||
if( aColors )
|
||||
m_dummyBoard->SetColorsSettings( aColors );
|
||||
else
|
||||
{
|
||||
static COLORS_DESIGN_SETTINGS defaultColors( FRAME_PCB_DISPLAY3D );
|
||||
m_dummyBoard->SetColorsSettings( &defaultColors );
|
||||
}
|
||||
|
||||
if( NULL != aCacheManager )
|
||||
m_resolver = aCacheManager->GetResolver();
|
||||
|
||||
m_parentInfoList = aParentInfoList;
|
||||
|
||||
m_dummyBoard->Add( (MODULE*)aModuleCopy );
|
||||
m_copyModule = aModuleCopy;
|
||||
|
||||
// Set 3d viewer configuration for preview
|
||||
m_settings3Dviewer = new CINFO3D_VISU();
|
||||
|
||||
// Create the 3D canvas
|
||||
m_previewPane = new EDA_3D_CANVAS( this,
|
||||
COGL_ATT_LIST::GetAttributesList( true ),
|
||||
m_dummyBoard,
|
||||
*m_settings3Dviewer,
|
||||
aCacheManager );
|
||||
|
||||
m_SizerPanelView->Add( m_previewPane, 1, wxEXPAND );
|
||||
|
||||
m_previewPane->Connect( wxEVT_ENTER_WINDOW,
|
||||
wxMouseEventHandler( PANEL_PREV_3D::onEnterPreviewCanvas ),
|
||||
NULL, this );
|
||||
}
|
||||
|
||||
|
||||
PANEL_PREV_3D::~PANEL_PREV_3D()
|
||||
{
|
||||
m_previewPane->Disconnect( wxEVT_ENTER_WINDOW,
|
||||
wxMouseEventHandler( PANEL_PREV_3D::onEnterPreviewCanvas ),
|
||||
NULL, this );
|
||||
|
||||
delete m_settings3Dviewer;
|
||||
delete m_dummyBoard;
|
||||
delete m_previewPane;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::initPanel()
|
||||
{
|
||||
m_resolver = NULL;
|
||||
currentModelFile.clear();
|
||||
m_dummyBoard = new BOARD();
|
||||
m_currentSelectedIdx = -1;
|
||||
|
||||
// Set the bitmap of 3D view buttons:
|
||||
m_bpvTop->SetBitmap( KiBitmap( axis3d_top_xpm ) );
|
||||
m_bpvFront->SetBitmap( KiBitmap( axis3d_front_xpm ) );
|
||||
m_bpvBack->SetBitmap( KiBitmap( axis3d_back_xpm ) );
|
||||
m_bpvLeft->SetBitmap( KiBitmap( axis3d_left_xpm ) );
|
||||
m_bpvRight->SetBitmap( KiBitmap( axis3d_right_xpm ) );
|
||||
m_bpvBottom->SetBitmap( KiBitmap( axis3d_bottom_xpm ) );
|
||||
m_bpvISO->SetBitmap( KiBitmap( ortho_xpm ) );
|
||||
m_bpUpdate->SetBitmap( KiBitmap( reload_xpm ) );
|
||||
|
||||
// Set the min and max values of spin buttons (mandatory on Linux)
|
||||
// They are not used, so they are set to min and max 32 bits int values
|
||||
// (the min and max values supported by a wxSpinButton)
|
||||
// It avoids blocking the up or down arrows when reaching this limit after
|
||||
// a few clicks.
|
||||
wxSpinButton* spinButtonList[] =
|
||||
{
|
||||
m_spinXscale, m_spinYscale, m_spinZscale,
|
||||
m_spinXrot, m_spinYrot, m_spinZrot,
|
||||
m_spinXoffset,m_spinYoffset, m_spinZoffset
|
||||
};
|
||||
|
||||
for( int ii = 0; ii < 9; ii++ )
|
||||
{
|
||||
spinButtonList[ii]->SetRange( INT_MIN, INT_MAX );
|
||||
}
|
||||
|
||||
wxString units;
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
case INCHES:
|
||||
units = _( "inches" );
|
||||
break;
|
||||
case MILLIMETRES:
|
||||
units = _( "mm" );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !units.IsEmpty() )
|
||||
{
|
||||
units = wxString::Format( _( "Offset (%s)" ), units );
|
||||
m_staticTextOffset->SetLabel( units );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief checkRotation
|
||||
* Ensure -MAX_ROTATION <= rotation <= MAX_ROTATION
|
||||
* aRotation will be normalized between -MAX_ROTATION and MAX_ROTATION
|
||||
* @param aRotation: in out parameter
|
||||
*/
|
||||
static void checkRotation( double& aRotation )
|
||||
{
|
||||
if( aRotation > MAX_ROTATION )
|
||||
{
|
||||
int n = aRotation / MAX_ROTATION;
|
||||
aRotation -= MAX_ROTATION * n;
|
||||
}
|
||||
else if( aRotation < -MAX_ROTATION )
|
||||
{
|
||||
int n = -aRotation / MAX_ROTATION;
|
||||
aRotation += MAX_ROTATION * n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool validateFloatTextCtrl( wxTextCtrl* aTextCtrl )
|
||||
{
|
||||
if( aTextCtrl == NULL )
|
||||
return false;
|
||||
|
||||
if( aTextCtrl->GetLineLength(0) == 0 ) // This will skip the got and event with empty field
|
||||
return false;
|
||||
|
||||
if( aTextCtrl->GetLineLength(0) == 1 )
|
||||
{
|
||||
if( (aTextCtrl->GetLineText(0).compare( "." ) == 0) ||
|
||||
(aTextCtrl->GetLineText(0).compare( "," ) == 0) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void incrementTextCtrl( wxTextCtrl* aTextCtrl, double aInc, double aMinval, double aMaxval )
|
||||
{
|
||||
if( !validateFloatTextCtrl( aTextCtrl ) )
|
||||
return;
|
||||
|
||||
double curr_value = 0;
|
||||
|
||||
aTextCtrl->GetValue().ToDouble( &curr_value );
|
||||
curr_value += aInc;
|
||||
|
||||
if( curr_value > aMaxval )
|
||||
curr_value = aMaxval;
|
||||
|
||||
if( curr_value < aMinval )
|
||||
curr_value = aMinval;
|
||||
|
||||
aTextCtrl->SetValue( wxString::Format( "%.4f", curr_value ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::SetModelDataIdx( int idx, bool aReloadPreviewModule )
|
||||
{
|
||||
wxASSERT( m_parentInfoList != NULL );
|
||||
|
||||
if( m_parentInfoList && (idx >= 0) )
|
||||
{
|
||||
wxASSERT( (unsigned int)idx < (*m_parentInfoList).size() );
|
||||
|
||||
if( (unsigned int)idx < (*m_parentInfoList).size() )
|
||||
{
|
||||
m_currentSelectedIdx = -1; // In case that we receive events on the
|
||||
// next updates, it will set first an
|
||||
// invalid selection
|
||||
|
||||
const MODULE_3D_SETTINGS *aModel = (const MODULE_3D_SETTINGS *)&((*m_parentInfoList)[idx]);
|
||||
|
||||
xscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.x ) );
|
||||
yscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.y ) );
|
||||
zscale->SetValue( wxString::Format( "%.4f", aModel->m_Scale.z ) );
|
||||
|
||||
xrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.x ) );
|
||||
yrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.y ) );
|
||||
zrot->SetValue( wxString::Format( "%.2f", aModel->m_Rotation.z ) );
|
||||
|
||||
// Convert from internal units (mm) to user units
|
||||
|
||||
double scaler = 1;
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
case MILLIMETRES:
|
||||
scaler = 1.0f;
|
||||
break;
|
||||
case INCHES:
|
||||
scaler = 25.4f;
|
||||
break;
|
||||
default:
|
||||
wxASSERT( 0 );
|
||||
}
|
||||
|
||||
xoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.x / scaler ) );
|
||||
yoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.y / scaler ) );
|
||||
zoff->SetValue( wxString::Format( "%.4f", aModel->m_Offset.z / scaler ) );
|
||||
|
||||
UpdateModelName( aModel->m_Filename );
|
||||
|
||||
if( aReloadPreviewModule && m_previewPane )
|
||||
{
|
||||
updateListOnModelCopy();
|
||||
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Request_refresh();
|
||||
}
|
||||
|
||||
m_currentSelectedIdx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::ResetModelData( bool aReloadPreviewModule )
|
||||
{
|
||||
m_currentSelectedIdx = -1;
|
||||
|
||||
xscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
yscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
zscale->SetValue( wxString::FromDouble( 1.0 ) );
|
||||
|
||||
xrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
yrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
zrot->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
|
||||
xoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
yoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
zoff->SetValue( wxString::FromDouble( 0.0 ) );
|
||||
|
||||
// This will update the model on the preview board with the current list of 3d shapes
|
||||
if( aReloadPreviewModule )
|
||||
{
|
||||
updateListOnModelCopy();
|
||||
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Request_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
if( m_previewPane )
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
|
||||
{
|
||||
bool newModel = false;
|
||||
|
||||
m_modelInfo.m_Filename = aModelName;
|
||||
|
||||
// if the model name is a directory simply clear the current model
|
||||
if( aModelName.empty() || wxFileName::DirExists( aModelName ) )
|
||||
{
|
||||
currentModelFile.clear();
|
||||
m_modelInfo.m_Filename.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxString newModelFile;
|
||||
|
||||
if( m_resolver )
|
||||
newModelFile = m_resolver->ResolvePath( aModelName );
|
||||
|
||||
if( !newModelFile.empty() && newModelFile.Cmp( currentModelFile ) )
|
||||
newModel = true;
|
||||
|
||||
currentModelFile = newModelFile;
|
||||
}
|
||||
|
||||
if( currentModelFile.empty() || newModel )
|
||||
{
|
||||
updateListOnModelCopy();
|
||||
|
||||
if( m_previewPane )
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
if( currentModelFile.empty() )
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_previewPane )
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
if( m_previewPane )
|
||||
m_previewPane->SetFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateOrientation( wxCommandEvent &event )
|
||||
{
|
||||
wxTextCtrl *textCtrl = (wxTextCtrl *)event.GetEventObject();
|
||||
|
||||
if( textCtrl == NULL )
|
||||
return;
|
||||
|
||||
if( textCtrl->GetLineLength(0) == 0 ) // This will skip the got and event with empty field
|
||||
return;
|
||||
|
||||
if( textCtrl->GetLineLength(0) == 1 )
|
||||
if( (textCtrl->GetLineText(0).compare( "." ) == 0) ||
|
||||
(textCtrl->GetLineText(0).compare( "," ) == 0) )
|
||||
return;
|
||||
|
||||
SGPOINT scale;
|
||||
SGPOINT rotation;
|
||||
SGPOINT offset;
|
||||
|
||||
getOrientationVars( scale, rotation, offset );
|
||||
|
||||
m_modelInfo.m_Scale.x = scale.x;
|
||||
m_modelInfo.m_Scale.y = scale.y;
|
||||
m_modelInfo.m_Scale.z = scale.z;
|
||||
m_modelInfo.m_Offset.x = offset.x;
|
||||
m_modelInfo.m_Offset.y = offset.y;
|
||||
m_modelInfo.m_Offset.z = offset.z;
|
||||
m_modelInfo.m_Rotation.x = rotation.x;
|
||||
m_modelInfo.m_Rotation.y = rotation.y;
|
||||
m_modelInfo.m_Rotation.z = rotation.z;
|
||||
|
||||
if( m_currentSelectedIdx >= 0 )
|
||||
{
|
||||
// This will update the parent list with the new data
|
||||
(*m_parentInfoList)[m_currentSelectedIdx] = m_modelInfo;
|
||||
|
||||
// It will update the copy model in the preview board
|
||||
updateListOnModelCopy();
|
||||
|
||||
// Since the OpenGL render does not need to be reloaded to update the
|
||||
// shapes position, we just request to redraw again the canvas
|
||||
if( m_previewPane )
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onIncrementRot( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xrot;
|
||||
|
||||
if( spinCtrl == m_spinYrot )
|
||||
textCtrl = yrot;
|
||||
else if( spinCtrl == m_spinZrot )
|
||||
textCtrl = zrot;
|
||||
|
||||
incrementTextCtrl( textCtrl, ROTATION_INCREMENT, -MAX_ROTATION, MAX_ROTATION );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onDecrementRot( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xrot;
|
||||
|
||||
if( spinCtrl == m_spinYrot )
|
||||
textCtrl = yrot;
|
||||
else if( spinCtrl == m_spinZrot )
|
||||
textCtrl = zrot;
|
||||
|
||||
incrementTextCtrl( textCtrl, -ROTATION_INCREMENT, -MAX_ROTATION, MAX_ROTATION );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onIncrementScale( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xscale;
|
||||
|
||||
if( spinCtrl == m_spinYscale )
|
||||
textCtrl = yscale;
|
||||
else if( spinCtrl == m_spinZscale )
|
||||
textCtrl = zscale;
|
||||
|
||||
incrementTextCtrl( textCtrl, SCALE_INCREMENT, 1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onDecrementScale( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xscale;
|
||||
|
||||
if( spinCtrl == m_spinYscale )
|
||||
textCtrl = yscale;
|
||||
else if( spinCtrl == m_spinZscale )
|
||||
textCtrl = zscale;
|
||||
|
||||
incrementTextCtrl( textCtrl, -SCALE_INCREMENT, 1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onIncrementOffset( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xoff;
|
||||
|
||||
if( spinCtrl == m_spinYoffset )
|
||||
textCtrl = yoff;
|
||||
else if( spinCtrl == m_spinZoffset )
|
||||
textCtrl = zoff;
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( g_UserUnit == INCHES )
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, -MAX_OFFSET, MAX_OFFSET );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onDecrementOffset( wxSpinEvent& event )
|
||||
{
|
||||
wxSpinButton* spinCtrl = (wxSpinButton*) event.GetEventObject();
|
||||
|
||||
wxTextCtrl * textCtrl = xoff;
|
||||
|
||||
if( spinCtrl == m_spinYoffset )
|
||||
textCtrl = yoff;
|
||||
else if( spinCtrl == m_spinZoffset )
|
||||
textCtrl = zoff;
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( g_UserUnit == INCHES )
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
|
||||
incrementTextCtrl( textCtrl, -step, -MAX_OFFSET, MAX_OFFSET );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelScale( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = SCALE_INCREMENT;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = SCALE_INCREMENT_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, 1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelRot( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
wxKeyboardState kbdState;
|
||||
|
||||
double step = ROTATION_INCREMENT_WHEEL;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = ROTATION_INCREMENT_WHEEL_FINE;
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, -MAX_ROTATION, MAX_ROTATION );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::onMouseWheelOffset( wxMouseEvent& event )
|
||||
{
|
||||
wxTextCtrl* textCtrl = (wxTextCtrl*) event.GetEventObject();
|
||||
|
||||
double step = OFFSET_INCREMENT_MM;
|
||||
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MM_FINE;
|
||||
|
||||
if( g_UserUnit == INCHES )
|
||||
{
|
||||
step = OFFSET_INCREMENT_MIL/1000.0;
|
||||
if( event.ShiftDown( ) )
|
||||
step = OFFSET_INCREMENT_MIL_FINE/1000.0;
|
||||
}
|
||||
|
||||
if( event.GetWheelRotation() >= 0 )
|
||||
step = -step;
|
||||
|
||||
incrementTextCtrl( textCtrl, step, -MAX_OFFSET, MAX_OFFSET );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::getOrientationVars( SGPOINT& aScale, SGPOINT& aRotation, SGPOINT& aOffset )
|
||||
{
|
||||
if( NULL == xscale || NULL == yscale || NULL == zscale
|
||||
|| NULL == xrot || NULL == yrot || NULL == zrot
|
||||
|| NULL == xoff || NULL == yoff || NULL == zoff )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
xscale->GetValue().ToDouble( &aScale.x );
|
||||
yscale->GetValue().ToDouble( &aScale.y );
|
||||
zscale->GetValue().ToDouble( &aScale.z );
|
||||
|
||||
xrot->GetValue().ToDouble( &aRotation.x );
|
||||
yrot->GetValue().ToDouble( &aRotation.y );
|
||||
zrot->GetValue().ToDouble( &aRotation.z );
|
||||
|
||||
checkRotation( aRotation.x );
|
||||
checkRotation( aRotation.y );
|
||||
checkRotation( aRotation.z );
|
||||
|
||||
xoff->GetValue().ToDouble( &aOffset.x );
|
||||
yoff->GetValue().ToDouble( &aOffset.y );
|
||||
zoff->GetValue().ToDouble( &aOffset.z );
|
||||
|
||||
// Convert from user units to internal units (mm)
|
||||
|
||||
double scaler = 1.0f;
|
||||
|
||||
switch( g_UserUnit )
|
||||
{
|
||||
case MILLIMETRES:
|
||||
scaler = 1.0f;
|
||||
break;
|
||||
case INCHES:
|
||||
scaler = 25.4f;
|
||||
break;
|
||||
default:
|
||||
wxASSERT( 0 );
|
||||
}
|
||||
|
||||
aOffset.x *= scaler;
|
||||
aOffset.y *= scaler;
|
||||
aOffset.z *= scaler;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_PREV_3D::ValidateWithMessage( wxString& aErrorMessage )
|
||||
{
|
||||
bool invalidScale = false;
|
||||
|
||||
for( unsigned int idx = 0; idx < m_parentInfoList->size(); ++idx )
|
||||
{
|
||||
wxString msg;
|
||||
bool addError = false;
|
||||
MODULE_3D_SETTINGS& s3dshape = (*m_parentInfoList)[idx];
|
||||
|
||||
SGPOINT scale;
|
||||
scale.x = s3dshape.m_Scale.x;
|
||||
scale.y = s3dshape.m_Scale.y;
|
||||
scale.z = s3dshape.m_Scale.z;
|
||||
|
||||
if( 1/MAX_SCALE > scale.x || MAX_SCALE < scale.x )
|
||||
{
|
||||
invalidScale = true;
|
||||
addError = true;
|
||||
msg += _( "Invalid X scale" );
|
||||
}
|
||||
|
||||
if( 1/MAX_SCALE > scale.y || MAX_SCALE < scale.y )
|
||||
{
|
||||
invalidScale = true;
|
||||
addError = true;
|
||||
|
||||
if( !msg.IsEmpty() )
|
||||
msg += "\n";
|
||||
|
||||
msg += _( "Invalid Y scale" );
|
||||
}
|
||||
|
||||
if( 1/MAX_SCALE > scale.z || MAX_SCALE < scale.z )
|
||||
{
|
||||
invalidScale = true;
|
||||
addError = true;
|
||||
|
||||
if( !msg.IsEmpty() )
|
||||
msg += "\n";
|
||||
|
||||
msg += _( "Invalid Z scale" );
|
||||
}
|
||||
|
||||
if( addError )
|
||||
{
|
||||
msg.Prepend( s3dshape.m_Filename + "\n" );
|
||||
|
||||
if( !aErrorMessage.IsEmpty() )
|
||||
aErrorMessage += "\n\n";
|
||||
|
||||
aErrorMessage += msg;
|
||||
}
|
||||
}
|
||||
|
||||
if( !aErrorMessage.IsEmpty() )
|
||||
{
|
||||
aErrorMessage += "\n\n";
|
||||
aErrorMessage += wxString::Format( "Min value = %.4f and max value = %.4f",
|
||||
1/MAX_SCALE, MAX_SCALE );
|
||||
}
|
||||
|
||||
return invalidScale == false;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_PREV_3D::updateListOnModelCopy()
|
||||
{
|
||||
auto draw3D = &m_copyModule->Models();
|
||||
draw3D->clear();
|
||||
draw3D->insert( draw3D->end(), m_parentInfoList->begin(), m_parentInfoList->end() );
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright (C) 2015-2016 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file panel_prev_model.h
|
||||
* @brief Defines a panel which is to be added to a wxFileDialog via
|
||||
* SetExtraControl();
|
||||
* The panel shows a preview of the module being edited and provides controls
|
||||
* to set the offset/rotation/scale of each model 3d shape as per KiCad's
|
||||
* current behavior. The panel may also be used in the 3D configuration dialog
|
||||
* to tune the positioning of the models without invoking a file selector dialog.
|
||||
*/
|
||||
|
||||
#ifndef PANEL_PREV_MODEL_H
|
||||
#define PANEL_PREV_MODEL_H
|
||||
|
||||
#include "panel_prev_3d_base.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <3d_canvas/eda_3d_canvas.h>
|
||||
|
||||
// Define min and max parameter values
|
||||
#define MAX_SCALE 10000.0
|
||||
#define MAX_ROTATION 180.0
|
||||
#define MAX_OFFSET 1000.0
|
||||
|
||||
#define SCALE_INCREMENT_FINE 0.02
|
||||
#define SCALE_INCREMENT 0.1
|
||||
|
||||
#define ROTATION_INCREMENT 5 // in degrees, for spin button command
|
||||
#define ROTATION_INCREMENT_WHEEL 15 // in degrees, for mouse wheel command
|
||||
#define ROTATION_INCREMENT_WHEEL_FINE 1 // in degrees, for mouse wheel command
|
||||
|
||||
#define OFFSET_INCREMENT_MM 0.5
|
||||
#define OFFSET_INCREMENT_MM_FINE 0.1
|
||||
|
||||
#define OFFSET_INCREMENT_MIL 25.0
|
||||
#define OFFSET_INCREMENT_MIL_FINE 5.0
|
||||
|
||||
|
||||
// Declared classes to create pointers
|
||||
class S3D_CACHE;
|
||||
class S3D_FILENAME_RESOLVER;
|
||||
class BOARD;
|
||||
class CINFO3D_VISU;
|
||||
class MODULE;
|
||||
class COLORS_DESIGN_SETTINGS;
|
||||
|
||||
class PANEL_PREV_3D: public PANEL_PREV_3D_BASE
|
||||
{
|
||||
public:
|
||||
PANEL_PREV_3D( wxWindow* aParent, S3D_CACHE* aCacheManager,
|
||||
MODULE* aModuleCopy,
|
||||
COLORS_DESIGN_SETTINGS *aColors,
|
||||
std::vector<MODULE_3D_SETTINGS> *aParentInfoList = NULL );
|
||||
|
||||
~PANEL_PREV_3D();
|
||||
|
||||
private:
|
||||
wxString currentModelFile; ///< Used to check if the model file was changed
|
||||
S3D_FILENAME_RESOLVER *m_resolver; ///< Used to get the full path name
|
||||
|
||||
/// The 3D canvas
|
||||
EDA_3D_CANVAS *m_previewPane;
|
||||
|
||||
/// A dummy board used to store the copy moduled
|
||||
BOARD *m_dummyBoard;
|
||||
|
||||
/// The settings that will be used for this 3D viewer canvas
|
||||
CINFO3D_VISU *m_settings3Dviewer;
|
||||
|
||||
/// A pointer to a new copy of the original module
|
||||
MODULE *m_copyModule;
|
||||
|
||||
/// A pointer to the parent MODULE_3D_SETTINGS list that we will use to copy to the preview module
|
||||
std::vector<MODULE_3D_SETTINGS> *m_parentInfoList;
|
||||
|
||||
/// The current selected index of the MODULE_3D_SETTINGS list
|
||||
int m_currentSelectedIdx;
|
||||
|
||||
/// Current MODULE_3D_SETTINGS that is being edited
|
||||
MODULE_3D_SETTINGS m_modelInfo;
|
||||
|
||||
// Methods of the class
|
||||
private:
|
||||
void initPanel();
|
||||
|
||||
/**
|
||||
* @brief updateOrientation - it will receive the events from editing the fields
|
||||
* @param event
|
||||
*/
|
||||
void updateOrientation( wxCommandEvent &event ) override;
|
||||
|
||||
void onMouseWheelScale( wxMouseEvent& event ) override;
|
||||
void onMouseWheelRot( wxMouseEvent& event ) override;
|
||||
void onMouseWheelOffset( wxMouseEvent& event ) override;
|
||||
|
||||
void onIncrementRot( wxSpinEvent& event ) override;
|
||||
void onDecrementRot( wxSpinEvent& event ) override;
|
||||
void onIncrementScale( wxSpinEvent& event ) override;
|
||||
void onDecrementScale( wxSpinEvent& event ) override;
|
||||
void onIncrementOffset( wxSpinEvent& event ) override;
|
||||
void onDecrementOffset( wxSpinEvent& event ) override;
|
||||
|
||||
/**
|
||||
* @brief getOrientationVars - gets the transformation from entries and validate it
|
||||
* @param aScale: output scale var
|
||||
* @param aRotation: output rotation var
|
||||
* @param aOffset: output offset var
|
||||
*/
|
||||
void getOrientationVars( SGPOINT& aScale, SGPOINT& aRotation, SGPOINT& aOffset );
|
||||
|
||||
/**
|
||||
* @brief updateListOnModelCopy - copy the current shape list to the copy of module that is on
|
||||
* the preview dummy board
|
||||
*/
|
||||
void updateListOnModelCopy();
|
||||
|
||||
|
||||
void onEnterPreviewCanvas( wxMouseEvent& event )
|
||||
{
|
||||
m_previewPane->SetFocus();
|
||||
}
|
||||
|
||||
void View3DISO( wxCommandEvent& event ) override
|
||||
{
|
||||
m_settings3Dviewer->CameraGet().ToggleProjection();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DLeft( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'X' );
|
||||
}
|
||||
|
||||
void View3DFront( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Y' );
|
||||
}
|
||||
|
||||
void View3DTop( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'Z' );
|
||||
}
|
||||
|
||||
void View3DUpdate( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->ReloadRequest();
|
||||
m_previewPane->Refresh();
|
||||
}
|
||||
|
||||
void View3DRight( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( 'X' );
|
||||
}
|
||||
|
||||
void View3DBack( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Y' );
|
||||
}
|
||||
|
||||
void View3DBottom( wxCommandEvent& event ) override
|
||||
{
|
||||
m_previewPane->SetView3D( GR_KB_SHIFT + 'Z' );
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief SetModelDataIdx - This will set the index of the INFO list that was set on the parent.
|
||||
* So we will update our values to edit based on the index on that list.
|
||||
* @param idx - The index that was selected
|
||||
* @param aReloadPreviewModule: if need to update the preview module
|
||||
*/
|
||||
void SetModelDataIdx( int idx, bool aReloadPreviewModule = false );
|
||||
|
||||
/**
|
||||
* @brief ResetModelData - Clear the values and reload the preview board
|
||||
* @param aReloadPreviewModule: if need to update the preview module
|
||||
*/
|
||||
void ResetModelData( bool aReloadPreviewModule = false );
|
||||
|
||||
void UpdateModelName( wxString const& aModel );
|
||||
|
||||
/**
|
||||
* @brief verify X,Y and Z scale factors are acceptable (> 0.001 and < 1000.0)
|
||||
* @return false if one (or more) value is not acceptable.
|
||||
* @param aErrorMessage is a wxString to store error messages, if any
|
||||
*/
|
||||
bool ValidateWithMessage( wxString& aErrorMessage );
|
||||
|
||||
bool Validate() override
|
||||
{
|
||||
wxString temp;
|
||||
return ValidateWithMessage(temp);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PANEL_PREV_MODEL_H
|
||||
@@ -44,7 +44,7 @@ if( APPLE )
|
||||
endif()
|
||||
|
||||
find_file( S3DSG_VERSION_FILE sg_version.h
|
||||
PATHS ${CMAKE_SOURCE_DIR}/include/plugins/3dapi NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
|
||||
PATHS ${CMAKE_SOURCE_DIR}/include/plugins/3dapi NO_DEFAULT_PATH )
|
||||
|
||||
if( NOT ${S3DSG_VERSION_FILE} STREQUAL "S3DSG_VERSION_FILE-NOTFOUND" )
|
||||
|
||||
@@ -91,21 +91,12 @@ endif()
|
||||
unset( S3DSG_VERSION_FILE CACHE )
|
||||
|
||||
# Define a flag to expose the appropriate EXPORT macro at build time
|
||||
target_compile_definitions( kicad_3dsg PRIVATE COMPILE_SGLIB )
|
||||
target_compile_definitions( kicad_3dsg PRIVATE -DCOMPILE_SGLIB )
|
||||
|
||||
target_link_libraries( kicad_3dsg ${wxWidgets_LIBRARIES} )
|
||||
|
||||
# Don't specify the ARCHIVE DESTINATION parameter to prevent
|
||||
# the install of the import library on Windows
|
||||
# https://cmake.org/pipermail/cmake/2011-November/047746.html
|
||||
install( TARGETS
|
||||
kicad_3dsg
|
||||
RUNTIME DESTINATION ${KICAD_LIB}
|
||||
LIBRARY DESTINATION ${KICAD_LIB}
|
||||
DESTINATION ${KICAD_LIB}
|
||||
COMPONENT binary
|
||||
)
|
||||
|
||||
if( KICAD_WIN32_INSTALL_PDBS )
|
||||
# Get the PDBs to copy over for MSVC
|
||||
install(FILES $<TARGET_PDB_FILE:kicad_3dsg> DESTINATION ${KICAD_BIN})
|
||||
endif()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -25,7 +24,6 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/log.h>
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
@@ -38,6 +36,10 @@
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
static char BadNode[] = " * [BUG] NULL pointer passed for aNode\n";
|
||||
#endif
|
||||
|
||||
// version format of the cache file
|
||||
#define SG_VERSION_TAG "VERSION:2"
|
||||
|
||||
@@ -71,13 +73,15 @@ static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
|
||||
|
||||
mat.m_Shininess = app->shininess;
|
||||
mat.m_Transparency = app->transparency;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
bool reuse, bool renameNodes )
|
||||
bool reuse, bool renameNodes )
|
||||
{
|
||||
if( nullptr == filename || filename[0] == 0 )
|
||||
if( NULL == filename || filename[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( filename );
|
||||
@@ -92,19 +96,46 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( aTopNode && aTopNode->GetNodeType() == S3D::SGTYPE_TRANSFORM, false );
|
||||
if( NULL == aTopNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aTopNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != aTopNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] aTopNode is not a SCENEGRAPH object";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OPEN_OSTREAM( op, filename );
|
||||
|
||||
if( op.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, filename );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
op.imbue( std::locale::classic() );
|
||||
op.imbue( std::locale( "C" ) );
|
||||
op << "#VRML V2.0 utf8\n";
|
||||
|
||||
if( renameNodes )
|
||||
@@ -123,8 +154,10 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
|
||||
CLOSE_STREAM( op );
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] problems encountered writing file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, filename );
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "problems encountered writing file" << " '" << filename << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -132,44 +165,102 @@ bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
|
||||
|
||||
void S3D::ResetNodeIndex( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ResetNodeIndex();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::RenameNodes( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aNode->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::DestroyNode( SGNODE* aNode ) noexcept
|
||||
void S3D::DestroyNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, /* void */ );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
delete aNode;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
const char* aPluginInfo )
|
||||
const char* aPluginInfo )
|
||||
{
|
||||
if( nullptr == aFileName || aFileName[0] == 0 )
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return false;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadNode;
|
||||
wxLogTrace( MASK_3D_SG, "%s", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( wxFileName::Exists( ofile ) )
|
||||
{
|
||||
if( !overwrite )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] file exists not overwriting '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "file exists; not overwriting" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -177,9 +268,11 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
// make sure we make no attempt to write a directory
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] specified path is a directory '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "specified path is a directory" << " '";
|
||||
errmsg << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -188,27 +281,34 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
|
||||
if( output.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
wxString errmsg;
|
||||
errmsg << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
errmsg << " * [INFO] " << "failed to open file" << " '" << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, errmsg );
|
||||
return false;
|
||||
}
|
||||
|
||||
output << "(" << SG_VERSION_TAG << ")";
|
||||
|
||||
if( nullptr != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
if( NULL != aPluginInfo && aPluginInfo[0] != 0 )
|
||||
output << "(" << aPluginInfo << ")";
|
||||
else
|
||||
output << "(INTERNAL:0.0.0.0)";
|
||||
|
||||
bool rval = aNode->WriteCache( output, nullptr );
|
||||
bool rval = aNode->WriteCache( output, NULL );
|
||||
CLOSE_STREAM( output );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] problems encountered writing cache file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] problems encountered writing cache file '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
// delete the defective file
|
||||
wxRemoveFile( ofile );
|
||||
@@ -219,31 +319,53 @@ bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
|
||||
|
||||
|
||||
SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
bool (*aTagCheck)( const char*, void* ) )
|
||||
{
|
||||
if( nullptr == aFileName || aFileName[0] == 0 )
|
||||
return nullptr;
|
||||
if( NULL == aFileName || aFileName[0] == 0 )
|
||||
return NULL;
|
||||
|
||||
wxString ofile = wxString::FromUTF8Unchecked( aFileName );
|
||||
|
||||
if( !wxFileName::FileExists( aFileName ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] no such file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "no such file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::unique_ptr<SGNODE> np = std::make_unique<SCENEGRAPH>( nullptr );
|
||||
SGNODE* np = new SCENEGRAPH( NULL );
|
||||
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] failed to instantiate SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPEN_ISTREAM( file, aFileName );
|
||||
|
||||
if( file.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] failed to open file '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aFileName );
|
||||
|
||||
return nullptr;
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = _( "failed to open file" );
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// from SG_VERSION_TAG 1, read the version tag; if it's not the expected tag
|
||||
@@ -256,13 +378,18 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left parenthesis"
|
||||
" at position '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( file.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
@@ -276,7 +403,7 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
if( name.compare( SG_VERSION_TAG ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
@@ -291,13 +418,18 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
|
||||
if( '(' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left parenthesis"
|
||||
" at position '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( file.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left parenthesis at position ";
|
||||
ostr << file.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.get( schar );
|
||||
@@ -309,39 +441,40 @@ SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
|
||||
}
|
||||
|
||||
// check the plugin tag
|
||||
if( nullptr != aTagCheck && nullptr != aPluginMgr
|
||||
&& !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
if( NULL != aTagCheck && NULL != aPluginMgr && !aTagCheck( name.c_str(), aPluginMgr ) )
|
||||
{
|
||||
CLOSE_STREAM( file );
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
|
||||
bool rval = np->ReadCache( file, nullptr );
|
||||
bool rval = np->ReadCache( file, NULL );
|
||||
CLOSE_STREAM( file );
|
||||
|
||||
if( !rval )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] problems encountered reading cache file "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aFileName );
|
||||
|
||||
return nullptr;
|
||||
delete np;
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
wxString errmsg = "problems encountered reading cache file";
|
||||
ostr << " * [INFO] " << errmsg.ToUTF8() << " '";
|
||||
ostr << aFileName << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return np.release();
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
return nullptr;
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
if( aNode->GetNodeType() != S3D::SGTYPE_TRANSFORM )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
S3D::MATLIST materials;
|
||||
std::vector< SMESH > meshes;
|
||||
@@ -351,20 +484,20 @@ S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
// gray in hopes that it may help highlight faulty models; this color is
|
||||
// also typical of MCAD applications. When a model has no associated
|
||||
// material color it shall be assigned the index 0.
|
||||
SGAPPEARANCE app( nullptr );
|
||||
app.ambient = SGCOLOR( 0.6f, 0.6f, 0.6f );
|
||||
app.diffuse = SGCOLOR( 0.6f, 0.6f, 0.6f );
|
||||
SGAPPEARANCE app( NULL );
|
||||
app.ambient = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.diffuse = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||
app.specular = app.diffuse;
|
||||
app.shininess = 0.05f;
|
||||
app.transparency = 0.0f;
|
||||
app.shininess = 0.05;
|
||||
app.transparency = 0.0;
|
||||
|
||||
materials.matorder.push_back( &app );
|
||||
materials.matmap.emplace( &app, 0 );
|
||||
materials.matmap.insert( std::pair< SGAPPEARANCE const*, int >( &app, 0 ) );
|
||||
|
||||
if( aNode->Prepare( nullptr, materials, meshes ) )
|
||||
if( aNode->Prepare( NULL, materials, meshes ) )
|
||||
{
|
||||
if( meshes.empty() )
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
S3DMODEL* model = S3D::New3DModel();
|
||||
|
||||
@@ -396,31 +529,35 @@ S3DMODEL* S3D::GetModel( SCENEGRAPH* aNode )
|
||||
for( size_t i = 0; i < j; ++i )
|
||||
S3D::Free3DMesh( meshes[i] );
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Destroy3DModel( S3DMODEL** aModel )
|
||||
{
|
||||
if( nullptr == aModel || nullptr == *aModel )
|
||||
if( NULL == aModel || NULL == *aModel )
|
||||
return;
|
||||
|
||||
S3DMODEL* m = *aModel;
|
||||
S3D::FREE_S3DMODEL( *m );
|
||||
delete m;
|
||||
*aModel = nullptr;
|
||||
*aModel = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Free3DModel( S3DMODEL& aModel )
|
||||
{
|
||||
S3D::FREE_S3DMODEL( aModel );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Free3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::FREE_SMESH( aMesh );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -435,17 +572,20 @@ S3DMODEL* S3D::New3DModel( void )
|
||||
void S3D::Init3DMaterial( SMATERIAL& aMat )
|
||||
{
|
||||
S3D::INIT_SMATERIAL( aMat );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::Init3DMesh( SMESH& aMesh )
|
||||
{
|
||||
S3D::INIT_SMESH( aMesh );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor, unsigned char* Patch,
|
||||
unsigned char* Revision ) noexcept
|
||||
void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor,
|
||||
unsigned char* Patch, unsigned char* Revision )
|
||||
{
|
||||
if( Major )
|
||||
*Major = KICADSG_VERSION_MAJOR;
|
||||
@@ -458,6 +598,8 @@ void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor, unsigned ch
|
||||
|
||||
if( Patch )
|
||||
*Patch = KICADSG_VERSION_PATCH;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -476,7 +618,7 @@ SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT&
|
||||
|
||||
// normal
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
(void)glm::normalize( tri );
|
||||
glm::normalize( tri );
|
||||
|
||||
return SGVECTOR( tri.x, tri.y, tri.z );
|
||||
}
|
||||
@@ -484,7 +626,7 @@ SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT&
|
||||
|
||||
S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return SGTYPE_END;
|
||||
|
||||
return aNode->GetNodeType();
|
||||
@@ -493,8 +635,8 @@ S3D::SGTYPES S3D::GetSGNodeType( SGNODE* aNode )
|
||||
|
||||
SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
return nullptr;
|
||||
if( NULL == aNode )
|
||||
return NULL;
|
||||
|
||||
return aNode->GetParent();
|
||||
}
|
||||
@@ -502,7 +644,7 @@ SGNODE* S3D::GetSGNodeParent( SGNODE* aNode )
|
||||
|
||||
bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( nullptr == aParent || nullptr == aChild )
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddRefNode( aChild );
|
||||
@@ -511,7 +653,7 @@ bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
|
||||
|
||||
bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
{
|
||||
if( nullptr == aParent || nullptr == aChild )
|
||||
if( NULL == aParent || NULL == aChild )
|
||||
return false;
|
||||
|
||||
return aParent->AddChildNode( aChild );
|
||||
@@ -520,8 +662,10 @@ bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
|
||||
|
||||
void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
|
||||
{
|
||||
if( nullptr == aObject || nullptr == aRefPtr || aObject != *aRefPtr )
|
||||
if( NULL == aObject || NULL == aRefPtr || aObject != *aRefPtr )
|
||||
return;
|
||||
|
||||
aObject->AssociateWrapper( aRefPtr );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -30,39 +29,55 @@
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_APPEARANCE::IFSG_APPEARANCE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,28 +85,39 @@ IFSG_APPEARANCE::IFSG_APPEARANCE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGAPPEARANCE( nullptr );
|
||||
m_node = new SGAPPEARANCE( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +126,7 @@ bool IFSG_APPEARANCE::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,13 +152,17 @@ bool IFSG_APPEARANCE::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGAPPEARANCE" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGAPPEARANCE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +176,17 @@ bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -154,131 +194,279 @@ bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetEmissive( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetEmissive( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetEmissive( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetDiffuse( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetSpecular( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetSpecular( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetSpecular( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetAmbient( aRVal, aGVal, aBVal );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRVal, aGVal, aBVal );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetAmbient( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGAPPEARANCE*) m_node )->SetAmbient( aRGBColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGAPPEARANCE*)m_node)->SetAmbient( aRGBColor );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess ) noexcept
|
||||
bool IFSG_APPEARANCE::SetShininess( float aShininess )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aShininess < 0 || aShininess > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] shininess out of range [0..1]" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] shininess out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
( (SGAPPEARANCE*) m_node )->shininess = aShininess;
|
||||
((SGAPPEARANCE*)m_node)->shininess = aShininess;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency ) noexcept
|
||||
bool IFSG_APPEARANCE::SetTransparency( float aTransparency )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( aTransparency < 0 || aTransparency > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] transparency out of range [0..1]" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] transparency out of range [0..1]";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
( (SGAPPEARANCE*) m_node )->transparency = aTransparency;
|
||||
((SGAPPEARANCE*)m_node)->transparency = aTransparency;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -30,38 +29,52 @@
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
return ;
|
||||
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COLORS::IFSG_COLORS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d" ), __FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,29 +82,39 @@ IFSG_COLORS::IFSG_COLORS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Braces needed due to dangling else warning from wxLogTrace macro
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGCOLORS( nullptr );
|
||||
m_node = new SGCOLORS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +123,7 @@ bool IFSG_COLORS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,12 +149,17 @@ bool IFSG_COLORS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOLORS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOLORS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,7 +173,17 @@ bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -153,17 +191,37 @@ bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGCOLORS*) m_node )->GetColorList( aListSize, aColorList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOLORS*)m_node)->GetColorList( aListSize, aColorList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOLORS*) m_node )->SetColorList( aListSize, aColorList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->SetColorList( aListSize, aColorList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -171,9 +229,19 @@ bool IFSG_COLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
|
||||
bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOLORS*) m_node )->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -181,9 +249,19 @@ bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueVa
|
||||
|
||||
bool IFSG_COLORS::AddColor( const SGCOLOR& aColor )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOLORS*) m_node )->AddColor( aColor );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOLORS*)m_node)->AddColor( aColor );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,39 +30,50 @@
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDINDEX::IFSG_COORDINDEX( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,25 +83,35 @@ IFSG_COORDINDEX::IFSG_COORDINDEX( IFSG_NODE& aParent )
|
||||
|
||||
if( !pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_node = new SGCOORDINDEX( nullptr );
|
||||
m_node = new SGCOORDINDEX( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +120,7 @@ bool IFSG_COORDINDEX::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,13 +146,17 @@ bool IFSG_COORDINDEX::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOORDINDEX" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDINDEX";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +170,17 @@ bool IFSG_COORDINDEX::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -30,39 +29,52 @@
|
||||
#include "3d_cache/sg/sg_coords.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_COORDS::IFSG_COORDS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,28 +82,39 @@ IFSG_COORDS::IFSG_COORDS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGCOORDS( nullptr );
|
||||
m_node = new SGCOORDS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +123,7 @@ bool IFSG_COORDS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -126,12 +149,17 @@ bool IFSG_COORDS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGCOORDS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGCOORDS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,7 +173,17 @@ bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -153,17 +191,37 @@ bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_COORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGCOORDS*) m_node )->GetCoordsList( aListSize, aCoordsList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGCOORDS*)m_node)->GetCoordsList( aListSize, aCoordsList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOORDS*) m_node )->SetCoordsList( aListSize, aCoordsList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->SetCoordsList( aListSize, aCoordsList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -171,9 +229,19 @@ bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
|
||||
bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOORDS*) m_node )->AddCoord( aXValue, aYValue, aZValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aXValue, aYValue, aZValue );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -181,9 +249,19 @@ bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
|
||||
bool IFSG_COORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGCOORDS*) m_node )->AddCoord( aPoint );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGCOORDS*)m_node)->AddCoord( aPoint );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,39 +30,52 @@
|
||||
#include "3d_cache/sg/sg_faceset.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_FACESET::IFSG_FACESET( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +83,39 @@ IFSG_FACESET::IFSG_FACESET( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGFACESET( nullptr );
|
||||
m_node = new SGFACESET( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +124,7 @@ bool IFSG_FACESET::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +150,17 @@ bool IFSG_FACESET::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGFACESET" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGFACESET";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +174,17 @@ bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -155,7 +193,7 @@ bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||
bool IFSG_FACESET::CalcNormals( SGNODE** aPtr )
|
||||
{
|
||||
if( m_node )
|
||||
return ( (SGFACESET*) m_node )->CalcNormals( aPtr );
|
||||
return ((SGFACESET*)m_node)->CalcNormals( aPtr );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,24 +30,51 @@
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_INDEX::IFSG_INDEX() : IFSG_NODE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGINDEX*) m_node )->GetIndices( nIndices, aIndexList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGINDEX*)m_node)->GetIndices( nIndices, aIndexList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGINDEX*) m_node )->SetIndices( nIndices, aIndexList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->SetIndices( nIndices, aIndexList );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -56,9 +82,19 @@ bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
|
||||
bool IFSG_INDEX::AddIndex( int aIndex )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGINDEX*) m_node )->AddIndex( aIndex );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGINDEX*)m_node)->AddIndex( aIndex );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,17 +30,15 @@
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/ifsg_api.h"
|
||||
|
||||
|
||||
// collection of common error strings used by the wrappers
|
||||
char BadObject[] = " * [BUG] operating on an invalid wrapper (object may have been deleted)";
|
||||
char BadOperand[] = " * [BUG] parameter aNode is an invalid wrapper; its data may have been deleted";
|
||||
char BadParent[] = " * [BUG] invalid parent node (data may have been deleted)";
|
||||
char WrongParent[] = " * [BUG] parent node type is incompatible";
|
||||
|
||||
|
||||
IFSG_NODE::IFSG_NODE()
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +46,8 @@ IFSG_NODE::~IFSG_NODE()
|
||||
{
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +57,13 @@ void IFSG_NODE::Destroy( void )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void ) noexcept
|
||||
SGNODE* IFSG_NODE::GetRawPtr( void )
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
@@ -70,7 +71,17 @@ SGNODE* IFSG_NODE::GetRawPtr( void ) noexcept
|
||||
|
||||
S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
{
|
||||
wxCHECK( m_node, S3D::SGTYPE_END );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
|
||||
return m_node->GetNodeType();
|
||||
}
|
||||
@@ -78,7 +89,17 @@ S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||
|
||||
SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetParent();
|
||||
}
|
||||
@@ -86,7 +107,17 @@ SGNODE* IFSG_NODE::GetParent( void ) const
|
||||
|
||||
bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->SetParent( aParent );
|
||||
}
|
||||
@@ -94,40 +125,90 @@ bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||
|
||||
const char* IFSG_NODE::GetName( void )
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetName();
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::SetName( const char* aName )
|
||||
bool IFSG_NODE::SetName( const char *aName )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_node->SetName( aName );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char* IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
const char * IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->GetNodeTypeName( aNodeType );
|
||||
}
|
||||
|
||||
|
||||
SGNODE* IFSG_NODE::FindNode( const char* aNodeName )
|
||||
SGNODE* IFSG_NODE::FindNode( const char *aNodeName )
|
||||
{
|
||||
wxCHECK( m_node, nullptr );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return m_node->FindNode( aNodeName, nullptr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m_node->FindNode( aNodeName, NULL );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( aNode );
|
||||
}
|
||||
@@ -135,11 +216,31 @@ bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||
|
||||
bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddRefNode( np );
|
||||
}
|
||||
@@ -147,7 +248,17 @@ bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||
|
||||
bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( aNode );
|
||||
}
|
||||
@@ -155,11 +266,31 @@ bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||
|
||||
bool IFSG_NODE::AddChildNode( IFSG_NODE& aNode )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = aNode.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadOperand;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_node->AddChildNode( np );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,39 +30,53 @@
|
||||
#include "3d_cache/sg/sg_normals.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_NORMALS::IFSG_NORMALS( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +84,39 @@ IFSG_NORMALS::IFSG_NORMALS( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGNORMALS( nullptr );
|
||||
m_node = new SGNORMALS( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +125,7 @@ bool IFSG_NORMALS::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +151,17 @@ bool IFSG_NORMALS::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGNORMALS" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGNORMALS";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +175,17 @@ bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -154,34 +193,74 @@ bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_NORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return ( (SGNORMALS*) m_node )->GetNormalList( aListSize, aNormalList );
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((SGNORMALS*)m_node)->GetNormalList( aListSize, aNormalList );
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGNORMALS*) m_node )->SetNormalList( aListSize, aNormalList );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->SetNormalList( aListSize, aNormalList );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGNORMALS*) m_node )->AddNormal( aXValue, aYValue, aZValue );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aXValue, aYValue, aZValue );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_NORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SGNORMALS*) m_node )->AddNormal( aNormal );
|
||||
return false;
|
||||
}
|
||||
|
||||
((SGNORMALS*)m_node)->AddNormal( aNormal );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,39 +30,53 @@
|
||||
#include "3d_cache/sg/sg_shape.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return ;
|
||||
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_SHAPE::IFSG_SHAPE( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,28 +84,39 @@ IFSG_SHAPE::IFSG_SHAPE( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* pp = aParent.GetRawPtr();
|
||||
|
||||
#ifdef DEBUG
|
||||
if( !pp )
|
||||
#ifdef DEBUG
|
||||
if( ! pp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
BadParent );
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_node = new SGSHAPE( nullptr );
|
||||
m_node = new SGSHAPE( NULL );
|
||||
|
||||
if( !m_node->SetParent( pp ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( pp ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +125,7 @@ bool IFSG_SHAPE::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -127,12 +151,17 @@ bool IFSG_SHAPE::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SGSHAPE" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SGSHAPE";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +175,17 @@ bool IFSG_SHAPE::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,38 +30,52 @@
|
||||
#include "3d_cache/sg/scenegraph.h"
|
||||
|
||||
|
||||
extern char BadObject[];
|
||||
extern char BadOperand[];
|
||||
extern char BadParent[];
|
||||
extern char WrongParent[];
|
||||
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( bool create )
|
||||
{
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !create )
|
||||
return;
|
||||
|
||||
m_node = new SCENEGRAPH( nullptr );
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
if( m_node )
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IFSG_TRANSFORM::IFSG_TRANSFORM( SGNODE* aParent )
|
||||
{
|
||||
m_node = new SCENEGRAPH( nullptr );
|
||||
m_node = new SCENEGRAPH( NULL );
|
||||
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
if( m_node )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
if( !m_node->SetParent( aParent ) )
|
||||
{
|
||||
delete m_node;
|
||||
m_node = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d %s" ), __FILE__, __FUNCTION__, __LINE__,
|
||||
WrongParent );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << WrongParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
}
|
||||
|
||||
m_node->AssociateWrapper( &m_node );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +84,7 @@ bool IFSG_TRANSFORM::Attach( SGNODE* aNode )
|
||||
if( m_node )
|
||||
m_node->DisassociateWrapper( &m_node );
|
||||
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
|
||||
if( !aNode )
|
||||
return false;
|
||||
@@ -97,12 +110,17 @@ bool IFSG_TRANSFORM::NewNode( SGNODE* aParent )
|
||||
|
||||
if( aParent != m_node->GetParent() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid SGNODE parent (%s) to SCENEGRAPH" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeTypeName( aParent->GetNodeType() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid SGNODE parent (";
|
||||
ostr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||
ostr << ") to SCENEGRAPH";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
delete m_node;
|
||||
m_node = nullptr;
|
||||
m_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -116,7 +134,17 @@ bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
{
|
||||
SGNODE* np = aParent.GetRawPtr();
|
||||
|
||||
wxCHECK( np, false );
|
||||
if( NULL == np )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadParent;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return NewNode( np );
|
||||
}
|
||||
@@ -124,20 +152,40 @@ bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||
|
||||
bool IFSG_TRANSFORM::SetRotation( const SGVECTOR& aRotationAxis, double aAngle )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->rotation_axis = aRotationAxis;
|
||||
( (SCENEGRAPH*) m_node )->rotation_angle = aAngle;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->rotation_axis = aRotationAxis;
|
||||
((SCENEGRAPH*)m_node)->rotation_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale ) noexcept
|
||||
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale = aScale;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = aScale;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -145,27 +193,51 @@ bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale ) noexcept
|
||||
|
||||
bool IFSG_TRANSFORM::SetScale( double aScale )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
|
||||
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||
if( NULL == m_node )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] |scale| is < 1e-8 - this seems strange" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale = SGPOINT( aScale, aScale, aScale );
|
||||
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] |scale| is < 1e-8 - this seems strange";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale = SGPOINT( aScale, aScale, aScale );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation ) noexcept
|
||||
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->translation = aTranslation;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->translation = aTranslation;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -173,20 +245,40 @@ bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation ) noexcept
|
||||
|
||||
bool IFSG_TRANSFORM::SetScaleOrientation( const SGVECTOR& aScaleAxis, double aAngle )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->scale_axis = aScaleAxis;
|
||||
( (SCENEGRAPH*) m_node )->scale_angle = aAngle;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->scale_axis = aScaleAxis;
|
||||
((SCENEGRAPH*)m_node)->scale_angle = aAngle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter ) noexcept
|
||||
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter )
|
||||
{
|
||||
wxCHECK( m_node, false );
|
||||
if( NULL == m_node )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << BadObject;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
( (SCENEGRAPH*) m_node )->center = aCenter;
|
||||
return false;
|
||||
}
|
||||
|
||||
((SCENEGRAPH*)m_node)->center = aCenter;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -45,19 +44,24 @@ SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
|
||||
scale.y = 1.0;
|
||||
scale.z = 1.0;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SCENEGRAPH (type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SCENEGRAPH (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,12 +74,14 @@ SCENEGRAPH::~SCENEGRAPH()
|
||||
// delete owned objects
|
||||
DEL_OBJS( SCENEGRAPH, m_Transforms );
|
||||
DEL_OBJS( SGSHAPE, m_Shape );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -84,14 +90,14 @@ bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a transform may be parent to a transform
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -105,8 +111,8 @@ bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||
|
||||
SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
@@ -115,8 +121,8 @@ SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -124,26 +130,33 @@ SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
|
||||
void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
switch( aNode->GetNodeType() )
|
||||
{
|
||||
case S3D::SGTYPE_TRANSFORM:
|
||||
UNLINK_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms,
|
||||
isChild );
|
||||
break;
|
||||
case S3D::SGTYPE_TRANSFORM:
|
||||
UNLINK_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
break;
|
||||
|
||||
case S3D::SGTYPE_SHAPE:
|
||||
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
break;
|
||||
case S3D::SGTYPE_SHAPE:
|
||||
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,16 +176,30 @@ void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
|
||||
|
||||
bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ADD_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||
ADD_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] object '%s' is not a valid type for this object (%d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aNode->GetName(),
|
||||
aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -210,7 +237,7 @@ void SCENEGRAPH::ReNameNodes( void )
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
// rename all transforms
|
||||
do
|
||||
@@ -224,13 +251,16 @@ void SCENEGRAPH::ReNameNodes( void )
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty() )
|
||||
if( m_Transforms.empty() && m_RTransforms.empty()
|
||||
&& m_Shape.empty() && m_RShape.empty() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -336,14 +366,14 @@ bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode && nullptr != m_Parent )
|
||||
if( NULL == parentNode && NULL != m_Parent )
|
||||
{
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -352,9 +382,19 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
if( nullptr == m_Parent )
|
||||
return false;
|
||||
}
|
||||
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
// ensure unique node names
|
||||
ResetNodeIndex();
|
||||
@@ -363,8 +403,12 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( aFile.fail() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -420,9 +464,12 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( !m_Transforms[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] bad stream while writing child transforms" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child transforms";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -430,20 +477,21 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RTransforms.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RTransforms[i]->GetName() << "]";
|
||||
|
||||
// write child shapes
|
||||
asize = m_Shape.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
{
|
||||
if( !m_Shape[i]->WriteCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [INFO] bad stream while writing child shapes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream while writing child shapes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -451,7 +499,6 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
// write referenced transform names
|
||||
asize = m_RShape.size();
|
||||
|
||||
for( i = 0; i < asize; ++i )
|
||||
aFile << "[" << m_RShape[i]->GetName() << "]";
|
||||
|
||||
@@ -465,20 +512,33 @@ bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty(),
|
||||
false );
|
||||
if( !m_Transforms.empty() || !m_RTransforms.empty()
|
||||
|| !m_Shape.empty() || !m_RShape.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name; // name of the node
|
||||
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
// we need to read the tag and verify its type
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; tag mismatch at position "
|
||||
"%ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; tag mismatch at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -512,10 +572,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child transform tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -525,10 +588,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading transform "
|
||||
"%ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -539,10 +605,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref transform tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref transform tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -551,20 +620,26 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref "
|
||||
"transform at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref transform '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_TRANSFORM != sp->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not TRANSFORM "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not TRANSFORM '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -577,10 +652,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child shape tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -590,10 +668,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; corrupt data while "
|
||||
"reading shape at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -604,10 +685,13 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref shape tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref shape tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -616,20 +700,26 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !sp )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref shape "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref shape '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_SHAPE != sp->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGSHAPE at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGSHAPE '";
|
||||
ostr << name << "' pos " << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -644,27 +734,21 @@ bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
}
|
||||
|
||||
|
||||
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes )
|
||||
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
// calculate the accumulated transform
|
||||
double rX, rY, rZ;
|
||||
|
||||
// rotation
|
||||
rotation_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 rM = glm::rotate( glm::dmat4( 1.0 ), rotation_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
|
||||
// translation
|
||||
glm::dmat4 tM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( translation.x, translation.y,
|
||||
translation.z ) );
|
||||
glm::dmat4 tM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( translation.x, translation.y, translation.z ) );
|
||||
// center
|
||||
glm::dmat4 cM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( center.x, center.y, center.z ) );
|
||||
glm::dmat4 ncM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( -center.x, -center.y,
|
||||
-center.z ) );
|
||||
|
||||
glm::dmat4 ncM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( -center.x, -center.y, -center.z ) );
|
||||
// scale
|
||||
glm::dmat4 sM = glm::scale( glm::dmat4( 1.0 ), glm::dvec3( scale.x, scale.y, scale.z ) );
|
||||
|
||||
// scaleOrientation
|
||||
scale_axis.GetVector( rX, rY, rZ );
|
||||
glm::dmat4 srM = glm::rotate( glm::dmat4( 1.0 ), scale_angle, glm::dvec3( rX, rY, rZ ) );
|
||||
@@ -676,7 +760,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
// tx0 = tM * cM * rM * srM * sM * nsrM * ncM
|
||||
glm::dmat4 tx0;
|
||||
|
||||
if( nullptr != aTransform )
|
||||
if( NULL != aTransform )
|
||||
tx0 = (*aTransform) * tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
else
|
||||
tx0 = tM * cM * rM * srM * sM * nsrM * ncM;
|
||||
@@ -704,7 +788,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
// prepare all transforms
|
||||
do
|
||||
@@ -727,7 +811,7 @@ bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
++sL;
|
||||
}
|
||||
|
||||
} while( 0 );
|
||||
} while(0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,10 @@
|
||||
|
||||
/**
|
||||
* @file scenegraph.h
|
||||
* defines the basic data set required to represent a 3D model;
|
||||
* this model must remain compatible with VRML2.0 in order to
|
||||
* facilitate VRML export of scene graph data created by available
|
||||
* 3D plugins.
|
||||
*/
|
||||
|
||||
|
||||
@@ -35,18 +38,38 @@
|
||||
|
||||
class SGSHAPE;
|
||||
|
||||
/**
|
||||
* Define the basic data set required to represent a 3D model.
|
||||
*
|
||||
* This model must remain compatible with VRML2.0 in order to facilitate VRML export of
|
||||
* scene graph data created by available 3D plugins.
|
||||
*/
|
||||
class SCENEGRAPH : public SGNODE
|
||||
{
|
||||
private:
|
||||
// The following are items which may be defined for reuse
|
||||
// in a VRML output file. They do not necessarily correspond
|
||||
// to the use of DEF within a VRML input file; it is the
|
||||
// responsibility of the plugin to perform any necessary
|
||||
// conversions to comply with the restrictions imposed by
|
||||
// this scene graph structure
|
||||
std::vector< SCENEGRAPH* > m_Transforms; // local Transform nodes
|
||||
std::vector< SGSHAPE* > m_Shape; // local Shape nodes
|
||||
|
||||
std::vector< SCENEGRAPH* > m_RTransforms; // referenced Transform nodes
|
||||
std::vector< SGSHAPE* > m_RShape; // referenced Shape nodes
|
||||
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
// note: order of transformation is Translate, Rotate, Offset
|
||||
SGPOINT center;
|
||||
SGPOINT translation;
|
||||
SGVECTOR rotation_axis;
|
||||
double rotation_angle; // radians
|
||||
SGPOINT scale;
|
||||
SGVECTOR scale_axis;
|
||||
double scale_angle; // radians
|
||||
|
||||
SCENEGRAPH( SGNODE* aParent );
|
||||
virtual ~SCENEGRAPH();
|
||||
|
||||
@@ -61,35 +84,8 @@ public:
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes );
|
||||
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// note: order of transformation is Translate, Rotate, Offset
|
||||
SGPOINT center;
|
||||
SGPOINT translation;
|
||||
SGVECTOR rotation_axis;
|
||||
double rotation_angle; // radians
|
||||
SGPOINT scale;
|
||||
SGVECTOR scale_axis;
|
||||
double scale_angle; // radians
|
||||
|
||||
private:
|
||||
// The following are items which may be defined for reuse
|
||||
// in a VRML output file. They do not necessarily correspond
|
||||
// to the use of DEF within a VRML input file; it is the
|
||||
// responsibility of the plugin to perform any necessary
|
||||
// conversions to comply with the restrictions imposed by
|
||||
// this scene graph structure
|
||||
std::vector< SCENEGRAPH* > m_Transforms; // local Transform nodes
|
||||
std::vector< SGSHAPE* > m_Shape; // local Shape nodes
|
||||
|
||||
std::vector< SCENEGRAPH* > m_RTransforms; // referenced Transform nodes
|
||||
std::vector< SGSHAPE* > m_RShape; // referenced Shape nodes
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -30,40 +29,46 @@
|
||||
#include "3d_cache/sg/sg_appearance.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent)
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_APPEARANCE;
|
||||
|
||||
// defaults in accord with VRML2.0 spec
|
||||
ambient.SetColor( 0.05317f, 0.17879f, 0.01804f );
|
||||
shininess = 0.2f;
|
||||
transparency = 0.0f;
|
||||
diffuse.SetColor( 0.8f, 0.8f, 0.8f );
|
||||
ambient.SetColor( 0.05317, 0.17879, 0.01804 );
|
||||
shininess = 0.2;
|
||||
transparency = 0.0;
|
||||
diffuse.SetColor( 0.8, 0.8, 0.8 );
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGAPPEARANCE (type %s )" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGAPPEARANCE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGAPPEARANCE::~SGAPPEARANCE()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -72,14 +77,14 @@ bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGAPPEARANCE
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -99,7 +104,17 @@ bool SGAPPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return emissive.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -119,7 +134,17 @@ bool SGAPPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return diffuse.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -139,7 +164,17 @@ bool SGAPPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return specular.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -158,7 +193,17 @@ bool SGAPPEARANCE::SetAmbient( float aRVal, float aGVal, float aBVal )
|
||||
|
||||
bool SGAPPEARANCE::SetAmbient( const SGCOLOR* aRGBColor )
|
||||
{
|
||||
wxCHECK_MSG( aRGBColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aRGBColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aRGBColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return ambient.SetColor( aRGBColor );
|
||||
}
|
||||
@@ -170,46 +215,66 @@ bool SGAPPEARANCE::SetAmbient( const SGCOLOR& aRGBColor )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGAPPEARANCE::FindNode( const char* aNodeName, const SGNODE* aCaller) noexcept
|
||||
SGNODE* SGAPPEARANCE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK_MSG( aCaller, /* void */,
|
||||
wxT( "unexpected code branch; node should have no children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK_MSG( aCaller, /* void */,
|
||||
wxT( "unexpected code branch; node should have no children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
// This is redundant but it keeps gcc from generating a warning on debug builds.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK_MSG( aNode, false, wxT( "this node does not accept children or refs" ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
// This is redundant but it keeps gcc from generating a warning on debug builds.
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -253,13 +318,13 @@ bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
diffuse.GetColor( ambr, ambg, ambb );
|
||||
float den = ( 0.212671 * ambr + 0.71516 * ambg + 0.072169 * ambb );
|
||||
|
||||
if( den < 0.004f )
|
||||
den = 0.004f;
|
||||
if( den < 0.004 )
|
||||
den = 0.004;
|
||||
|
||||
amb /= den;
|
||||
|
||||
if( amb > 1.0f )
|
||||
amb = 1.0f;
|
||||
if( amb > 1.0 )
|
||||
amb = 1.0;
|
||||
|
||||
S3D::FormatFloat( tmp, amb );
|
||||
aFile << " ambientIntensity " << tmp << "\n";
|
||||
@@ -303,16 +368,26 @@ bool SGAPPEARANCE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK_MSG( m_Parent, false, wxT( "corrupt data; m_aParent is NULL" ) );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -321,20 +396,34 @@ bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK_MSG( parentNode == m_Parent, false, wxT( "corrupt data; parentNode != m_aParent" ) );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
S3D::WriteColor( aFile, ambient );
|
||||
aFile.write( (char*) &shininess, sizeof( shininess ) );
|
||||
aFile.write( (char*) &transparency, sizeof( transparency ) );
|
||||
aFile.write( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.write( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::WriteColor( aFile, diffuse );
|
||||
S3D::WriteColor( aFile, emissive );
|
||||
S3D::WriteColor( aFile, specular );
|
||||
@@ -350,8 +439,8 @@ bool SGAPPEARANCE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
bool SGAPPEARANCE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
S3D::ReadColor( aFile, ambient );
|
||||
aFile.read( (char*) &shininess, sizeof( shininess ) );
|
||||
aFile.read( (char*) &transparency, sizeof( transparency ) );
|
||||
aFile.read( (char*)&shininess, sizeof(shininess) );
|
||||
aFile.read( (char*)&transparency, sizeof(transparency) );
|
||||
S3D::ReadColor( aFile, diffuse );
|
||||
S3D::ReadColor( aFile, emissive );
|
||||
S3D::ReadColor( aFile, specular );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_appearance.h
|
||||
* defines the generic material appearance of a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_APPEARANCE_H
|
||||
@@ -31,15 +31,20 @@
|
||||
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Defines the generic material appearance of a scenegraph object.
|
||||
*/
|
||||
class SGAPPEARANCE : public SGNODE
|
||||
{
|
||||
public:
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
float shininess; // default 0.2
|
||||
float transparency; // default 0.0
|
||||
SGCOLOR ambient; // default 0.05317 0.17879 0.01804
|
||||
SGCOLOR diffuse; // default 0.8 0.8 0.8
|
||||
SGCOLOR emissive; // default 0.0 0.0 0.0
|
||||
SGCOLOR specular; // default 0.0 0.0 0.0
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGAPPEARANCE( SGNODE* aParent );
|
||||
virtual ~SGAPPEARANCE();
|
||||
|
||||
@@ -61,23 +66,15 @@ public:
|
||||
bool SetAmbient( const SGCOLOR* aRGBColor );
|
||||
bool SetAmbient( const SGCOLOR& aRGBColor );
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
float shininess; // default 0.2
|
||||
float transparency; // default 0.0
|
||||
SGCOLOR ambient; // default 0.05317 0.17879 0.01804
|
||||
SGCOLOR diffuse; // default 0.8 0.8 0.8
|
||||
SGCOLOR emissive; // default 0.0 0.0 0.0
|
||||
SGCOLOR specular; // default 0.0 0.0 0.0
|
||||
|
||||
};
|
||||
|
||||
#endif // SG_APPEARANCE_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -36,14 +35,20 @@ SGCOLOR::SGCOLOR()
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||
{
|
||||
if( !checkRange( aRVal, aGVal, aBVal ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid value passed to constructor" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid value passed to constructor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
red = 0.0;
|
||||
green = 0.0;
|
||||
blue = 0.0;
|
||||
@@ -53,32 +58,46 @@ SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||
red = aRVal;
|
||||
green = aGVal;
|
||||
blue = aBVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const noexcept
|
||||
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const
|
||||
{
|
||||
aRedVal = red;
|
||||
aGreenVal = green;
|
||||
aBlueVal = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const noexcept
|
||||
void SGCOLOR::GetColor( SGCOLOR& aColor ) const
|
||||
{
|
||||
aColor.red = red;
|
||||
aColor.green = green;
|
||||
aColor.blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const noexcept
|
||||
void SGCOLOR::GetColor( SGCOLOR* aColor ) const
|
||||
{
|
||||
wxCHECK_MSG( aColor, /* void */, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
aColor->red = red;
|
||||
aColor->green = green;
|
||||
aColor->blue = blue;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +114,7 @@ bool SGCOLOR::SetColor( float aRedVal, float aGreenVal, float aBlueVal )
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor ) noexcept
|
||||
bool SGCOLOR::SetColor( const SGCOLOR& aColor )
|
||||
{
|
||||
red = aColor.red;
|
||||
green = aColor.green;
|
||||
@@ -104,9 +123,19 @@ bool SGCOLOR::SetColor( const SGCOLOR& aColor ) noexcept
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor ) noexcept
|
||||
bool SGCOLOR::SetColor( const SGCOLOR* aColor )
|
||||
{
|
||||
wxCHECK_MSG( aColor, false, wxT( "NULL pointer passed for aRGBColor" ) );
|
||||
if( NULL == aColor )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aColor";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
red = aColor->red;
|
||||
green = aColor->green;
|
||||
@@ -115,31 +144,42 @@ bool SGCOLOR::SetColor( const SGCOLOR* aColor ) noexcept
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const noexcept
|
||||
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
if( aRedVal < 0.0 || aRedVal > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid RED value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aRedVal );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid RED value: " << aRedVal;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aGreenVal < 0.0 || aGreenVal > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid GREEN value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aGreenVal );
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid GREEN value: %f\n", aGreenVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if( aBlueVal < 0.0 || aBlueVal > 1.0 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] invalid BLUE value: %g" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aBlueVal );
|
||||
|
||||
#ifdef DEBUG
|
||||
if( ok )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, "%s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__ );
|
||||
}
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] invalid BLUE value: %f\n", aBlueVal );
|
||||
#endif
|
||||
ok = false;
|
||||
}
|
||||
|
||||
@@ -152,10 +192,11 @@ SGPOINT::SGPOINT()
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
z = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
@@ -163,45 +204,60 @@ SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const double& aXVal, const double& aYVal, const double& aZVal ) noexcept
|
||||
void SGPOINT::GetPoint( double& aXVal, double& aYVal, double& aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const SGPOINT& aPoint ) noexcept
|
||||
void SGPOINT::GetPoint( SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::GetPoint( const SGPOINT* aPoint ) noexcept
|
||||
void SGPOINT::GetPoint( SGPOINT* aPoint )
|
||||
{
|
||||
wxCHECK_MSG( aPoint, /* void */, wxT( "NULL pointer passed for aPoint" ) );
|
||||
if( NULL == aPoint )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aPoint";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
x = aPoint->x;
|
||||
y = aPoint->y;
|
||||
z = aPoint->z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal ) noexcept
|
||||
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal )
|
||||
{
|
||||
x = aXVal;
|
||||
y = aYVal;
|
||||
z = aZVal;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint ) noexcept
|
||||
void SGPOINT::SetPoint( const SGPOINT& aPoint )
|
||||
{
|
||||
x = aPoint.x;
|
||||
y = aPoint.y;
|
||||
z = aPoint.z;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +266,7 @@ SGVECTOR::SGVECTOR()
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,14 +276,16 @@ SGVECTOR::SGVECTOR( double aXVal, double aYVal, double aZVal )
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const noexcept
|
||||
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const
|
||||
{
|
||||
aXVal = vx;
|
||||
aYVal = vy;
|
||||
aZVal = vz;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,25 +295,28 @@ void SGVECTOR::SetVector( double aXVal, double aYVal, double aZVal )
|
||||
vy = aYVal;
|
||||
vz = aZVal;
|
||||
normalize();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::SetVector( const SGVECTOR& aVector )
|
||||
{
|
||||
aVector.GetVector( vx, vy, vz );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGVECTOR::normalize( void ) noexcept
|
||||
void SGVECTOR::normalize( void )
|
||||
{
|
||||
double dx = vx * vx;
|
||||
double dy = vy * vy;
|
||||
double dz = vz * vz;
|
||||
double dv2 = sqrt( dx + dy + dz );
|
||||
|
||||
if( ( dx + dy + dz ) < 1e-8 )
|
||||
if( (dx + dy + dz) < 1e-8 )
|
||||
{
|
||||
// use the default; the numbers are too small to be believable
|
||||
// use the default; the numbers are too small
|
||||
// to be believable
|
||||
vx = 0.0;
|
||||
vy = 0.0;
|
||||
vz = 1.0;
|
||||
@@ -264,10 +326,12 @@ void SGVECTOR::normalize( void ) noexcept
|
||||
vx /= dv2;
|
||||
vy /= dv2;
|
||||
vz /= dv2;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source ) noexcept
|
||||
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source )
|
||||
{
|
||||
vx = source.vx;
|
||||
vy = source.vy;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -29,35 +28,41 @@
|
||||
#include "3d_cache/sg/sg_colors.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGCOLORS::SGCOLORS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COLORS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGCOLORS (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOLORS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOLORS::~SGCOLORS()
|
||||
{
|
||||
colors.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -66,14 +71,14 @@ bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOLORS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -85,41 +90,65 @@ bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOLORS::FindNode(const char* aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGCOLORS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOLORS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOLORS::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOLORS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -130,7 +159,7 @@ bool SGCOLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||
if( colors.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aColorList = nullptr;
|
||||
aColorList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -144,7 +173,7 @@ void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
{
|
||||
colors.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aColorList )
|
||||
if( 0 == aListSize || NULL == aColorList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
@@ -156,7 +185,7 @@ void SGCOLORS::SetColorList( size_t aListSize, const SGCOLOR* aColorList )
|
||||
|
||||
void SGCOLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||
{
|
||||
colors.emplace_back( aRedValue, aGreenValue, aBlueValue );
|
||||
colors.push_back( SGCOLOR( aRedValue, aGreenValue, aBlueValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -238,16 +267,26 @@ bool SGCOLORS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -256,12 +295,26 @@ bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -283,10 +336,20 @@ bool SGCOLORS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGCOLORS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( colors.empty(), false );
|
||||
if( !colors.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ncolors;
|
||||
aFile.read( (char*) &ncolors, sizeof( size_t ) );
|
||||
aFile.read( (char*)&ncolors, sizeof(size_t) );
|
||||
SGCOLOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_colors.h
|
||||
* defines an RGB color set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COLORS_H
|
||||
@@ -32,23 +32,23 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define an RGB color set for a scenegraph object.
|
||||
*/
|
||||
class SGCOLORS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGCOLOR > colors;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOLORS( SGNODE* aParent );
|
||||
virtual ~SGCOLORS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
|
||||
void SetColorList( size_t aListSize, const SGCOLOR* aColorList );
|
||||
@@ -60,8 +60,6 @@ public:
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
std::vector< SGCOLOR > colors;
|
||||
};
|
||||
|
||||
#endif // SG_COLORS_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -29,15 +28,18 @@ SGCOORDINDEX::SGCOORDINDEX( SGNODE* aParent ) : SGINDEX( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDINDEX;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDINDEX::~SGCOORDINDEX()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,4 +49,6 @@ void SGCOORDINDEX::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
return;
|
||||
|
||||
aIndexList.insert( aIndexList.end(), index.begin(), index.end() );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_coordindex.h
|
||||
* defines an coordinate index set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDINDEX_H
|
||||
@@ -32,12 +32,14 @@
|
||||
#include "3d_cache/sg/sg_index.h"
|
||||
|
||||
/**
|
||||
* An object to maintain a coordinate index list.
|
||||
*
|
||||
* Users must ensure that coordinate indices are specified as triplets (triangular faces)
|
||||
* since no checking is performed. In instances where it is not possible to determine which
|
||||
* side of the triangle is to be rendered (for example IGES entities) then the user must
|
||||
* supply each triplet in both point orders.
|
||||
* Class SGCOORDINDEX
|
||||
* is a class which maintains a coordinate index list. Users
|
||||
* must ensure that coordinate indices are specified as
|
||||
* triplets (triangular faces) since no checking is performed.
|
||||
* In instances where it is not possible to determine which
|
||||
* side of the triangle is to be rendered (for example IGES
|
||||
* entities) then the user must supply each triplet in both
|
||||
* point orders.
|
||||
*/
|
||||
class SGCOORDINDEX : public SGINDEX
|
||||
{
|
||||
@@ -46,7 +48,9 @@ public:
|
||||
virtual ~SGCOORDINDEX();
|
||||
|
||||
/**
|
||||
* Add all coordinate indices to the given list in preparation for a normals calculation.
|
||||
* Function GatherCoordIndices
|
||||
* adds all coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -36,30 +35,37 @@ SGCOORDS::SGCOORDS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_COORDS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGCOORDS (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGCOORDS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGCOORDS::~SGCOORDS()
|
||||
{
|
||||
coords.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -68,14 +74,14 @@ bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGCOORDS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -87,41 +93,65 @@ bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( aCaller, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOORDS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGCOORDS::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGCOORDS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -132,7 +162,7 @@ bool SGCOORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||
if( coords.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aCoordsList = nullptr;
|
||||
aCoordsList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,23 +176,27 @@ void SGCOORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||
{
|
||||
coords.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aCoordsList )
|
||||
if( 0 == aListSize || NULL == aCoordsList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < aListSize; ++i )
|
||||
coords.push_back( aCoordsList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
coords.emplace_back( aXValue, aYValue, aZValue );
|
||||
coords.push_back( SGPOINT( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGCOORDS::AddCoord( const SGPOINT& aPoint )
|
||||
{
|
||||
coords.push_back( aPoint );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,16 +274,26 @@ bool SGCOORDS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -258,12 +302,26 @@ bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -285,10 +343,20 @@ bool SGCOORDS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( coords.empty(), false );
|
||||
if( !coords.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*) &npts, sizeof( size_t ) );
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGPOINT tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
@@ -309,15 +377,15 @@ bool SGCOORDS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
{
|
||||
if( aPtr )
|
||||
*aPtr = nullptr;
|
||||
*aPtr = NULL;
|
||||
|
||||
if( nullptr == m_Parent || nullptr == callingNode )
|
||||
if( NULL == m_Parent || NULL == callingNode )
|
||||
return false;
|
||||
|
||||
// the parent and all references must have indices; collect all
|
||||
// indices into one std::vector<>
|
||||
std::vector< int > ilist;
|
||||
SGNORMALS* np = nullptr;
|
||||
SGNORMALS* np = NULL;
|
||||
|
||||
if( callingNode == m_Parent )
|
||||
{
|
||||
@@ -333,7 +401,7 @@ bool SGCOORDS::CalcNormals( SGFACESET* callingNode, SGNODE** aPtr )
|
||||
++sB;
|
||||
}
|
||||
|
||||
np = ( (SGFACESET*) m_Parent )->m_Normals;
|
||||
np = ((SGFACESET*)m_Parent)->m_Normals;
|
||||
|
||||
if( !np )
|
||||
np = new SGNORMALS( m_Parent );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_coords.h
|
||||
* defines a vertex coordinate set for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_COORDS_H
|
||||
@@ -34,23 +34,23 @@
|
||||
|
||||
class SGFACESET;
|
||||
|
||||
/**
|
||||
* Define a vertex coordinate set for a scenegraph object.
|
||||
*/
|
||||
class SGCOORDS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGPOINT > coords;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGCOORDS( SGNODE* aParent );
|
||||
virtual ~SGCOORDS();
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList );
|
||||
void SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList );
|
||||
@@ -58,18 +58,17 @@ public:
|
||||
void AddCoord( const SGPOINT& aPoint );
|
||||
|
||||
/**
|
||||
* Calculate normals for this coordinate list and sets the normals list in the
|
||||
* parent #SGFACESET.
|
||||
* Function CalcNormals
|
||||
* calculates normals for this coordinate list and sets the
|
||||
* normals list in the parent SGFACESET
|
||||
*/
|
||||
bool CalcNormals( SGFACESET* callingNode, SGNODE** aPtr = nullptr );
|
||||
bool CalcNormals( SGFACESET* callingNode, SGNODE** aPtr = NULL );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
std::vector< SGPOINT > coords;
|
||||
};
|
||||
|
||||
#endif // SG_COORDS_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -34,33 +33,37 @@
|
||||
#include "3d_cache/sg/sg_coordindex.h"
|
||||
#include "3d_cache/sg/sg_helpers.h"
|
||||
|
||||
|
||||
SGFACESET::SGFACESET( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_FACESET;
|
||||
m_Colors = nullptr;
|
||||
m_Coords = nullptr;
|
||||
m_CoordIndices = nullptr;
|
||||
m_Normals = nullptr;
|
||||
m_RColors = nullptr;
|
||||
m_RCoords = nullptr;
|
||||
m_RNormals = nullptr;
|
||||
m_Colors = NULL;
|
||||
m_Coords = NULL;
|
||||
m_CoordIndices = NULL;
|
||||
m_Normals = NULL;
|
||||
m_RColors = NULL;
|
||||
m_RCoords = NULL;
|
||||
m_RNormals = NULL;
|
||||
valid = false;
|
||||
validated = false;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] inappropriate parent to SGFACESET (type %s)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGFACESET (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,55 +73,57 @@ SGFACESET::~SGFACESET()
|
||||
if( m_RColors )
|
||||
{
|
||||
m_RColors->delNodeRef( this );
|
||||
m_RColors = nullptr;
|
||||
m_RColors = NULL;
|
||||
}
|
||||
|
||||
if( m_RCoords )
|
||||
{
|
||||
m_RCoords->delNodeRef( this );
|
||||
m_RCoords = nullptr;
|
||||
m_RCoords = NULL;
|
||||
}
|
||||
|
||||
if( m_RNormals )
|
||||
{
|
||||
m_RNormals->delNodeRef( this );
|
||||
m_RNormals = nullptr;
|
||||
m_RNormals = NULL;
|
||||
}
|
||||
|
||||
// delete owned objects
|
||||
if( m_Colors )
|
||||
{
|
||||
m_Colors->SetParent( nullptr, false );
|
||||
m_Colors->SetParent( NULL, false );
|
||||
delete m_Colors;
|
||||
m_Colors = nullptr;
|
||||
m_Colors = NULL;
|
||||
}
|
||||
|
||||
if( m_Coords )
|
||||
{
|
||||
m_Coords->SetParent( nullptr, false );
|
||||
m_Coords->SetParent( NULL, false );
|
||||
delete m_Coords;
|
||||
m_Coords = nullptr;
|
||||
m_Coords = NULL;
|
||||
}
|
||||
|
||||
if( m_Normals )
|
||||
{
|
||||
m_Normals->SetParent( nullptr, false );
|
||||
m_Normals->SetParent( NULL, false );
|
||||
delete m_Normals;
|
||||
m_Normals = nullptr;
|
||||
m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( m_CoordIndices )
|
||||
{
|
||||
m_CoordIndices->SetParent( nullptr, false );
|
||||
m_CoordIndices->SetParent( NULL, false );
|
||||
delete m_CoordIndices;
|
||||
m_CoordIndices = nullptr;
|
||||
m_CoordIndices = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -127,14 +132,14 @@ bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGSHAPE may be parent to a SGFACESET
|
||||
if( nullptr != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -148,13 +153,13 @@ bool SGFACESET::SetParent( SGNODE* aParent, bool notify )
|
||||
|
||||
SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* np = nullptr;
|
||||
SGNODE* np = NULL;
|
||||
|
||||
if( m_Colors )
|
||||
{
|
||||
@@ -189,8 +194,8 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -198,7 +203,7 @@ SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
|
||||
void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
valid = false;
|
||||
@@ -208,25 +213,25 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode == m_Colors )
|
||||
{
|
||||
m_Colors = nullptr;
|
||||
m_Colors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_Coords )
|
||||
{
|
||||
m_Coords = nullptr;
|
||||
m_Coords = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_Normals )
|
||||
{
|
||||
m_Normals = nullptr;
|
||||
m_Normals = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_CoordIndices )
|
||||
{
|
||||
m_CoordIndices = nullptr;
|
||||
m_CoordIndices = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -235,46 +240,66 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
if( aNode == m_RColors )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RColors = nullptr;
|
||||
m_RColors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RCoords )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RCoords = nullptr;
|
||||
m_RCoords = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RNormals )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RNormals = nullptr;
|
||||
m_RNormals = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGFACESET::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGFACESET::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
valid = false;
|
||||
validated = false;
|
||||
@@ -285,8 +310,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Colors && aNode != m_RColors )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Colors nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Colors nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -314,8 +343,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Coords && aNode != m_RCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Colors nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Coords nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -343,8 +376,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Normals && aNode != m_RNormals )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Normals nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Normals nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -372,9 +409,12 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_CoordIndices )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG,
|
||||
wxT( "%s:%s:%d * [BUG] assigning multiple CoordIndex nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple CoordIndex nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -388,11 +428,16 @@ bool SGFACESET::addNode( SGNODE* aNode, bool isChild )
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] object type '%s' is not a valid type for "
|
||||
"this object '%d'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aNode->GetName(),
|
||||
aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' (type " << aNode->GetNodeType();
|
||||
ostr << ") is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -432,12 +477,15 @@ void SGFACESET::ReNameNodes( void )
|
||||
// rename all Normals and Indices
|
||||
if( m_Normals )
|
||||
m_Normals->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGFACESET::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( ( nullptr == m_Coords && nullptr == m_RCoords ) || ( nullptr == m_CoordIndices ) )
|
||||
if( ( NULL == m_Coords && NULL == m_RCoords )
|
||||
|| ( NULL == m_CoordIndices ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -492,16 +540,26 @@ bool SGFACESET::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -510,24 +568,38 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if any references are unwritten and swap parents if so
|
||||
if( nullptr != m_RCoords && !m_RCoords->isWritten() )
|
||||
if( NULL != m_RCoords && !m_RCoords->isWritten() )
|
||||
m_RCoords->SwapParent( this );
|
||||
|
||||
if( nullptr != m_RNormals && !m_RNormals->isWritten() )
|
||||
if( NULL != m_RNormals && !m_RNormals->isWritten() )
|
||||
m_RNormals->SwapParent( this );
|
||||
|
||||
if( nullptr != m_RColors && !m_RColors->isWritten() )
|
||||
if( NULL != m_RColors && !m_RColors->isWritten() )
|
||||
m_RColors->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
@@ -539,35 +611,35 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
if( nullptr != m_Coords )
|
||||
if( NULL != m_Coords )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RCoords )
|
||||
if( NULL != m_RCoords )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_CoordIndices )
|
||||
if( NULL != m_CoordIndices )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_Normals )
|
||||
if( NULL != m_Normals )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RNormals )
|
||||
if( NULL != m_RNormals )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_Colors )
|
||||
if( NULL != m_Colors )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
if( nullptr != m_RColors )
|
||||
if( NULL != m_RColors )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
aFile.write( (char*) &items[jj], sizeof( bool ) );
|
||||
aFile.write( (char*)&items[jj], sizeof(bool) );
|
||||
|
||||
if( items[0] )
|
||||
m_Coords->WriteCache( aFile, this );
|
||||
@@ -600,11 +672,16 @@ bool SGFACESET::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( m_Coords || m_RCoords || m_CoordIndices || m_Colors || m_RColors || m_Normals
|
||||
|| m_RNormals )
|
||||
if( m_Coords || m_RCoords || m_CoordIndices
|
||||
|| m_Colors || m_RColors
|
||||
|| m_Normals || m_RNormals )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] non-empty node" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -613,14 +690,18 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
bool items[NITEMS];
|
||||
|
||||
for( int i = 0; i < NITEMS; ++i )
|
||||
aFile.read( (char*) &items[i], sizeof( bool ) );
|
||||
aFile.read( (char*)&items[i], sizeof(bool) );
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[3] && items[4] ) || ( items[5] && items[6] ) )
|
||||
if( ( items[0] && items[1] ) || ( items[3] && items[4] )
|
||||
|| ( items[5] && items[6] ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; multiple item definitions "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; multiple item definitions at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -631,10 +712,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child coords tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child coords tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -644,10 +728,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Coords->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; corrupt data while "
|
||||
"reading coords '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading coords '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -657,10 +744,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref coords tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref coords tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -669,20 +759,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; cannot find ref "
|
||||
"coords '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref coords '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_COORDS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; type is not SGCOORDS "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGCOORDS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -695,10 +791,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COORDINDEX != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad coord index tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad coord index tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -708,10 +807,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_CoordIndices->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading coord "
|
||||
"index '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading coord index '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -721,10 +823,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child normals tag "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child normals tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -734,10 +839,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Normals->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading normals "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading normals '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -747,10 +855,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref normals tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref normals tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -759,19 +870,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt: cannot find ref normals "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref normals '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_NORMALS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt: type is not SGNORMALS '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGNORMALS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -784,10 +902,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child colors tag "
|
||||
"at position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child colors tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -797,10 +918,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Colors->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading colors "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading colors '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -810,10 +934,13 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref colors tag at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref colors tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -822,20 +949,26 @@ bool SGFACESET::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref colors "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref colors '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_COLORS != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGCOLORS "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGCOLORS '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -858,14 +991,16 @@ bool SGFACESET::validate( void )
|
||||
return valid;
|
||||
|
||||
// ensure we have at least coordinates and their normals
|
||||
if( ( nullptr == m_Coords && nullptr == m_RCoords )
|
||||
|| ( nullptr == m_Normals && nullptr == m_RNormals )
|
||||
|| ( nullptr == m_CoordIndices ) )
|
||||
if( (NULL == m_Coords && NULL == m_RCoords)
|
||||
|| (NULL == m_Normals && NULL == m_RNormals)
|
||||
|| (NULL == m_CoordIndices) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; no vertices, vertex indices, "
|
||||
"or normals" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; no vertices, vertex indices, or normals";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -874,18 +1009,21 @@ bool SGFACESET::validate( void )
|
||||
// check that there are >3 vertices
|
||||
SGCOORDS* coords = m_Coords;
|
||||
|
||||
if( nullptr == coords )
|
||||
if( NULL == coords )
|
||||
coords = m_RCoords;
|
||||
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* lCoords = nullptr;
|
||||
SGPOINT* lCoords = NULL;
|
||||
coords->GetCoordsList( nCoords, lCoords );
|
||||
|
||||
if( nCoords < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; fewer than 3 vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; fewer than 3 vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -893,15 +1031,17 @@ bool SGFACESET::validate( void )
|
||||
|
||||
// check that nVertices is divisible by 3 (facets are triangles)
|
||||
size_t nCIdx = 0;
|
||||
int* lCIdx = nullptr;
|
||||
int* lCIdx = NULL;
|
||||
m_CoordIndices->GetIndices( nCIdx, lCIdx );
|
||||
|
||||
if( nCIdx < 3 || ( nCIdx % 3 > 0 ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; no vertex indices or not "
|
||||
"multiple of 3" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; no vertex indices or not multiple of 3";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -912,10 +1052,12 @@ bool SGFACESET::validate( void )
|
||||
{
|
||||
if( lCIdx[i] < 0 || lCIdx[i] >= (int)nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; vertex index out of "
|
||||
"bounds" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; vertex index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -924,22 +1066,23 @@ bool SGFACESET::validate( void )
|
||||
|
||||
// check that there are as many normals as vertices
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* lNorms = nullptr;
|
||||
SGVECTOR* lNorms = NULL;
|
||||
SGNORMALS* pNorms = m_Normals;
|
||||
|
||||
if( nullptr == pNorms )
|
||||
if( NULL == pNorms )
|
||||
pNorms = m_RNormals;
|
||||
|
||||
pNorms->GetNormalList( nNorms, lNorms );
|
||||
|
||||
if( nNorms != nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; number of normals (%ul) does "
|
||||
"not match number of vertices (%ul)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( nNorms ),
|
||||
static_cast<unsigned long>( nCoords ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; number of normals (" << nNorms;
|
||||
ostr << ") does not match number of vertices (" << nCoords << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
validated = true;
|
||||
valid = false;
|
||||
return false;
|
||||
@@ -948,14 +1091,14 @@ bool SGFACESET::validate( void )
|
||||
// if there are colors then ensure there are as many colors as vertices
|
||||
SGCOLORS* pColors = m_Colors;
|
||||
|
||||
if( nullptr == pColors )
|
||||
if( NULL == pColors )
|
||||
pColors = m_RColors;
|
||||
|
||||
if( nullptr != pColors )
|
||||
if( NULL != pColors )
|
||||
{
|
||||
// we must have at least as many colors as vertices
|
||||
size_t nColor = 0;
|
||||
SGCOLOR* pColor = nullptr;
|
||||
SGCOLOR* pColor = NULL;
|
||||
pColors->GetColorList( nColor, pColor );
|
||||
}
|
||||
|
||||
@@ -969,6 +1112,8 @@ void SGFACESET::GatherCoordIndices( std::vector< int >& aIndexList )
|
||||
{
|
||||
if( m_CoordIndices )
|
||||
m_CoordIndices->GatherCoordIndices( aIndexList );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -979,7 +1124,7 @@ bool SGFACESET::CalcNormals( SGNODE** aPtr )
|
||||
if( m_RCoords )
|
||||
coords = m_RCoords;
|
||||
|
||||
if( nullptr == coords || coords->coords.empty() )
|
||||
if( NULL == coords || coords->coords.empty() )
|
||||
return false;
|
||||
|
||||
if( m_Normals && !m_Normals->norms.empty( ) )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_faceset.h
|
||||
* defines an indexed face set for a scenegraph
|
||||
*/
|
||||
|
||||
|
||||
@@ -40,18 +40,38 @@ class SGNORMALS;
|
||||
class SGCOLORINDEX;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
/**
|
||||
* Define an indexed face set for a scenegraph.
|
||||
*/
|
||||
class SGFACESET : public SGNODE
|
||||
{
|
||||
private:
|
||||
bool valid;
|
||||
bool validated;
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
public:
|
||||
// owned objects
|
||||
SGCOLORS* m_Colors;
|
||||
SGCOORDS* m_Coords;
|
||||
SGCOORDINDEX* m_CoordIndices;
|
||||
SGNORMALS* m_Normals;
|
||||
|
||||
// referenced objects
|
||||
SGCOLORS* m_RColors;
|
||||
SGCOORDS* m_RCoords;
|
||||
SGNORMALS* m_RNormals;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
// validate the data held by this face set
|
||||
bool validate( void );
|
||||
|
||||
public:
|
||||
SGFACESET( SGNODE* aParent );
|
||||
virtual ~SGFACESET();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode( const char* aNodeName, const SGNODE* aCaller ) override;
|
||||
SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
@@ -64,34 +84,11 @@ public:
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
/**
|
||||
* Add all internal coordinate indices to the given list in preparation for a normals
|
||||
* calculation.
|
||||
* Function GatherCoordIndices
|
||||
* adds all internal coordinate indices to the given list
|
||||
* in preparation for a normals calculation
|
||||
*/
|
||||
void GatherCoordIndices( std::vector< int >& aIndexList );
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
// validate the data held by this face set
|
||||
bool validate( void );
|
||||
|
||||
// owned objects
|
||||
SGCOLORS* m_Colors;
|
||||
SGCOORDS* m_Coords;
|
||||
SGCOORDINDEX* m_CoordIndices;
|
||||
SGNORMALS* m_Normals;
|
||||
|
||||
// referenced objects
|
||||
SGCOLORS* m_RColors;
|
||||
SGCOORDS* m_RCoords;
|
||||
SGNORMALS* m_RNormals;
|
||||
|
||||
private:
|
||||
bool valid;
|
||||
bool validated;
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -34,6 +33,7 @@
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void S3D::FormatFloat( std::string& result, double value )
|
||||
{
|
||||
if( value < 1e-8 && value > -1e-8 )
|
||||
@@ -49,9 +49,10 @@ void S3D::FormatFloat( std::string& result, double value )
|
||||
|
||||
result = out.str();
|
||||
|
||||
size_t p = result.find( '.' );
|
||||
size_t p = result.find( "." );
|
||||
|
||||
// trim trailing 0 if appropriate
|
||||
|
||||
if( std::string::npos == p )
|
||||
return;
|
||||
|
||||
@@ -59,26 +60,28 @@ void S3D::FormatFloat( std::string& result, double value )
|
||||
|
||||
if( std::string::npos == p )
|
||||
{
|
||||
while( '0' == *( result.rbegin() ) )
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( '0' != result.at( p - 1 ) )
|
||||
if( '0' != result.at( p -1 ) )
|
||||
return;
|
||||
|
||||
// trim all 0 to the left of 'p'
|
||||
std::string tmp = result.substr( p );
|
||||
result = result.substr( 0, p );
|
||||
|
||||
while( '0' == *( result.rbegin() ) )
|
||||
while( '0' == *(result.rbegin()) )
|
||||
result.erase( result.size() - 1 );
|
||||
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format orientation data for VRML output
|
||||
void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation )
|
||||
{
|
||||
double aX;
|
||||
@@ -97,9 +100,11 @@ void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double r
|
||||
FormatFloat( tmp, rotation );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format point data for VRML output
|
||||
void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||
{
|
||||
FormatFloat( result, point.x );
|
||||
@@ -112,9 +117,12 @@ void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||
FormatFloat( tmp, point.z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format vector data for VRML output
|
||||
void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||
{
|
||||
double X, Y, Z;
|
||||
@@ -129,9 +137,12 @@ void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||
FormatFloat( tmp, Z );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// format Color data for VRML output
|
||||
void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||
{
|
||||
float R, G, B;
|
||||
@@ -146,14 +157,16 @@ void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||
FormatFloat( tmp, B );
|
||||
result.append( " " );
|
||||
result.append( tmp );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::WritePoint( std::ostream& aFile, const SGPOINT& aPoint )
|
||||
{
|
||||
aFile.write( (char*) &aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.write( (char*) &aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.write( (char*) &aPoint.z, sizeof( aPoint.z ) );
|
||||
aFile.write( (char*)&aPoint.x, sizeof(aPoint.x) );
|
||||
aFile.write( (char*)&aPoint.y, sizeof(aPoint.y) );
|
||||
aFile.write( (char*)&aPoint.z, sizeof(aPoint.z) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -166,9 +179,9 @@ bool S3D::WriteVector( std::ostream& aFile, const SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aVector.GetVector( x, y, z );
|
||||
aFile.write( (char*) &x, sizeof( double ) );
|
||||
aFile.write( (char*) &y, sizeof( double ) );
|
||||
aFile.write( (char*) &z, sizeof( double ) );
|
||||
aFile.write( (char*)&x, sizeof(double) );
|
||||
aFile.write( (char*)&y, sizeof(double) );
|
||||
aFile.write( (char*)&z, sizeof(double) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -181,9 +194,9 @@ bool S3D::WriteColor( std::ostream& aFile, const SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aColor.GetColor( r, g, b );
|
||||
aFile.write( (char*) &r, sizeof( float ) );
|
||||
aFile.write( (char*) &g, sizeof( float ) );
|
||||
aFile.write( (char*) &b, sizeof( float ) );
|
||||
aFile.write( (char*)&r, sizeof(float) );
|
||||
aFile.write( (char*)&g, sizeof(float) );
|
||||
aFile.write( (char*)&b, sizeof(float) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -199,10 +212,13 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( '[' != schar )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; missing left bracket at "
|
||||
"position %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<int>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; missing left bracket at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -218,9 +234,12 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( schar != ']' )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; could not find right "
|
||||
"bracket" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; could not find right bracket";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -230,9 +249,13 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
if( std::string::npos == upos )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; no underscore in name '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no underscore in name '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -256,9 +279,15 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
return types[i];
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; no node type matching '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; no node type matching '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return S3D::SGTYPE_END;
|
||||
}
|
||||
@@ -266,9 +295,9 @@ S3D::SGTYPES S3D::ReadTag( std::istream& aFile, std::string& aName )
|
||||
|
||||
bool S3D::ReadPoint( std::istream& aFile, SGPOINT& aPoint )
|
||||
{
|
||||
aFile.read( (char*) &aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.read( (char*) &aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.read( (char*) &aPoint.z, sizeof( aPoint.z ) );
|
||||
aFile.read( (char*)&aPoint.x, sizeof( aPoint.x ) );
|
||||
aFile.read( (char*)&aPoint.y, sizeof( aPoint.y ) );
|
||||
aFile.read( (char*)&aPoint.z, sizeof( aPoint.z ) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
@@ -280,9 +309,9 @@ bool S3D::ReadPoint( std::istream& aFile, SGPOINT& aPoint )
|
||||
bool S3D::ReadVector( std::istream& aFile, SGVECTOR& aVector )
|
||||
{
|
||||
double x, y, z;
|
||||
aFile.read( (char*) &x, sizeof( double ) );
|
||||
aFile.read( (char*) &y, sizeof( double ) );
|
||||
aFile.read( (char*) &z, sizeof( double ) );
|
||||
aFile.read( (char*)&x, sizeof(double) );
|
||||
aFile.read( (char*)&y, sizeof(double) );
|
||||
aFile.read( (char*)&z, sizeof(double) );
|
||||
aVector.SetVector( x, y, z );
|
||||
|
||||
if( aFile.fail() )
|
||||
@@ -295,9 +324,9 @@ bool S3D::ReadVector( std::istream& aFile, SGVECTOR& aVector )
|
||||
bool S3D::ReadColor( std::istream& aFile, SGCOLOR& aColor )
|
||||
{
|
||||
float r, g, b;
|
||||
aFile.read( (char*) &r, sizeof( float ) );
|
||||
aFile.read( (char*) &g, sizeof( float ) );
|
||||
aFile.read( (char*) &b, sizeof( float ) );
|
||||
aFile.read( (char*)&r, sizeof(float) );
|
||||
aFile.read( (char*)&g, sizeof(float) );
|
||||
aFile.read( (char*)&b, sizeof(float) );
|
||||
aColor.SetColor( r, g, b );
|
||||
|
||||
if( aFile.fail() )
|
||||
@@ -307,7 +336,7 @@ bool S3D::ReadColor( std::istream& aFile, SGCOLOR& aColor )
|
||||
}
|
||||
|
||||
|
||||
bool S3D::degenerate( glm::dvec3* pts ) noexcept
|
||||
bool S3D::degenerate( glm::dvec3* pts )
|
||||
{
|
||||
double dx, dy, dz;
|
||||
|
||||
@@ -347,19 +376,24 @@ static void calcTriad( glm::dvec3* pts, glm::dvec3& tri )
|
||||
|
||||
// normal * 2 * area
|
||||
tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >& index,
|
||||
std::vector< SGVECTOR >& norms )
|
||||
bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords,
|
||||
std::vector< int >& index, std::vector< SGVECTOR >& norms )
|
||||
{
|
||||
size_t vsize = coords.size();
|
||||
|
||||
if( vsize < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] invalid vertex set (fewer than 3 "
|
||||
"vertices)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid vertex set (fewer than 3 vertices)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -368,16 +402,24 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
|
||||
if( 0 != isize % 3 || index.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] invalid index set (not multiple of 3)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set (not multiple of 3)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !norms.empty() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] normals set is not empty" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] normals set is not empty";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -393,14 +435,15 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
p2 = index[i++];
|
||||
p3 = index[i++];
|
||||
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize || p3 < 0 || p3 >= (int)vsize )
|
||||
if( p1 < 0 || p1 >= (int)vsize || p2 < 0 || p2 >= (int)vsize ||
|
||||
p3 < 0 || p3 >= (int)vsize )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] invalid index set; index out of bounds";
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s\n" ), ostr.str().c_str() );
|
||||
#endif
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -420,7 +463,8 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.emplace( p1, std::list < glm::dvec3 >( 1, tri ) );
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p1, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p2 );
|
||||
@@ -431,7 +475,8 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.emplace( p2, std::list < glm::dvec3 >( 1, tri ) );
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p2, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
|
||||
ip = vmap.find( p3 );
|
||||
@@ -442,7 +487,8 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
}
|
||||
else
|
||||
{
|
||||
vmap.emplace( p3, std::list < glm::dvec3 >( 1, tri ) );
|
||||
vmap.insert( std::pair < int, std::list < glm::dvec3 > >
|
||||
( p3, std::list < glm::dvec3 >( 1, tri ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +503,7 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
// assign any skipped coordinates a normal of (0,0,1)
|
||||
while( item > idx )
|
||||
{
|
||||
norms.emplace_back( 0, 0, 1 );
|
||||
norms.push_back( SGVECTOR( 0, 0, 1 ) );
|
||||
++idx;
|
||||
}
|
||||
|
||||
@@ -471,7 +517,7 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
++sT;
|
||||
}
|
||||
|
||||
norms.emplace_back( norm.x, norm.y, norm.z );
|
||||
norms.push_back( SGVECTOR( norm.x, norm.y, norm.z ) );
|
||||
|
||||
++idx;
|
||||
++sM;
|
||||
@@ -479,9 +525,12 @@ bool S3D::CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >
|
||||
|
||||
if( norms.size() != coords.size() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] number of normals does not equal number "
|
||||
"of vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] number of normals does not equal number of vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+121
-147
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,10 +23,10 @@
|
||||
|
||||
/**
|
||||
* @file sg_helpers.h
|
||||
*
|
||||
* Define a number of macros to aid in repetitious code which is probably best expressed
|
||||
* as a preprocessor macro rather than as a template. This header also declares a number
|
||||
* of functions which are only of use within the sg_* classes.
|
||||
* defines a number of macro functions to aid in repetitious code which
|
||||
* is probably best expressed as a preprocessor macro rather than as
|
||||
* a template. This header also declares a number of functions which are
|
||||
* only of use within the sg_* classes.
|
||||
*/
|
||||
|
||||
#ifndef SG_HELPERS_H
|
||||
@@ -45,182 +44,151 @@ class SGNORMALS;
|
||||
class SGCOORDS;
|
||||
class SGCOORDINDEX;
|
||||
|
||||
|
||||
// Function to drop references within an SGNODE
|
||||
// The node being destroyed must remove itself from the object reference's
|
||||
// backpointer list in order to avoid a segfault.
|
||||
#define DROP_REFS( aType, aList ) \
|
||||
do \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sL = aList.begin(); \
|
||||
std::vector<aType*>::iterator eL = aList.end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
( (SGNODE*) *sL )->delNodeRef( this ); \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
#define DROP_REFS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->delNodeRef( this ); \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to delete owned objects within an SGNODE
|
||||
// The owned object's parent is set to NULL before
|
||||
// deletion to avoid a redundant 'unlinkChildNode' call.
|
||||
#define DEL_OBJS( aType, aList ) \
|
||||
do \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sL = aList.begin(); \
|
||||
std::vector<aType*>::iterator eL = aList.end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
( (SGNODE*) *sL )->SetParent( nullptr, false ); \
|
||||
delete *sL; \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
#define DEL_OBJS( aType, aList ) do { \
|
||||
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||
std::vector< aType* >::iterator eL = aList.end(); \
|
||||
while( sL != eL ) { \
|
||||
((SGNODE*)*sL)->SetParent( NULL, false ); \
|
||||
delete *sL; \
|
||||
++sL; \
|
||||
} \
|
||||
aList.clear(); \
|
||||
} while( 0 )
|
||||
|
||||
|
||||
// Function to unlink a child or reference node when that child or
|
||||
// reference node is being destroyed.
|
||||
#define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) \
|
||||
do \
|
||||
{ \
|
||||
if( aNodeID == aNode->GetNodeType() ) \
|
||||
{ \
|
||||
std::vector<aType*>* oSL; \
|
||||
std::vector<aType*>::iterator sL; \
|
||||
std::vector<aType*>::iterator eL; \
|
||||
if( isChild ) \
|
||||
{ \
|
||||
oSL = &aOwnedList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
if( (SGNODE*) *sL == aNode ) \
|
||||
{ \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
oSL = &aRefList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) \
|
||||
{ \
|
||||
if( (SGNODE*) *sL == aNode ) \
|
||||
{ \
|
||||
delNodeRef( this ); \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
} while( 0 )
|
||||
#define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >* oSL; \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
std::vector< aType* >::iterator eL; \
|
||||
if( isChild ) { \
|
||||
oSL = &aOwnedList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} else { \
|
||||
oSL = &aRefList; \
|
||||
sL = oSL->begin(); \
|
||||
eL = oSL->end(); \
|
||||
while( sL != eL ) { \
|
||||
if( (SGNODE*)*sL == aNode ) { \
|
||||
delNodeRef( this ); \
|
||||
oSL->erase( sL ); \
|
||||
return; \
|
||||
} \
|
||||
++sL; \
|
||||
} \
|
||||
} \
|
||||
return; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to check a node type, check for an existing reference,
|
||||
// and add the node type to the reference list if applicable
|
||||
#define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) \
|
||||
do \
|
||||
{ \
|
||||
if( aNodeID == aNode->GetNodeType() ) \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sL; \
|
||||
sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
|
||||
if( sL != aOwnedList.end() ) \
|
||||
return true; \
|
||||
sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
|
||||
if( sL != aRefList.end() ) \
|
||||
return true; \
|
||||
if( isChild ) \
|
||||
{ \
|
||||
SGNODE* ppn = (SGNODE*) aNode->GetParent(); \
|
||||
if( nullptr != ppn ) \
|
||||
{ \
|
||||
if( this != ppn ) \
|
||||
{ \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
|
||||
std::cerr << m_Name << "'\n"; \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
aOwnedList.push_back( (aType*) aNode ); \
|
||||
aNode->SetParent( this, false ); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/*if( nullptr == aNode->GetParent() ) { \
|
||||
#define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||
if( aNodeID == aNode->GetNodeType() ) { \
|
||||
std::vector< aType* >::iterator sL; \
|
||||
sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
|
||||
if( sL != aOwnedList.end() ) return true; \
|
||||
sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
|
||||
if( sL != aRefList.end() ) return true; \
|
||||
if( isChild ) { \
|
||||
SGNODE* ppn = (SGNODE*)aNode->GetParent(); \
|
||||
if( NULL != ppn ) { \
|
||||
if( this != ppn ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
|
||||
std::cerr << m_Name << "'\n"; \
|
||||
return false; \
|
||||
} \
|
||||
} \
|
||||
aOwnedList.push_back( (aType*)aNode ); \
|
||||
aNode->SetParent( this, false ); \
|
||||
} else { \
|
||||
/*if( NULL == aNode->GetParent() ) { \
|
||||
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||
std::cerr << "' has no parent\n"; \
|
||||
std::cerr << " * [INFO] possible copy assignment or copy constructor bug\n"; \
|
||||
return false; \
|
||||
} */ \
|
||||
aRefList.push_back( (aType*) aNode ); \
|
||||
aNode->addNodeRef( this ); \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
} while( 0 )
|
||||
} */ \
|
||||
aRefList.push_back( (aType*)aNode ); \
|
||||
aNode->addNodeRef( this ); \
|
||||
} \
|
||||
return true; \
|
||||
} } while( 0 )
|
||||
|
||||
|
||||
// Function to find a node object given a (non-unique) node name
|
||||
#define FIND_NODE( aType, aName, aNodeList, aCallingNode ) \
|
||||
do \
|
||||
{ \
|
||||
std::vector<aType*>::iterator sLA = aNodeList.begin(); \
|
||||
std::vector<aType*>::iterator eLA = aNodeList.end(); \
|
||||
SGNODE* psg = nullptr; \
|
||||
while( sLA != eLA ) \
|
||||
{ \
|
||||
if( (SGNODE*) *sLA != aCallingNode ) \
|
||||
{ \
|
||||
psg = (SGNODE*) ( *sLA )->FindNode( aName, this ); \
|
||||
if( nullptr != psg ) \
|
||||
return psg; \
|
||||
} \
|
||||
++sLA; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#define FIND_NODE( aType, aName, aNodeList, aCallingNode ) do { \
|
||||
std::vector< aType* >::iterator sLA = aNodeList.begin(); \
|
||||
std::vector< aType* >::iterator eLA = aNodeList.end(); \
|
||||
SGNODE* psg = NULL; \
|
||||
while( sLA != eLA ) { \
|
||||
if( (SGNODE*)*sLA != aCallingNode ) { \
|
||||
psg = (SGNODE*) (*sLA)->FindNode( aName, this ); \
|
||||
if( NULL != psg) \
|
||||
return psg; \
|
||||
} \
|
||||
++sLA; \
|
||||
} } while ( 0 )
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
bool degenerate( glm::dvec3* pts ) noexcept;
|
||||
bool degenerate( glm::dvec3* pts );
|
||||
|
||||
//
|
||||
// Normals calculations from triangles
|
||||
//
|
||||
|
||||
/*
|
||||
* Take an array of 3D coordinates and its corresponding index set and calculates
|
||||
* the normals assuming that indices are given in CCW order.
|
||||
* Function CalcTriangleNormals
|
||||
* takes an array of 3D coordinates and its corresponding index set and calculates
|
||||
* the normals assuming that indices are given in CCW order. Care must be taken in
|
||||
* using this function to ensure that:
|
||||
* (a) all coordinates are indexed; unindexed coordinates are assigned normal(0,0,1);
|
||||
* when dealing with VRML models which may list and reuse one large coordinate set it
|
||||
* is necessary to gather all index sets and perform this operation only once.
|
||||
* (b) index sets must represent triangles (multiple of 3 indices) and must not be
|
||||
* degenerate - that is all indices and coordinates in a triad must be unique.
|
||||
*
|
||||
* Care must be taken in using this function to ensure that:
|
||||
* -# All coordinates are indexed; unindexed coordinates are assigned normal(0,0,1);
|
||||
* when dealing with VRML models which may list and reuse one large coordinate set it
|
||||
* is necessary to gather all index sets and perform this operation only once.
|
||||
* -# Index sets must represent triangles (multiple of 3 indices) and must not be
|
||||
* degenerate, that is all indices and coordinates in a triad must be unique.
|
||||
*
|
||||
* @param coords is the array of 3D vertices.
|
||||
* @param index is the array of 3x vertex indices (triads).
|
||||
* @param norms is an empty array which holds the normals corresponding to each vector.
|
||||
* @param coords is the array of 3D vertices
|
||||
* @param index is the array of 3x vertex indices (triads)
|
||||
* @param norms is an empty array which holds the normals corresponding to each vector
|
||||
* @return true on success; otherwise false.
|
||||
*/
|
||||
bool CalcTriangleNormals( std::vector< SGPOINT > coords, std::vector< int >& index,
|
||||
std::vector< SGVECTOR >& norms );
|
||||
std::vector< SGVECTOR >& norms );
|
||||
|
||||
//
|
||||
// VRML related functions
|
||||
//
|
||||
|
||||
// formats a floating point number for text output to a VRML file
|
||||
void FormatFloat( std::string& result, double value );
|
||||
@@ -250,13 +218,19 @@ namespace S3D
|
||||
// write out an RGB color
|
||||
bool WriteColor( std::ostream& aFile, const SGCOLOR& aColor );
|
||||
|
||||
//
|
||||
// Cache related READ functions
|
||||
//
|
||||
|
||||
/**
|
||||
* Read the text tag of a binary cache file which is the NodeTag and unique ID number combined.
|
||||
* Function ReadTag
|
||||
* reads the text tag of a binary cache file which is the
|
||||
* NodeTag and unique ID number combined
|
||||
*
|
||||
* @param aFile is a binary file open for reading.
|
||||
* @param aName will hold the tag name on successful return.
|
||||
* @return will be the NodeType which the tag represents or S3D::SGTYPES::SGTYPE_END on
|
||||
* failure.
|
||||
* @param aFile is a binary file open for reading
|
||||
* @param aName will hold the tag name on successful return
|
||||
* @return will be the NodeType which the tag represents or
|
||||
* S3D::SGTYPES::SGTYPE_END on failure
|
||||
*/
|
||||
S3D::SGTYPES ReadTag( std::istream& aFile, std::string& aName );
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -31,27 +30,33 @@
|
||||
|
||||
SGINDEX::SGINDEX( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGINDEX (type "
|
||||
"'%d')" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGINDEX (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGINDEX::~SGINDEX()
|
||||
{
|
||||
index.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -60,14 +65,14 @@ bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGINDEX and derived types
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -79,45 +84,65 @@ bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept
|
||||
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGINDEX::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGINDEX::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGINDEX::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGINDEX::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGINDEX::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGINDEX::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
// Node should have no children or refs.
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -128,7 +153,7 @@ bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||
if( index.empty() )
|
||||
{
|
||||
nIndices = 0;
|
||||
aIndexList = nullptr;
|
||||
aIndexList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -142,7 +167,7 @@ void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
{
|
||||
index.clear();
|
||||
|
||||
if( 0 == nIndices || nullptr == aIndexList )
|
||||
if( 0 == nIndices || NULL == aIndexList )
|
||||
return;
|
||||
|
||||
for( size_t i = 0; i < nIndices; ++i )
|
||||
@@ -155,6 +180,7 @@ void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||
void SGINDEX::AddIndex( int aIndex )
|
||||
{
|
||||
index.push_back( aIndex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,8 +210,17 @@ bool SGINDEX::writeCoordIndex( std::ostream& aFile )
|
||||
{
|
||||
size_t n = index.size();
|
||||
|
||||
wxCHECK_MSG( n % 3 == 0, false, wxT( "Coordinate index is not divisible by three (violates "
|
||||
"triangle constraint)" ) );
|
||||
if( n % 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] coord index is not divisible by three (violates triangle constraint)";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
aFile << " coordIndex [\n ";
|
||||
|
||||
@@ -261,16 +296,26 @@ bool SGINDEX::writeIndexList( std::ostream& aFile )
|
||||
|
||||
bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -279,12 +324,26 @@ bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -306,7 +365,17 @@ bool SGINDEX::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( index.empty(), false );
|
||||
if( !index.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
@@ -317,7 +386,7 @@ bool SGINDEX::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
for( size_t i = 0; i < npts; ++i )
|
||||
{
|
||||
aFile.read( (char*) &tmp, sizeof( int ) );
|
||||
aFile.read( (char*)&tmp, sizeof(int) );
|
||||
|
||||
if( aFile.fail() )
|
||||
return false;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_index.h
|
||||
* defines a generic Index interface for a scenegraph object
|
||||
*/
|
||||
|
||||
#ifndef SG_INDEX_H
|
||||
@@ -32,59 +32,8 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define a generic index interface for a scenegraph object.
|
||||
*/
|
||||
class SGINDEX : public SGNODE
|
||||
{
|
||||
public:
|
||||
SGINDEX( SGNODE* aParent );
|
||||
virtual ~SGINDEX();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char* aNodeName, const SGNODE* aCaller) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aCaller ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aCaller ) noexcept override;
|
||||
|
||||
/**
|
||||
* Retrieve the number of indices and a pointer to the list.
|
||||
*
|
||||
* @note The returned pointer may be invalidated by future operations on the SGNODE. The
|
||||
* caller must make immediate use of the data and must not rely on the pointer's
|
||||
* validity in the future.
|
||||
*
|
||||
* @param nIndices will hold the number of indices in the list.
|
||||
* @param aIndexList will store a pointer to the data.
|
||||
* @return true if there was available data (nIndices > 0) otherwise false.
|
||||
*/
|
||||
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||
|
||||
/**
|
||||
* Set the number of indices and creates a copy of the given index data.
|
||||
*
|
||||
* @param nIndices the number of indices to be stored.
|
||||
* @param aIndexList the index data.
|
||||
*/
|
||||
void SetIndices( size_t nIndices, int* aIndexList );
|
||||
|
||||
|
||||
/**
|
||||
* Add a single index to the list.
|
||||
*
|
||||
* @param aIndex is the index to add.
|
||||
*/
|
||||
void AddIndex( int aIndex );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
protected:
|
||||
bool writeCoordIndex( std::ostream& aFile );
|
||||
bool writeColorIndex( std::ostream& aFile );
|
||||
@@ -93,6 +42,56 @@ protected:
|
||||
public:
|
||||
// for internal SG consumption only
|
||||
std::vector< int > index;
|
||||
void unlinkChildNode( const SGNODE* aCaller ) override;
|
||||
void unlinkRefNode( const SGNODE* aCaller ) override;
|
||||
|
||||
public:
|
||||
SGINDEX( SGNODE* aParent );
|
||||
virtual ~SGINDEX();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
/**
|
||||
* Function GetIndices
|
||||
* retrieves the number of indices and a pointer to
|
||||
* the list. Note: the returned pointer may be invalidated
|
||||
* by future operations on the SGNODE; the caller must make
|
||||
* immediate use of the data and must not rely on the pointer's
|
||||
* validity in the future.
|
||||
*
|
||||
* @param nIndices [out] will hold the number of indices in the list
|
||||
* @param aIndexList [out] will store a pointer to the data
|
||||
* @return true if there was available data (nIndices > 0) otherwise false
|
||||
*/
|
||||
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||
|
||||
/**
|
||||
* Function SetIndices
|
||||
* sets the number of indices and creates a copy of the given index data.
|
||||
*
|
||||
* @param nIndices [in] the number of indices to be stored
|
||||
* @param aIndexList [in] the index data
|
||||
*/
|
||||
void SetIndices( size_t nIndices, int* aIndexList );
|
||||
|
||||
|
||||
/**
|
||||
* Function AddIndex
|
||||
* adds a single index to the list
|
||||
*
|
||||
* @param aIndex is the index to add
|
||||
*/
|
||||
void AddIndex( int aIndex );
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
};
|
||||
|
||||
#endif // SG_INDEX_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -32,7 +31,6 @@
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
#include "plugins/3dapi/c3dmodel.h"
|
||||
|
||||
|
||||
static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
"TXFM",
|
||||
"APP",
|
||||
@@ -50,7 +48,7 @@ static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||
static unsigned int node_counts[S3D::SGTYPE_END] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType ) noexcept
|
||||
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType )
|
||||
{
|
||||
return node_names[aType].c_str();
|
||||
}
|
||||
@@ -70,15 +68,19 @@ static void getNodeName( S3D::SGTYPES nodeType, std::string& aName )
|
||||
std::ostringstream ostr;
|
||||
ostr << node_names[nodeType] << "_" << seqNum;
|
||||
aName = ostr.str();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNODE::SGNODE( SGNODE* aParent )
|
||||
{
|
||||
m_Parent = aParent;
|
||||
m_Association = nullptr;
|
||||
m_Association = NULL;
|
||||
m_written = false;
|
||||
m_SGtype = S3D::SGTYPE_END;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +90,7 @@ SGNODE::~SGNODE()
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
if( m_Association )
|
||||
*m_Association = nullptr;
|
||||
*m_Association = NULL;
|
||||
|
||||
std::list< SGNODE* >::iterator sBP = m_BackPointers.begin();
|
||||
std::list< SGNODE* >::iterator eBP = m_BackPointers.end();
|
||||
@@ -98,16 +100,18 @@ SGNODE::~SGNODE()
|
||||
(*sBP)->unlinkRefNode( this );
|
||||
++sBP;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const noexcept
|
||||
S3D::SGTYPES SGNODE::GetNodeType( void ) const
|
||||
{
|
||||
return m_SGtype;
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNODE::GetParent( void ) const noexcept
|
||||
SGNODE* SGNODE::GetParent( void ) const
|
||||
{
|
||||
return m_Parent;
|
||||
}
|
||||
@@ -118,10 +122,10 @@ bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
if( aNewParent == m_Parent )
|
||||
return true;
|
||||
|
||||
if( nullptr == aNewParent )
|
||||
if( NULL == aNewParent )
|
||||
return false;
|
||||
|
||||
if( nullptr == m_Parent )
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
if( aNewParent->AddChildNode( this ) )
|
||||
return true;
|
||||
@@ -134,7 +138,7 @@ bool SGNODE::SwapParent( SGNODE* aNewParent )
|
||||
|
||||
SGNODE* oldParent = m_Parent;
|
||||
m_Parent->unlinkChildNode( this );
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
aNewParent->unlinkRefNode( this );
|
||||
aNewParent->AddChildNode( this );
|
||||
oldParent->AddRefNode( this );
|
||||
@@ -152,16 +156,18 @@ const char* SGNODE::GetName( void )
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::SetName( const char* aName )
|
||||
void SGNODE::SetName( const char *aName )
|
||||
{
|
||||
if( nullptr == aName || 0 == aName[0] )
|
||||
if( NULL == aName || 0 == aName[0] )
|
||||
getNodeName( m_SGtype, m_Name );
|
||||
else
|
||||
m_Name = aName;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const char* SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept
|
||||
const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||
{
|
||||
return node_names[aNodeType].c_str();
|
||||
}
|
||||
@@ -169,7 +175,7 @@ const char* SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept
|
||||
|
||||
void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
@@ -179,12 +185,13 @@ void SGNODE::addNodeRef( SGNODE* aNode )
|
||||
return;
|
||||
|
||||
m_BackPointers.push_back( aNode );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
std::list< SGNODE* >::iterator np =
|
||||
@@ -196,49 +203,110 @@ void SGNODE::delNodeRef( const SGNODE* aNode )
|
||||
return;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] delNodeRef() did not find its target, this "
|
||||
"node type %d, referenced node type %d" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
m_SGtype,
|
||||
aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] delNodeRef() did not find its target\n";
|
||||
ostr << " * This Node Type: " << m_SGtype << ", Referenced node type: ";
|
||||
ostr << aNode->GetNodeType() << "\n";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef ) noexcept
|
||||
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
wxCHECK( aWrapperRef && *aWrapperRef == this, /* void */ );
|
||||
if( NULL == aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL handle";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( *aWrapperRef != this )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] handle value does not match this object's pointer";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is an existing association then break it and emit a warning
|
||||
// just in case the behavior is undesired
|
||||
if( m_Association )
|
||||
{
|
||||
*m_Association = nullptr;
|
||||
*m_Association = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [WARNING] association being broken with "
|
||||
"previous wrapper" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [WARNING] association being broken with previous wrapper";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
m_Association = aWrapperRef;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef ) noexcept
|
||||
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef )
|
||||
{
|
||||
if( !m_Association )
|
||||
return;
|
||||
|
||||
wxCHECK( aWrapperRef, /* void */ );
|
||||
if( !aWrapperRef )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] invalid handle value aWrapperRef";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
wxCHECK( *aWrapperRef == *m_Association && aWrapperRef == m_Association, /* void */ );
|
||||
return;
|
||||
}
|
||||
|
||||
m_Association = nullptr;
|
||||
if( *aWrapperRef != *m_Association || aWrapperRef != m_Association )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] *aWrapperRef (" << *aWrapperRef;
|
||||
ostr << ") does not match *m_Association (" << *m_Association << ") in type ";
|
||||
ostr << node_names[ m_SGtype] << "\n";
|
||||
ostr << " * [INFO] OR aWrapperRef(" << aWrapperRef << ") != m_Association(";
|
||||
ostr << m_Association << ")\n";
|
||||
ostr << " * [INFO] node name: " << GetName();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_Association = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNODE::ResetNodeIndex( void ) noexcept
|
||||
void SGNODE::ResetNodeIndex( void )
|
||||
{
|
||||
for( int i = 0; i < (int)S3D::SGTYPE_END; ++i )
|
||||
node_counts[i] = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +314,28 @@ bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
{
|
||||
aIndex = 0;
|
||||
|
||||
wxCHECK( aNode && S3D::SGTYPE_APPEARANCE == aNode->GetNodeType(), false );
|
||||
if( NULL == aNode || S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
ostr.str( "" );
|
||||
|
||||
if( NULL == aNode )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, " * [BUG] aNode is NULL\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
ostr << " * [BUG] invalid node type (" << aNode->GetNodeType();
|
||||
ostr << "), expected " << S3D::SGTYPE_APPEARANCE;
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGAPPEARANCE* node = (SGAPPEARANCE*)aNode;
|
||||
|
||||
@@ -260,7 +349,7 @@ bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
|
||||
int idx = (int)aList.matorder.size();
|
||||
aList.matorder.push_back( node );
|
||||
aList.matmap.emplace( node, idx );
|
||||
aList.matmap.insert( std::pair< SGAPPEARANCE const*, int >( node, idx ) );
|
||||
aIndex = idx;
|
||||
|
||||
return true;
|
||||
@@ -269,78 +358,85 @@ bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||
|
||||
void S3D::INIT_SMATERIAL( SMATERIAL& aMaterial )
|
||||
{
|
||||
aMaterial = {};
|
||||
memset( &aMaterial, 0, sizeof( aMaterial ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_SMESH( SMESH& aMesh ) noexcept
|
||||
void S3D::INIT_SMESH( SMESH& aMesh )
|
||||
{
|
||||
aMesh = {};
|
||||
memset( &aMesh, 0, sizeof( aMesh ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel ) noexcept
|
||||
void S3D::INIT_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
aModel = {};
|
||||
memset( &aModel, 0, sizeof( aModel ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_SMESH( SMESH& aMesh ) noexcept
|
||||
void S3D::FREE_SMESH( SMESH& aMesh)
|
||||
{
|
||||
if( nullptr != aMesh.m_Positions )
|
||||
if( NULL != aMesh.m_Positions )
|
||||
{
|
||||
delete [] aMesh.m_Positions;
|
||||
aMesh.m_Positions = nullptr;
|
||||
aMesh.m_Positions = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Normals )
|
||||
if( NULL != aMesh.m_Normals )
|
||||
{
|
||||
delete [] aMesh.m_Normals;
|
||||
aMesh.m_Normals = nullptr;
|
||||
aMesh.m_Normals = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Texcoords )
|
||||
if( NULL != aMesh.m_Texcoords )
|
||||
{
|
||||
delete [] aMesh.m_Texcoords;
|
||||
aMesh.m_Texcoords = nullptr;
|
||||
aMesh.m_Texcoords = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_Color )
|
||||
if( NULL != aMesh.m_Color )
|
||||
{
|
||||
delete [] aMesh.m_Color;
|
||||
aMesh.m_Color = nullptr;
|
||||
aMesh.m_Color = NULL;
|
||||
}
|
||||
|
||||
if( nullptr != aMesh.m_FaceIdx )
|
||||
if( NULL != aMesh.m_FaceIdx )
|
||||
{
|
||||
delete [] aMesh.m_FaceIdx;
|
||||
aMesh.m_FaceIdx = nullptr;
|
||||
aMesh.m_FaceIdx = NULL;
|
||||
}
|
||||
|
||||
aMesh.m_VertexSize = 0;
|
||||
aMesh.m_FaceIdxSize = 0;
|
||||
aMesh.m_MaterialIdx = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void S3D::FREE_S3DMODEL( S3DMODEL& aModel )
|
||||
{
|
||||
if( nullptr != aModel.m_Materials )
|
||||
if( NULL != aModel.m_Materials )
|
||||
{
|
||||
delete [] aModel.m_Materials;
|
||||
aModel.m_Materials = nullptr;
|
||||
aModel.m_Materials = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MaterialsSize = 0;
|
||||
|
||||
if( nullptr != aModel.m_Meshes )
|
||||
if( NULL != aModel.m_Meshes )
|
||||
{
|
||||
for( unsigned int i = 0; i < aModel.m_MeshesSize; ++i )
|
||||
FREE_SMESH( aModel.m_Meshes[i] );
|
||||
|
||||
delete [] aModel.m_Meshes;
|
||||
aModel.m_Meshes = nullptr;
|
||||
aModel.m_Meshes = NULL;
|
||||
}
|
||||
|
||||
aModel.m_MeshesSize = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+121
-107
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_node.h
|
||||
* defines the base class of the intermediate scene graph NODE
|
||||
*/
|
||||
|
||||
|
||||
@@ -47,9 +47,10 @@ class SGAPPEARANCE;
|
||||
namespace S3D
|
||||
{
|
||||
/**
|
||||
* Return the name of the given type of node
|
||||
* Function GetNodeTypeName
|
||||
* returns the name of the given type of node
|
||||
*/
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType ) noexcept;
|
||||
char const* GetNodeTypeName( S3D::SGTYPES aType );
|
||||
|
||||
struct MATLIST
|
||||
{
|
||||
@@ -60,67 +61,129 @@ namespace S3D
|
||||
bool GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex );
|
||||
|
||||
void INIT_SMATERIAL( SMATERIAL& aMaterial );
|
||||
void INIT_SMESH( SMESH& aMesh ) noexcept;
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel ) noexcept;
|
||||
void INIT_SMESH( SMESH& aMesh );
|
||||
void INIT_S3DMODEL( S3DMODEL& aModel );
|
||||
|
||||
void FREE_SMESH( SMESH& aMesh) noexcept;
|
||||
void FREE_SMESH( SMESH& aMesh);
|
||||
void FREE_S3DMODEL( S3DMODEL& aModel );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The base class of all Scene Graph nodes.
|
||||
* Class SGNODE
|
||||
* represents the base class of all Scene Graph nodes
|
||||
*/
|
||||
class SGNODE
|
||||
{
|
||||
private:
|
||||
SGNODE** m_Association; // handle to the instance held by a wrapper
|
||||
|
||||
protected:
|
||||
std::list< SGNODE* > m_BackPointers; // nodes which hold a reference to this
|
||||
SGNODE* m_Parent; // pointer to parent node; may be NULL for top level transform
|
||||
S3D::SGTYPES m_SGtype; // type of SG node
|
||||
std::string m_Name; // name to use for referencing the entity by name
|
||||
bool m_written; // set true when the object has been written after a ReNameNodes()
|
||||
|
||||
public:
|
||||
/**
|
||||
* Function unlinkChild
|
||||
* removes references to an owned child; it is invoked by the child upon destruction
|
||||
* to ensure that the parent has no invalid references.
|
||||
*
|
||||
* @param aNode is the child which is being deleted
|
||||
*/
|
||||
virtual void unlinkChildNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function unlinkRef
|
||||
* removes pointers to a referenced node; it is invoked by the referenced node
|
||||
* upon destruction to ensure that the referring node has no invalid references.
|
||||
*
|
||||
* @param aNode is the node which is being deleted
|
||||
*/
|
||||
virtual void unlinkRefNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Function addNodeRef
|
||||
* adds a pointer to a node which references, but does not own, this node.
|
||||
* Such back-pointers are required to ensure that invalidated references
|
||||
* are removed when a node is deleted
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void addNodeRef( SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function delNodeRef
|
||||
* removes a pointer to a node which references, but does not own, this node.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object
|
||||
*/
|
||||
void delNodeRef( const SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Function IsWritten
|
||||
* returns true if the object had already been written to a
|
||||
* cache file or VRML file; for internal use only.
|
||||
*/
|
||||
bool isWritten( void )
|
||||
{
|
||||
return m_written;
|
||||
}
|
||||
|
||||
public:
|
||||
SGNODE( SGNODE* aParent );
|
||||
virtual ~SGNODE();
|
||||
|
||||
/**
|
||||
* Return the type of this node instance.
|
||||
* Function GetNodeType
|
||||
* returns the type of this node instance
|
||||
*/
|
||||
S3D::SGTYPES GetNodeType( void ) const noexcept;
|
||||
S3D::SGTYPES GetNodeType( void ) const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to the parent SGNODE of this object or NULL if the object has
|
||||
* no parent (ie. top level transform).
|
||||
* Function GetParent
|
||||
* returns a pointer to the parent SGNODE of this object
|
||||
* or NULL if the object has no parent (ie. top level transform)
|
||||
*/
|
||||
SGNODE* GetParent( void ) const noexcept;
|
||||
SGNODE* GetParent( void ) const;
|
||||
|
||||
/**
|
||||
* Set the parent #SGNODE of this object.
|
||||
* Function SetParent
|
||||
* sets the parent SGNODE of this object.
|
||||
*
|
||||
* @param aParent [in] is the desired parent node
|
||||
* @return true if the operation succeeds; false if the given node is not allowed to
|
||||
* be a parent to the derived object.
|
||||
* @return true if the operation succeeds; false if
|
||||
* the given node is not allowed to be a parent to
|
||||
* the derived object.
|
||||
*/
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) = 0;
|
||||
|
||||
/**
|
||||
* Swap the ownership with the given parent.
|
||||
* Function SwapParent
|
||||
* swaps the ownership with the given parent. This operation
|
||||
* may be required when reordering nodes for optimization.
|
||||
*
|
||||
* This operation may be required when reordering nodes for optimization.
|
||||
*
|
||||
* @param aNewParent will become the new parent to the object; it must be the same type
|
||||
* as the parent of this instance.
|
||||
* @param aNewParent [in] will become the new parent to the
|
||||
* object; it must be the same type as the parent of this
|
||||
* instance.
|
||||
*/
|
||||
bool SwapParent( SGNODE* aNewParent );
|
||||
|
||||
const char* GetName( void );
|
||||
void SetName(const char *aName);
|
||||
|
||||
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const noexcept;
|
||||
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const;
|
||||
|
||||
/**
|
||||
* Search the tree of linked nodes and return a reference to the first node found with
|
||||
* the given name.
|
||||
* Function FindNode searches the tree of linked nodes and returns a
|
||||
* reference to the first node found with the given name. The reference
|
||||
* is then typically added to another node via AddRefNode().
|
||||
*
|
||||
* The reference is then typically added to another node via AddRefNode().
|
||||
*
|
||||
* @param aNodeName is the name of the node to search for.
|
||||
* @param aCaller is a pointer to the node invoking this function.
|
||||
* @return is a valid node pointer on success, otherwise NULL.
|
||||
* @param aNodeName is the name of the node to search for
|
||||
* @param aCaller is a pointer to the node invoking this function
|
||||
* @return is a valid node pointer on success, otherwise NULL
|
||||
*/
|
||||
virtual SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) = 0;
|
||||
|
||||
@@ -129,108 +192,59 @@ public:
|
||||
virtual bool AddChildNode( SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Associate this object with a handle to itself.
|
||||
*
|
||||
* The handle is typically held by an IFSG* wrapper and the pointer which it refers to
|
||||
* is set to NULL upon destruction of this object. This mechanism provides a scheme
|
||||
* by which a wrapper can be notified of the destruction of the object which it wraps.
|
||||
* Function AssociateWrapper
|
||||
* associates this object with a handle to itself; this handle
|
||||
* is typically held by an IFSG* wrapper and the pointer which
|
||||
* it refers to is set to NULL upon destruction of this object.
|
||||
* This mechanism provides a scheme by which a wrapper can be
|
||||
* notified of the destruction of the object which it wraps.
|
||||
*/
|
||||
void AssociateWrapper( SGNODE** aWrapperRef ) noexcept;
|
||||
void AssociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Remove the association between an IFSG* wrapper object and this object.
|
||||
* Function DisassociateWrapper
|
||||
* removes the association between an IFSG* wrapper
|
||||
* object and this object.
|
||||
*/
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef ) noexcept;
|
||||
void DisassociateWrapper( SGNODE** aWrapperRef );
|
||||
|
||||
/**
|
||||
* Reset the global SG* node indices in preparation for write operations.
|
||||
* Function ResetNodeIndex
|
||||
* resets the global SG* node indices in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
void ResetNodeIndex( void ) noexcept;
|
||||
void ResetNodeIndex( void );
|
||||
|
||||
/**
|
||||
* Rename a node and all its child nodes in preparation for write operations.
|
||||
* Function ReNameNodes
|
||||
* renames a node and all its child nodes in preparation for
|
||||
* Write() operations
|
||||
*/
|
||||
virtual void ReNameNodes( void ) = 0;
|
||||
|
||||
/**
|
||||
* Writes this node's data to a VRML file.
|
||||
*
|
||||
* This includes all data of child and referenced nodes.
|
||||
* Function WriteVRML
|
||||
* writes this node's data to a VRML file; this includes
|
||||
* all data of child and referenced nodes.
|
||||
*/
|
||||
virtual bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) = 0;
|
||||
|
||||
/**
|
||||
* Write this node's data to a binary cache file.
|
||||
*
|
||||
* The data includes all data of children and references to children. If this function
|
||||
* is invoked by the user, parentNode must be set to NULL in order to ensure coherent data.
|
||||
* Function WriteCache
|
||||
* write's this node's data to a binary cache file; the data
|
||||
* includes all data of children and references to children.
|
||||
* If this function is invoked by the user, parentNode must be
|
||||
* set to NULL in order to ensure coherent data.
|
||||
*/
|
||||
virtual bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) = 0;
|
||||
|
||||
/**
|
||||
* Reads binary format data from a cache file.
|
||||
*
|
||||
* To read a cache file, open the file for reading and invoke this function from a new
|
||||
* #SCENEGRAPH node.
|
||||
* Function ReadCache
|
||||
* Reads binary format data from a cache file. To read a cache file,
|
||||
* open the file for reading and invoke this function from a new
|
||||
* SCENEGRAPH node.
|
||||
*/
|
||||
virtual bool ReadCache( std::istream& aFile, SGNODE* parentNode ) = 0;
|
||||
|
||||
/**
|
||||
* Remove references to an owned child.
|
||||
*
|
||||
* This is invoked by the child upon destruction to ensure that the parent has no
|
||||
* invalid references.
|
||||
*
|
||||
* @param aNode is the child which is being deleted.
|
||||
*/
|
||||
virtual void unlinkChildNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Remove pointers to a referenced node.
|
||||
*
|
||||
* This is invoked by the referenced node upon destruction to ensure that the referring
|
||||
* node has no invalid references.
|
||||
*
|
||||
* @param aNode is the node which is being deleted.
|
||||
*/
|
||||
virtual void unlinkRefNode( const SGNODE* aNode ) = 0;
|
||||
|
||||
/**
|
||||
* Add a pointer to a node which references this node, but does not own.
|
||||
*
|
||||
* Such back-pointers are required to ensure that invalidated references are removed
|
||||
* when a node is deleted.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object.
|
||||
*/
|
||||
void addNodeRef( SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Remove a pointer to a node which references this node, but does not own.
|
||||
*
|
||||
* @param aNode is the node holding a reference to this object.
|
||||
*/
|
||||
void delNodeRef( const SGNODE* aNode );
|
||||
|
||||
/**
|
||||
* Return true if the object had already been written to a cache file or VRML file
|
||||
*
|
||||
* For internal use only.
|
||||
*/
|
||||
bool isWritten( void ) noexcept
|
||||
{
|
||||
return m_written;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::list< SGNODE* > m_BackPointers; ///< nodes which hold a reference to this.
|
||||
SGNODE* m_Parent; ///< Pointer to parent node; may be NULL for top level transform.
|
||||
S3D::SGTYPES m_SGtype; ///< Type of Scene Graph node.
|
||||
std::string m_Name; ///< name to use for referencing the entity by name.
|
||||
bool m_written; ///< Set to true when the object has been written after a ReNameNodes().
|
||||
|
||||
private:
|
||||
SGNODE** m_Association; ///< Handle to the instance held by a wrapper.
|
||||
};
|
||||
|
||||
#endif // SG_NODE_H
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -34,31 +33,37 @@ SGNORMALS::SGNORMALS( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_NORMALS;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGNORMALS "
|
||||
"(type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGNORMALS (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SGNORMALS::~SGNORMALS()
|
||||
{
|
||||
norms.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -67,14 +72,14 @@ bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGFACESET may be parent to a SGNORMALS
|
||||
if( nullptr != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -86,41 +91,65 @@ bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGNORMALS::FindNode( const char* aNodeName, const SGNODE* aCaller ) noexcept
|
||||
SGNODE* SGNORMALS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller ) noexcept
|
||||
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller ) noexcept
|
||||
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller )
|
||||
{
|
||||
wxCHECK( false, /* void */ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unexpected code branch; node should have no children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddRefNode( SGNODE* aNode ) noexcept
|
||||
bool SGNORMALS::AddRefNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SGNORMALS::AddChildNode( SGNODE* aNode ) noexcept
|
||||
bool SGNORMALS::AddChildNode( SGNODE* aNode )
|
||||
{
|
||||
wxCHECK( false, false );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] this node does not accept children or refs";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -131,7 +160,7 @@ bool SGNORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||
if( norms.empty() )
|
||||
{
|
||||
aListSize = 0;
|
||||
aNormalList = nullptr;
|
||||
aNormalList = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -145,23 +174,27 @@ void SGNORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||
{
|
||||
norms.clear();
|
||||
|
||||
if( 0 == aListSize || nullptr == aNormalList )
|
||||
if( 0 == aListSize || NULL == aNormalList )
|
||||
return;
|
||||
|
||||
for( int i = 0; i < (int)aListSize; ++i )
|
||||
norms.push_back( aNormalList[i] );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||
{
|
||||
norms.emplace_back( aXValue, aYValue, aZValue );
|
||||
norms.push_back( SGVECTOR( aXValue, aYValue, aZValue ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGNORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||
{
|
||||
norms.push_back( aNormal );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,16 +266,26 @@ bool SGNORMALS::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -251,12 +294,26 @@ bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -278,10 +335,20 @@ bool SGNORMALS::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGNORMALS::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( norms.empty(), false );
|
||||
if( !norms.empty() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t npts;
|
||||
aFile.read( (char*) &npts, sizeof( size_t ) );
|
||||
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||
SGVECTOR tmp;
|
||||
|
||||
if( aFile.fail() )
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_normals.h
|
||||
* defines a set of vertex normals for a scene graph object
|
||||
*/
|
||||
|
||||
#ifndef SG_NORMALS_H
|
||||
@@ -32,20 +32,23 @@
|
||||
#include <vector>
|
||||
#include "3d_cache/sg/sg_node.h"
|
||||
|
||||
/**
|
||||
* Define a set of vertex normals for a scene graph object
|
||||
*/
|
||||
class SGNORMALS : public SGNODE
|
||||
{
|
||||
public:
|
||||
std::vector< SGVECTOR > norms;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGNORMALS( SGNODE* aParent );
|
||||
virtual ~SGNORMALS();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode( const char* aNodeName, const SGNODE* aCaller ) noexcept override;
|
||||
bool AddRefNode( SGNODE* aNode ) noexcept override;
|
||||
bool AddChildNode( SGNODE* aNode ) noexcept override;
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
bool GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList );
|
||||
void SetNormalList( size_t aListSize, const SGVECTOR* aNormalList );
|
||||
@@ -57,11 +60,6 @@ public:
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) noexcept override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) noexcept override;
|
||||
|
||||
std::vector< SGVECTOR > norms;
|
||||
};
|
||||
|
||||
#endif // SG_NORMALS_H
|
||||
|
||||
+249
-132
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -40,22 +39,29 @@
|
||||
SGSHAPE::SGSHAPE( SGNODE* aParent ) : SGNODE( aParent )
|
||||
{
|
||||
m_SGtype = S3D::SGTYPE_SHAPE;
|
||||
m_Appearance = nullptr;
|
||||
m_RAppearance = nullptr;
|
||||
m_FaceSet = nullptr;
|
||||
m_RFaceSet = nullptr;
|
||||
m_Appearance = NULL;
|
||||
m_RAppearance = NULL;
|
||||
m_FaceSet = NULL;
|
||||
m_RFaceSet = NULL;
|
||||
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGSHAPE (type %d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] inappropriate parent to SGSHAPE (type ";
|
||||
ostr << aParent->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
}
|
||||
else if( nullptr != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||
{
|
||||
m_Parent->AddChildNode( this );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,35 +71,37 @@ SGSHAPE::~SGSHAPE()
|
||||
if( m_RAppearance )
|
||||
{
|
||||
m_RAppearance->delNodeRef( this );
|
||||
m_RAppearance = nullptr;
|
||||
m_RAppearance = NULL;
|
||||
}
|
||||
|
||||
if( m_RFaceSet )
|
||||
{
|
||||
m_RFaceSet->delNodeRef( this );
|
||||
m_RFaceSet = nullptr;
|
||||
m_RFaceSet = NULL;
|
||||
}
|
||||
|
||||
// delete objects
|
||||
if( m_Appearance )
|
||||
{
|
||||
m_Appearance->SetParent( nullptr, false );
|
||||
m_Appearance->SetParent( NULL, false );
|
||||
delete m_Appearance;
|
||||
m_Appearance = nullptr;
|
||||
m_Appearance = NULL;
|
||||
}
|
||||
|
||||
if( m_FaceSet )
|
||||
{
|
||||
m_FaceSet->SetParent( nullptr, false );
|
||||
m_FaceSet->SetParent( NULL, false );
|
||||
delete m_FaceSet;
|
||||
m_FaceSet = nullptr;
|
||||
m_FaceSet = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
{
|
||||
if( nullptr != m_Parent )
|
||||
if( NULL != m_Parent )
|
||||
{
|
||||
if( aParent == m_Parent )
|
||||
return true;
|
||||
@@ -102,14 +110,14 @@ bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
if( notify )
|
||||
m_Parent->unlinkChildNode( this );
|
||||
|
||||
m_Parent = nullptr;
|
||||
m_Parent = NULL;
|
||||
|
||||
if( nullptr == aParent )
|
||||
if( NULL == aParent )
|
||||
return true;
|
||||
}
|
||||
|
||||
// only a SGTRANSFORM may be parent to a SGSHAPE
|
||||
if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||
return false;
|
||||
|
||||
m_Parent = aParent;
|
||||
@@ -121,17 +129,17 @@ bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||
}
|
||||
|
||||
|
||||
SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
SGNODE* SGSHAPE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||
{
|
||||
if( nullptr == aNodeName || 0 == aNodeName[0] )
|
||||
return nullptr;
|
||||
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||
return NULL;
|
||||
|
||||
if( !m_Name.compare( aNodeName ) )
|
||||
return this;
|
||||
|
||||
SGNODE* tmp = nullptr;
|
||||
SGNODE* tmp = NULL;
|
||||
|
||||
if( nullptr != m_Appearance )
|
||||
if( NULL != m_Appearance )
|
||||
{
|
||||
tmp = m_Appearance->FindNode( aNodeName, this );
|
||||
|
||||
@@ -141,7 +149,7 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
}
|
||||
}
|
||||
|
||||
if( nullptr != m_FaceSet )
|
||||
if( NULL != m_FaceSet )
|
||||
{
|
||||
tmp = m_FaceSet->FindNode( aNodeName, this );
|
||||
|
||||
@@ -152,8 +160,8 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
}
|
||||
|
||||
// query the parent if appropriate
|
||||
if( aCaller == m_Parent || nullptr == m_Parent )
|
||||
return nullptr;
|
||||
if( aCaller == m_Parent || NULL == m_Parent )
|
||||
return NULL;
|
||||
|
||||
return m_Parent->FindNode( aNodeName, this );
|
||||
}
|
||||
@@ -161,20 +169,20 @@ SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
|
||||
|
||||
void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( nullptr == aNode )
|
||||
if( NULL == aNode )
|
||||
return;
|
||||
|
||||
if( isChild )
|
||||
{
|
||||
if( aNode == m_Appearance )
|
||||
{
|
||||
m_Appearance = nullptr;
|
||||
m_Appearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_FaceSet )
|
||||
{
|
||||
m_FaceSet = nullptr;
|
||||
m_FaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -183,38 +191,58 @@ void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||
if( aNode == m_RAppearance )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RAppearance = nullptr;
|
||||
m_RAppearance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if( aNode == m_RFaceSet )
|
||||
{
|
||||
delNodeRef( this );
|
||||
m_RFaceSet = nullptr;
|
||||
m_RFaceSet = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] unlinkNode() did not find its target";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkChildNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, true );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SGSHAPE::unlinkRefNode( const SGNODE* aNode )
|
||||
{
|
||||
unlinkNode( aNode, false );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
wxCHECK( aNode, false );
|
||||
if( NULL == aNode )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] NULL pointer passed for aNode";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE == aNode->GetNodeType() )
|
||||
{
|
||||
@@ -222,9 +250,12 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_Appearance && aNode != m_RAppearance )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Appearance "
|
||||
"nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple Appearance nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -252,8 +283,12 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
{
|
||||
if( aNode != m_FaceSet && aNode != m_RFaceSet )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple FaceSet nodes" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] assigning multiple FaceSet nodes";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -275,9 +310,15 @@ bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||
return true;
|
||||
}
|
||||
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] object %s is not a valid type for this "
|
||||
"object (%d)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, aNode->GetName(), aNode->GetNodeType() );
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] object '" << aNode->GetName();
|
||||
ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
} while( 0 );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -310,12 +351,15 @@ void SGSHAPE::ReNameNodes( void )
|
||||
// rename FaceSet
|
||||
if( m_FaceSet )
|
||||
m_FaceSet->ReNameNodes();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
{
|
||||
if( !m_Appearance && !m_RAppearance && !m_FaceSet && !m_RFaceSet )
|
||||
if( !m_Appearance && !m_RAppearance
|
||||
&& !m_FaceSet && !m_RFaceSet )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -358,16 +402,26 @@ bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
|
||||
|
||||
bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( nullptr == parentNode )
|
||||
if( NULL == parentNode )
|
||||
{
|
||||
wxCHECK( m_Parent, false );
|
||||
if( NULL == m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; m_aParent is NULL";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SGNODE* np = m_Parent;
|
||||
|
||||
while( nullptr != np->GetParent() )
|
||||
while( NULL != np->GetParent() )
|
||||
np = np->GetParent();
|
||||
|
||||
if( np->WriteCache( aFile, nullptr ) )
|
||||
if( np->WriteCache( aFile, NULL ) )
|
||||
{
|
||||
m_written = true;
|
||||
return true;
|
||||
@@ -376,21 +430,35 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
return false;
|
||||
}
|
||||
|
||||
wxCHECK( parentNode == m_Parent, false );
|
||||
if( parentNode != m_Parent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] corrupt data; parentNode != m_aParent";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !aFile.good() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] bad stream" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad stream";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if any references are unwritten and swap parents if so
|
||||
if( nullptr != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
if( NULL != m_RAppearance && !m_RAppearance->isWritten() )
|
||||
m_RAppearance->SwapParent(this);
|
||||
|
||||
if( nullptr != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
if( NULL != m_RFaceSet && !m_RFaceSet->isWritten() )
|
||||
m_RFaceSet->SwapParent( this );
|
||||
|
||||
aFile << "[" << GetName() << "]";
|
||||
@@ -402,23 +470,19 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
items[i] = 0;
|
||||
|
||||
i = 0;
|
||||
|
||||
if( nullptr != m_Appearance )
|
||||
if( NULL != m_Appearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_RAppearance )
|
||||
if( NULL != m_RAppearance )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_FaceSet )
|
||||
if( NULL != m_FaceSet )
|
||||
items[i] = true;
|
||||
|
||||
++i;
|
||||
|
||||
if( nullptr != m_RFaceSet )
|
||||
if( NULL != m_RFaceSet )
|
||||
items[i] = true;
|
||||
|
||||
for( int jj = 0; jj < NITEMS; ++jj )
|
||||
@@ -446,8 +510,17 @@ bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
|
||||
|
||||
bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
wxCHECK( m_Appearance == nullptr && m_RAppearance == nullptr && m_FaceSet == nullptr &&
|
||||
m_RFaceSet == nullptr, false );
|
||||
if( m_Appearance || m_RAppearance || m_FaceSet || m_RFaceSet )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [BUG] non-empty node";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define NITEMS 4
|
||||
bool items[NITEMS];
|
||||
@@ -457,10 +530,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; multiple item definitions "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; multiple item definitions at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -471,10 +547,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child appearance "
|
||||
"tag at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child apperance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -484,9 +563,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_Appearance->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading appearance "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -496,10 +579,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref appearance tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref appearance tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -508,20 +594,26 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref "
|
||||
"appearance '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref appearance '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_APPEARANCE != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not "
|
||||
"SGAPPEARANCE '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGAPPEARANCE '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -534,10 +626,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child face set tag "
|
||||
"at position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad child face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -547,9 +642,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !m_FaceSet->ReadCache( aFile, this ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading face set "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data while reading face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -559,10 +658,13 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
{
|
||||
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref face set tag at "
|
||||
"position %ul" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
static_cast<unsigned long>( aFile.tellg() ) );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data; bad ref face set tag at position ";
|
||||
ostr << aFile.tellg();
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -571,20 +673,26 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
|
||||
if( !np )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref face "
|
||||
"set '%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: cannot find ref face set '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( S3D::SGTYPE_FACESET != np->GetNodeType() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGFACESET "
|
||||
"'%s'" ),
|
||||
__FILE__, __FUNCTION__, __LINE__,
|
||||
name );
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] corrupt data: type is not SGFACESET '";
|
||||
ostr << name << "'";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -600,8 +708,8 @@ bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
|
||||
}
|
||||
|
||||
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes )
|
||||
bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||
{
|
||||
SMESH m;
|
||||
S3D::INIT_SMESH( m );
|
||||
@@ -609,25 +717,28 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
SGAPPEARANCE* pa = m_Appearance;
|
||||
SGFACESET* pf = m_FaceSet;
|
||||
|
||||
if( nullptr == pa )
|
||||
if( NULL == pa )
|
||||
pa = m_RAppearance;
|
||||
|
||||
if( nullptr == pf )
|
||||
if( NULL == pf )
|
||||
pf = m_RFaceSet;
|
||||
|
||||
// no face sets = nothing to render, which is valid though pointless
|
||||
if( nullptr == pf )
|
||||
if( NULL == pf )
|
||||
return true;
|
||||
|
||||
if( !pf->validate() )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; inconsistent data" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; inconsistent data";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
if( nullptr == pa )
|
||||
if( NULL == pa )
|
||||
{
|
||||
m.m_MaterialIdx = 0;
|
||||
}
|
||||
@@ -650,22 +761,22 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
SGCOORDINDEX* vidx = pf->m_CoordIndices;
|
||||
SGNORMALS* pn = pf->m_Normals;
|
||||
|
||||
if( nullptr == pc )
|
||||
if( NULL == pc )
|
||||
pc = pf->m_RColors;
|
||||
|
||||
if( nullptr == pv )
|
||||
if( NULL == pv )
|
||||
pv = pf->m_RCoords;
|
||||
|
||||
if( nullptr == pn )
|
||||
if( NULL == pn )
|
||||
pn = pf->m_RNormals;
|
||||
|
||||
// set the vertex points and indices
|
||||
size_t nCoords = 0;
|
||||
SGPOINT* pCoords = nullptr;
|
||||
SGPOINT* pCoords = NULL;
|
||||
pv->GetCoordsList( nCoords, pCoords );
|
||||
|
||||
size_t nColors = 0;
|
||||
SGCOLOR* pColors = nullptr;
|
||||
SGCOLOR* pColors = NULL;
|
||||
|
||||
if( pc )
|
||||
{
|
||||
@@ -674,18 +785,20 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
if( nColors < nCoords )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough colors per "
|
||||
"vertex (%ul vs %ul)" ),
|
||||
__FILE__, __FUNCTION__, __LINE__, static_cast<unsigned long>( nColors ),
|
||||
static_cast<unsigned long>( nCoords ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough colors per vertex (";
|
||||
ostr << nColors << " vs " << nCoords << ")";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// set the vertex indices
|
||||
size_t nvidx = 0;
|
||||
int* lv = nullptr;
|
||||
int* lv = NULL;
|
||||
vidx->GetIndices( nvidx, lv );
|
||||
|
||||
// note: reduce the vertex set to include only the referenced vertices
|
||||
@@ -699,21 +812,24 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
if( mit == indexmap.end() )
|
||||
{
|
||||
indexmap.emplace( lv[i], vertices.size() );
|
||||
indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) );
|
||||
vertices.push_back( lv[i] );
|
||||
}
|
||||
}
|
||||
|
||||
if( vertices.size() < 3 )
|
||||
{
|
||||
wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough vertices" ),
|
||||
__FILE__, __FUNCTION__, __LINE__ );
|
||||
|
||||
#ifdef DEBUG
|
||||
std::ostringstream ostr;
|
||||
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||
ostr << " * [INFO] bad model; not enough vertices";
|
||||
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// construct the final vertex/color list
|
||||
SFVEC3F* lColors = nullptr;
|
||||
SFVEC3F* lColors = NULL;
|
||||
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
|
||||
int ti;
|
||||
|
||||
@@ -723,6 +839,7 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
m.m_Color = lColors;
|
||||
}
|
||||
|
||||
|
||||
if( pc )
|
||||
{
|
||||
for( size_t i = 0; i < vertices.size(); ++i )
|
||||
@@ -760,7 +877,7 @@ bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
|
||||
// set the per-vertex normals
|
||||
size_t nNorms = 0;
|
||||
SGVECTOR* pNorms = nullptr;
|
||||
SGVECTOR* pNorms = NULL;
|
||||
double x, y, z;
|
||||
|
||||
pn->GetNormalList( nNorms, pNorms );
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
* Copyright The 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
|
||||
@@ -24,6 +23,7 @@
|
||||
|
||||
/**
|
||||
* @file sg_shape.h
|
||||
* defines a complex 3D shape for a scenegraph object
|
||||
*/
|
||||
|
||||
|
||||
@@ -36,33 +36,8 @@
|
||||
class SGAPPEARANCE;
|
||||
class SGFACESET;
|
||||
|
||||
/**
|
||||
* Define a complex 3D shape for a scenegraph object.
|
||||
*/
|
||||
class SGSHAPE : public SGNODE
|
||||
{
|
||||
public:
|
||||
SGSHAPE( SGNODE* aParent );
|
||||
virtual ~SGSHAPE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char* aNodeName, const SGNODE* aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
|
||||
std::vector< SMESH >& meshes );
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
private:
|
||||
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||
bool addNode( SGNODE* aNode, bool isChild );
|
||||
@@ -75,6 +50,28 @@ public:
|
||||
// referenced nodes
|
||||
SGAPPEARANCE* m_RAppearance;
|
||||
SGFACESET* m_RFaceSet;
|
||||
|
||||
void unlinkChildNode( const SGNODE* aNode ) override;
|
||||
void unlinkRefNode( const SGNODE* aNode ) override;
|
||||
|
||||
public:
|
||||
SGSHAPE( SGNODE* aParent );
|
||||
virtual ~SGSHAPE();
|
||||
|
||||
virtual bool SetParent( SGNODE* aParent, bool notify = true ) override;
|
||||
|
||||
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller) override;
|
||||
bool AddRefNode( SGNODE* aNode ) override;
|
||||
bool AddChildNode( SGNODE* aNode ) override;
|
||||
|
||||
void ReNameNodes( void ) override;
|
||||
bool WriteVRML( std::ostream& aFile, bool aReuseFlag ) override;
|
||||
|
||||
bool WriteCache( std::ostream& aFile, SGNODE* parentNode ) override;
|
||||
bool ReadCache( std::istream& aFile, SGNODE* parentNode ) override;
|
||||
|
||||
bool Prepare( const glm::dmat4* aTransform,
|
||||
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file str_rsort.h
|
||||
* provides a wxString sorting functino which works from the
|
||||
* end of the string towards the beginning
|
||||
*/
|
||||
|
||||
#ifndef STR_RSORT_H
|
||||
#define STR_RSORT_H
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
namespace S3D
|
||||
{
|
||||
|
||||
struct rsort_wxString
|
||||
{
|
||||
bool operator() (const wxString& strA, const wxString& strB ) const
|
||||
{
|
||||
// sort a wxString using the reverse character order; for 3d model
|
||||
// filenames this will typically be a much faster operation than
|
||||
// a normal alphabetic sort
|
||||
wxString::const_reverse_iterator sA = strA.rbegin();
|
||||
wxString::const_reverse_iterator eA = strA.rend();
|
||||
|
||||
wxString::const_reverse_iterator sB = strB.rbegin();
|
||||
wxString::const_reverse_iterator eB = strB.rend();
|
||||
|
||||
if( strA.empty() )
|
||||
{
|
||||
if( strB.empty() )
|
||||
return false;
|
||||
|
||||
// note: this rule implies that a null string is first in the sort order
|
||||
return true;
|
||||
}
|
||||
|
||||
if( strB.empty() )
|
||||
return false;
|
||||
|
||||
while( sA != eA && sB != eB )
|
||||
{
|
||||
if( (*sA) == (*sB) )
|
||||
{
|
||||
++sA;
|
||||
++sB;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (*sA) < (*sB) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if( sB == eB )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end NAMESPACE
|
||||
|
||||
#endif // STR_RSORT_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,537 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 2023 CERN
|
||||
* Copyright The 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef BOARD_ADAPTER_H
|
||||
#define BOARD_ADAPTER_H
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "../3d_rendering/raytracing/accelerators/container_2d.h"
|
||||
#include "../3d_rendering/raytracing/accelerators/container_3d.h"
|
||||
#include "../3d_rendering/raytracing/shapes3D/bbox_3d.h"
|
||||
#include <gal/3d/camera.h>
|
||||
#include <3d_enums.h>
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include "../common_ogl/ogl_attr_list.h"
|
||||
#include "../3d_viewer/eda_3d_viewer_settings.h"
|
||||
|
||||
#include <layer_ids.h>
|
||||
#include <pad.h>
|
||||
#include <pcb_track.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <pcb_text.h>
|
||||
#include <pcb_textbox.h>
|
||||
#include <pcb_table.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <pcb_dimension.h>
|
||||
#include <zone.h>
|
||||
#include <footprint.h>
|
||||
#include <reporter.h>
|
||||
#include <dialogs/dialog_color_picker.h>
|
||||
|
||||
class COLOR_SETTINGS;
|
||||
class PCB_TEXTBOX;
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map<PCB_LAYER_ID, BVH_CONTAINER_2D*> MAP_CONTAINER_2D_BASE;
|
||||
|
||||
/// A type that stores polysets for each layer id
|
||||
typedef std::map<PCB_LAYER_ID, SHAPE_POLY_SET*> MAP_POLY;
|
||||
|
||||
/// This defines the range that all coord will have to be rendered.
|
||||
/// It will use this value to convert to a normalized value between
|
||||
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to handle information needed to display 3D board.
|
||||
*/
|
||||
class BOARD_ADAPTER
|
||||
{
|
||||
public:
|
||||
BOARD_ADAPTER();
|
||||
|
||||
~BOARD_ADAPTER();
|
||||
|
||||
/**
|
||||
* Update the cache manager pointer.
|
||||
*
|
||||
* @param aCachePointer: the pointer to the 3D cache manager.
|
||||
*/
|
||||
void Set3dCacheManager( S3D_CACHE* aCacheMgr ) noexcept { m_3dModelManager = aCacheMgr; }
|
||||
S3D_CACHE* Get3dCacheManager() const noexcept { return m_3dModelManager; }
|
||||
|
||||
/**
|
||||
* Check if a layer is enabled.
|
||||
*
|
||||
* @param aLayer layer ID to get status.
|
||||
*/
|
||||
bool Is3dLayerEnabled( PCB_LAYER_ID aLayer,
|
||||
const std::bitset<LAYER_3D_END>& aVisibilityFlags ) const;
|
||||
|
||||
/**
|
||||
* Test if footprint should be displayed in relation to attributes and the flags.
|
||||
*/
|
||||
bool IsFootprintShown( FOOTPRINT_ATTR_T aFPAttributes ) const;
|
||||
|
||||
/**
|
||||
* Set current board to be rendered.
|
||||
*
|
||||
* @param aBoard board to process.
|
||||
*/
|
||||
void SetBoard( BOARD* aBoard ) noexcept { m_board = aBoard; }
|
||||
const BOARD* GetBoard() const noexcept { return m_board; }
|
||||
|
||||
void ReloadColorSettings() noexcept;
|
||||
|
||||
/**
|
||||
* Build a color list which is used to store colors layers
|
||||
*/
|
||||
std::map<int, COLOR4D> GetLayerColors() const;
|
||||
|
||||
/**
|
||||
* Build the copper color list used by the board editor, and store it in m_BoardEditorColors
|
||||
*/
|
||||
void GetBoardEditorCopperLayerColors( PCBNEW_SETTINGS* aCfg );
|
||||
|
||||
std::map<int, COLOR4D> GetDefaultColors() const;
|
||||
void SetLayerColors( const std::map<int, COLOR4D>& aColors );
|
||||
|
||||
std::bitset<LAYER_3D_END> GetVisibleLayers() const;
|
||||
std::bitset<LAYER_3D_END> GetDefaultVisibleLayers() const;
|
||||
void SetVisibleLayers( const std::bitset<LAYER_3D_END>& aLayers );
|
||||
|
||||
/**
|
||||
* Function to be called by the render when it need to reload the settings for the board.
|
||||
*
|
||||
* @param aStatusReporter the pointer for the status reporter.
|
||||
* @param aWarningReporter pointer for the warning reporter.
|
||||
*/
|
||||
void InitSettings( REPORTER* aStatusReporter, REPORTER* aWarningReporter );
|
||||
|
||||
/**
|
||||
* Board integer units To 3D units.
|
||||
*
|
||||
* @return the conversion factor to transform a position from the board to 3D units.
|
||||
*/
|
||||
double BiuTo3dUnits() const noexcept { return m_biuTo3Dunits; }
|
||||
|
||||
/**
|
||||
* Get the board outline bounding box.
|
||||
*
|
||||
* @return the board bounding box in 3D units.
|
||||
*/
|
||||
const BBOX_3D& GetBBox() const noexcept { return m_boardBoundingBox; }
|
||||
|
||||
/**
|
||||
* Get the board body thickness, including internal copper layers (in 3D units).
|
||||
*/
|
||||
float GetBoardBodyThickness() const noexcept { return m_boardBodyThickness3DU; }
|
||||
|
||||
/**
|
||||
* Get the non copper layers thickness (in 3D units).
|
||||
*/
|
||||
float GetNonCopperLayerThickness() const noexcept { return m_nonCopperLayerThickness3DU; }
|
||||
|
||||
/**
|
||||
* Get the copper layer thicknesses (in 3D units).
|
||||
*/
|
||||
float GetFrontCopperThickness() const noexcept { return m_frontCopperThickness3DU; }
|
||||
float GetBackCopperThickness() const noexcept { return m_backCopperThickness3DU; }
|
||||
|
||||
/**
|
||||
* Get the hole plating thickness (NB: in BOARD UNITS!).
|
||||
*/
|
||||
int GetHolePlatingThickness() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the board size.
|
||||
*
|
||||
* @return size in BIU units.
|
||||
*/
|
||||
VECTOR2I GetBoardSize() const noexcept { return m_boardSize; }
|
||||
|
||||
/**
|
||||
* Get the board center.
|
||||
*
|
||||
* @return position in BIU units.
|
||||
*/
|
||||
VECTOR2I GetBoardPos() const noexcept { return m_boardPos; }
|
||||
|
||||
/**
|
||||
* The board center position in 3D units.
|
||||
*
|
||||
* @return board center vector position in 3D units.
|
||||
*/
|
||||
const SFVEC3F& GetBoardCenter() const noexcept { return m_boardCenter; }
|
||||
|
||||
/**
|
||||
* Get the position of the footprint in 3d integer units considering if it is flipped or not.
|
||||
*
|
||||
* @param aIsFlipped true for use in footprints on Front (top) layer, false
|
||||
* if footprint is on back (bottom) layer.
|
||||
* @return the Z position of 3D shapes, in 3D integer units.
|
||||
*/
|
||||
float GetFootprintZPos( bool aIsFlipped ) const ;
|
||||
|
||||
/**
|
||||
* Get the current polygon of the epoxy board.
|
||||
*
|
||||
* @return the shape polygon
|
||||
*/
|
||||
const SHAPE_POLY_SET& GetBoardPoly() const noexcept { return m_board_poly; }
|
||||
|
||||
/**
|
||||
* Get the technical color of a layer.
|
||||
*
|
||||
* @param aLayerId the layer to get the color information.
|
||||
* @return the color in SFVEC3F format.
|
||||
*/
|
||||
SFVEC4F GetLayerColor( PCB_LAYER_ID aLayerId ) const;
|
||||
|
||||
/**
|
||||
* Get the technical color of a layer.
|
||||
*
|
||||
* @param aItemId the item id to get the color information.
|
||||
* @return the color in SFVEC3F format.
|
||||
*/
|
||||
SFVEC4F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @param[in] aColor is the color mapped.
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC4F GetColor( const COLOR4D& aColor ) const;
|
||||
|
||||
SFVEC2F GetSphericalCoord( int i ) const;
|
||||
|
||||
/**
|
||||
* Get the top z position.
|
||||
*
|
||||
* @param aLayerId layer id.
|
||||
* @return position in 3D units.
|
||||
*/
|
||||
float GetLayerTopZPos( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
auto it = m_layerZcoordTop.find( aLayerId );
|
||||
|
||||
if( it != m_layerZcoordTop.end() )
|
||||
return it->second;
|
||||
else
|
||||
return -( m_boardBodyThickness3DU / 2.0f );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bottom z position.
|
||||
*
|
||||
* @param aLayerId layer id.
|
||||
* @return position in 3D units.
|
||||
*/
|
||||
float GetLayerBottomZPos( PCB_LAYER_ID aLayerId ) const noexcept
|
||||
{
|
||||
auto it = m_layerZcoordBottom.find( aLayerId );
|
||||
|
||||
if( it != m_layerZcoordBottom.end() )
|
||||
return it->second;
|
||||
else
|
||||
return -( m_boardBodyThickness3DU / 2.0f ) - m_backCopperThickness3DU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map of containers that have the objects per layer.
|
||||
*
|
||||
* @return the map containers of this board.
|
||||
*/
|
||||
const MAP_CONTAINER_2D_BASE& GetLayerMap() const noexcept { return m_layerMap; }
|
||||
const BVH_CONTAINER_2D* GetPlatedPadsFront() const noexcept { return m_platedPadsFront; }
|
||||
const BVH_CONTAINER_2D* GetPlatedPadsBack() const noexcept { return m_platedPadsBack; }
|
||||
const BVH_CONTAINER_2D* GetOffboardPadsFront() const noexcept { return m_offboardPadsFront; }
|
||||
const BVH_CONTAINER_2D* GetOffboardPadsBack() const noexcept { return m_offboardPadsBack; }
|
||||
|
||||
const MAP_CONTAINER_2D_BASE& GetLayerHoleMap() const noexcept { return m_layerHoleMap; }
|
||||
const BVH_CONTAINER_2D& GetTH_IDs() const noexcept { return m_TH_IDs; }
|
||||
const BVH_CONTAINER_2D& GetTH_ODs() const noexcept { return m_TH_ODs; }
|
||||
|
||||
/**
|
||||
* Get through hole outside diameter 2D polygons.
|
||||
*
|
||||
* The outside diameter 2D polygon is the hole diameter plus the plating thickness.
|
||||
*
|
||||
* @return a container with through hold outside diameter 2D polygons.
|
||||
*/
|
||||
const SHAPE_POLY_SET& GetTH_ODPolys() const noexcept
|
||||
{
|
||||
return m_TH_ODPolys;
|
||||
}
|
||||
|
||||
const BVH_CONTAINER_2D& GetViaAnnuli() const noexcept
|
||||
{
|
||||
return m_viaAnnuli;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetViaAnnuliPolys() const noexcept
|
||||
{
|
||||
return m_viaAnnuliPolys;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetNPTH_ODPolys() const noexcept
|
||||
{
|
||||
return m_NPTH_ODPolys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a container with through hole via hole outside diameters.
|
||||
*/
|
||||
const BVH_CONTAINER_2D& GetViaTH_ODs() const noexcept
|
||||
{
|
||||
return m_viaTH_ODs;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET& GetViaTH_ODPolys() const noexcept
|
||||
{
|
||||
return m_viaTH_ODPolys;
|
||||
}
|
||||
|
||||
unsigned int GetViaCount() const noexcept { return m_viaCount; }
|
||||
unsigned int GetHoleCount() const noexcept { return m_holeCount; }
|
||||
|
||||
/**
|
||||
* @return via hole average diameter dimension in 3D units.
|
||||
*/
|
||||
float GetAverageViaHoleDiameter() const noexcept { return m_averageViaHoleDiameter; }
|
||||
|
||||
/**
|
||||
* @return the average diameter of through holes in 3D units.
|
||||
*/
|
||||
float GetAverageHoleDiameter() const noexcept { return m_averageHoleDiameter; }
|
||||
|
||||
/**
|
||||
* @return average track width in 3D units.
|
||||
*/
|
||||
float GetAverageTrackWidth() const noexcept { return m_averageTrackWidth; }
|
||||
|
||||
/**
|
||||
* @param aDiameter3DU diameter in 3DU.
|
||||
* @return number of sides that should be used in a circle with \a aDiameter3DU.
|
||||
*/
|
||||
unsigned int GetCircleSegmentCount( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @param aDiameterBIU diameter in board internal units.
|
||||
* @return number of sides that should be used in circle with \a aDiameterBIU.
|
||||
*/
|
||||
unsigned int GetCircleSegmentCount( int aDiameterBIU ) const;
|
||||
|
||||
/**
|
||||
* Get map of polygon's layers.
|
||||
*
|
||||
* @return the map with polygon's layers.
|
||||
*/
|
||||
const MAP_POLY& GetPolyMap() const noexcept { return m_layers_poly; }
|
||||
|
||||
const SHAPE_POLY_SET* GetFrontPlatedPadAndGraphicPolys()
|
||||
{
|
||||
return m_frontPlatedPadAndGraphicPolys;
|
||||
}
|
||||
|
||||
const SHAPE_POLY_SET* GetBackPlatedPadAndGraphicPolys()
|
||||
{
|
||||
return m_backPlatedPadAndGraphicPolys;
|
||||
}
|
||||
|
||||
const MAP_POLY& GetHoleIdPolysMap() const noexcept { return m_layerHoleIdPolys; }
|
||||
const MAP_POLY& GetHoleOdPolysMap() const noexcept { return m_layerHoleOdPolys; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Create the board outline polygon.
|
||||
*
|
||||
* @return false if the outline could not be created
|
||||
*/
|
||||
bool createBoardPolygon( wxString* aErrorMsg );
|
||||
void createLayers( REPORTER* aStatusReporter );
|
||||
void destroyLayers();
|
||||
|
||||
// Helper functions to create the board
|
||||
void createTrackWithMargin( const PCB_TRACK* aTrack, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayer, int aMargin = 0 );
|
||||
|
||||
void createPadWithMargin( const PAD *aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayer, const VECTOR2I& aMargin ) const;
|
||||
|
||||
void createPadWithHole( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer,
|
||||
int aInflateValue );
|
||||
|
||||
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads );
|
||||
|
||||
void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
const std::bitset<LAYER_3D_END>& aVisibilityFlags );
|
||||
|
||||
void addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aDstContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addShape( const PCB_SHAPE* aShape, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner, PCB_LAYER_ID aLayer );
|
||||
|
||||
void addShape( const PCB_DIMENSION_BASE* aDimension, CONTAINER_2D_BASE* aDstContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addTable( const PCB_TABLE* aTable, CONTAINER_2D_BASE* aContainer,
|
||||
const BOARD_ITEM* aOwner );
|
||||
|
||||
void addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void createArcSegments( const VECTOR2I& aCentre, const VECTOR2I& aStart,
|
||||
const EDA_ANGLE& aArcAngle, int aCircleToSegmentsCount, int aWidth,
|
||||
CONTAINER_2D_BASE* aContainer, const BOARD_ITEM& aOwner );
|
||||
|
||||
void buildPadOutlineAsSegments( const PAD* aPad, PCB_LAYER_ID aLayer,
|
||||
CONTAINER_2D_BASE* aDstContainer, int aWidth );
|
||||
|
||||
public:
|
||||
static CUSTOM_COLORS_LIST g_SilkColors;
|
||||
static CUSTOM_COLORS_LIST g_MaskColors;
|
||||
static CUSTOM_COLORS_LIST g_PasteColors;
|
||||
static CUSTOM_COLORS_LIST g_FinishColors;
|
||||
static CUSTOM_COLORS_LIST g_BoardColors;
|
||||
|
||||
static KIGFX::COLOR4D g_DefaultBackgroundTop;
|
||||
static KIGFX::COLOR4D g_DefaultBackgroundBot;
|
||||
static KIGFX::COLOR4D g_DefaultSilkscreen;
|
||||
static KIGFX::COLOR4D g_DefaultSolderMask;
|
||||
static KIGFX::COLOR4D g_DefaultSolderPaste;
|
||||
static KIGFX::COLOR4D g_DefaultSurfaceFinish;
|
||||
static KIGFX::COLOR4D g_DefaultBoardBody;
|
||||
static KIGFX::COLOR4D g_DefaultComments;
|
||||
static KIGFX::COLOR4D g_DefaultECOs;
|
||||
|
||||
public:
|
||||
EDA_3D_VIEWER_SETTINGS* m_Cfg;
|
||||
|
||||
bool m_IsBoardView;
|
||||
bool m_MousewheelPanning;
|
||||
bool m_IsPreviewer; ///< true if we're in a 3D preview panel, false
|
||||
///< for the standard 3D viewer
|
||||
|
||||
SFVEC4F m_BgColorBot; ///< background bottom color
|
||||
SFVEC4F m_BgColorTop; ///< background top color
|
||||
SFVEC4F m_BoardBodyColor; ///< in realistic mode: FR4 board color
|
||||
SFVEC4F m_SolderMaskColorBot; ///< in realistic mode: solder mask color ( bot )
|
||||
SFVEC4F m_SolderMaskColorTop; ///< in realistic mode: solder mask color ( top )
|
||||
SFVEC4F m_SolderPasteColor; ///< in realistic mode: solder paste color
|
||||
SFVEC4F m_SilkScreenColorBot; ///< in realistic mode: SilkScreen color ( bot )
|
||||
SFVEC4F m_SilkScreenColorTop; ///< in realistic mode: SilkScreen color ( top )
|
||||
SFVEC4F m_CopperColor; ///< in realistic mode: copper color
|
||||
SFVEC4F m_UserDrawingsColor;
|
||||
SFVEC4F m_UserCommentsColor;
|
||||
SFVEC4F m_ECO1Color;
|
||||
SFVEC4F m_ECO2Color;
|
||||
|
||||
std::map<int, COLOR4D> m_ColorOverrides; ///< allows to override color scheme colors
|
||||
std::map<int, COLOR4D> m_BoardEditorColors; ///< list of colors used by the board editor
|
||||
|
||||
private:
|
||||
BOARD* m_board;
|
||||
S3D_CACHE* m_3dModelManager;
|
||||
COLOR_SETTINGS* m_colors;
|
||||
|
||||
VECTOR2I m_boardPos; ///< Board center position in board internal units.
|
||||
VECTOR2I m_boardSize; ///< Board size in board internal units.
|
||||
SFVEC3F m_boardCenter; ///< 3D center position of the board in 3D units.
|
||||
BBOX_3D m_boardBoundingBox; ///< 3D bounding box of the board in 3D units.
|
||||
|
||||
MAP_POLY m_layers_poly; ///< Amalgamated polygon contours for various types
|
||||
///< of items
|
||||
|
||||
SHAPE_POLY_SET* m_frontPlatedPadAndGraphicPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedPadAndGraphicPolys;
|
||||
SHAPE_POLY_SET* m_frontPlatedCopperPolys;
|
||||
SHAPE_POLY_SET* m_backPlatedCopperPolys;
|
||||
|
||||
MAP_POLY m_layerHoleOdPolys; ///< Hole outer diameters (per layer)
|
||||
MAP_POLY m_layerHoleIdPolys; ///< Hole inner diameters (per layer)
|
||||
|
||||
SHAPE_POLY_SET m_NPTH_ODPolys; ///< NPTH outer diameters
|
||||
SHAPE_POLY_SET m_TH_ODPolys; ///< PTH outer diameters
|
||||
SHAPE_POLY_SET m_viaTH_ODPolys; ///< Via hole outer diameters
|
||||
SHAPE_POLY_SET m_viaAnnuliPolys; ///< Via annular ring outer diameters
|
||||
|
||||
SHAPE_POLY_SET m_board_poly; ///< Board outline polygon.
|
||||
|
||||
MAP_CONTAINER_2D_BASE m_layerMap; ///< 2D elements for each layer.
|
||||
MAP_CONTAINER_2D_BASE m_layerHoleMap; ///< Holes for each layer.
|
||||
|
||||
BVH_CONTAINER_2D* m_platedPadsFront;
|
||||
BVH_CONTAINER_2D* m_platedPadsBack;
|
||||
BVH_CONTAINER_2D* m_offboardPadsFront;
|
||||
BVH_CONTAINER_2D* m_offboardPadsBack;
|
||||
|
||||
BVH_CONTAINER_2D m_TH_ODs; ///< List of PTH outer diameters
|
||||
BVH_CONTAINER_2D m_TH_IDs; ///< List of PTH inner diameters
|
||||
BVH_CONTAINER_2D m_viaAnnuli; ///< List of via annular rings
|
||||
BVH_CONTAINER_2D m_viaTH_ODs; ///< List of via hole outer diameters
|
||||
|
||||
unsigned int m_copperLayersCount;
|
||||
|
||||
double m_biuTo3Dunits; ///< Scale factor to convert board internal units
|
||||
///< to 3D units normalized between -1.0 and 1.0.
|
||||
|
||||
std::map<PCB_LAYER_ID, float> m_layerZcoordTop; ///< Top (End) Z position of each
|
||||
///< layer in 3D units.
|
||||
|
||||
std::map<PCB_LAYER_ID, float> m_layerZcoordBottom; ///< Bottom (Start) Z position of
|
||||
///< each layer in 3D units.
|
||||
|
||||
float m_frontCopperThickness3DU;
|
||||
float m_backCopperThickness3DU;
|
||||
float m_boardBodyThickness3DU;
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
float m_solderPasteLayerThickness3DU;
|
||||
|
||||
unsigned int m_trackCount;
|
||||
float m_averageTrackWidth;
|
||||
unsigned int m_viaCount;
|
||||
float m_averageViaHoleDiameter;
|
||||
unsigned int m_holeCount;
|
||||
float m_averageHoleDiameter;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable debug output for this class. Output can be turned
|
||||
* on by setting the WXTRACE environment variable to "KI_TRACE_EDA_CINFO3D_VISU". See the
|
||||
* wxWidgets documentation on wxLogTrace for more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // BOARD_ADAPTER_H
|
||||
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.cpp
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h>
|
||||
#include <class_board.h>
|
||||
#include <3d_math.h>
|
||||
#include "3d_fastmath.h"
|
||||
#include <geometry/geometry_utils.h>
|
||||
|
||||
/**
|
||||
* 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_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar *CINFO3D_VISU::m_logTrace = wxT( "KI_TRACE_EDA_CINFO3D_VISU" );
|
||||
|
||||
|
||||
CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
|
||||
CINFO3D_VISU::CINFO3D_VISU() :
|
||||
m_currentCamera( m_trackBallCamera ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::CINFO3D_VISU" ) );
|
||||
|
||||
m_board = NULL;
|
||||
m_3d_model_manager = NULL;
|
||||
m_3D_grid_type = GRID3D_NONE;
|
||||
m_drawFlags.resize( FL_LAST, false );
|
||||
|
||||
m_render_engine = RENDER_ENGINE_OPENGL_LEGACY;
|
||||
m_material_mode = MATERIAL_MODE_NORMAL;
|
||||
|
||||
m_boardPos = wxPoint();
|
||||
m_boardSize = wxSize();
|
||||
m_boardCenter = SFVEC3F( 0.0f );
|
||||
|
||||
m_boardBoudingBox.Reset();
|
||||
m_board2dBBox3DU.Reset();
|
||||
|
||||
m_layers_container2D.clear();
|
||||
m_layers_holes2D.clear();
|
||||
m_through_holes_inner.Clear();
|
||||
m_through_holes_outer.Clear();
|
||||
|
||||
m_copperLayersCount = -1;
|
||||
m_epoxyThickness3DU = 0.0f;
|
||||
m_copperThickness3DU = 0.0f;
|
||||
m_nonCopperLayerThickness3DU = 0.0f;
|
||||
m_biuTo3Dunits = 1.0;
|
||||
|
||||
m_stats_nr_tracks = 0;
|
||||
m_stats_nr_vias = 0;
|
||||
m_stats_via_med_hole_diameter = 0.0f;
|
||||
m_stats_nr_holes = 0;
|
||||
m_stats_hole_med_diameter = 0.0f;
|
||||
m_stats_track_med_width = 0.0f;
|
||||
|
||||
m_calc_seg_min_factor3DU = 0.0f;
|
||||
m_calc_seg_max_factor3DU = 0.0f;
|
||||
|
||||
|
||||
memset( m_layerZcoordTop, 0, sizeof( m_layerZcoordTop ) );
|
||||
memset( m_layerZcoordBottom, 0, sizeof( m_layerZcoordBottom ) );
|
||||
|
||||
SetFlag( FL_USE_REALISTIC_MODE, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_SHOW_BOARD_BODY, true );
|
||||
SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT, true );
|
||||
SetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL, true );
|
||||
SetFlag( FL_ZONE, true );
|
||||
SetFlag( FL_SILKSCREEN, true );
|
||||
SetFlag( FL_SOLDERMASK, true );
|
||||
|
||||
m_BgColorBot = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_BgColorTop = SFVEC3D( 0.8, 0.8, 0.9 );
|
||||
m_BoardBodyColor = SFVEC3D( 0.4, 0.4, 0.5 );
|
||||
m_SolderMaskColor = SFVEC3D( 0.1, 0.2, 0.1 );
|
||||
m_SolderPasteColor = SFVEC3D( 0.4, 0.4, 0.4 );
|
||||
m_SilkScreenColor = SFVEC3D( 0.9, 0.9, 0.9 );
|
||||
m_CopperColor = SFVEC3D( 0.75, 0.61, 0.23 );
|
||||
}
|
||||
|
||||
|
||||
CINFO3D_VISU::~CINFO3D_VISU()
|
||||
{
|
||||
destroyLayers();
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const
|
||||
{
|
||||
wxASSERT( aLayer < PCB_LAYER_ID_COUNT );
|
||||
|
||||
DISPLAY3D_FLG flg;
|
||||
|
||||
// see if layer needs to be shown
|
||||
// check the flags
|
||||
switch( aLayer )
|
||||
{
|
||||
case B_Adhes:
|
||||
case F_Adhes:
|
||||
flg = FL_ADHESIVE;
|
||||
break;
|
||||
|
||||
case B_Paste:
|
||||
case F_Paste:
|
||||
flg = FL_SOLDERPASTE;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
case F_SilkS:
|
||||
flg = FL_SILKSCREEN;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case F_Mask:
|
||||
flg = FL_SOLDERMASK;
|
||||
break;
|
||||
|
||||
case Dwgs_User:
|
||||
case Cmts_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_COMMENTS;
|
||||
break;
|
||||
|
||||
case Eco1_User:
|
||||
case Eco2_User:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
flg = FL_ECO;
|
||||
break;
|
||||
|
||||
case Edge_Cuts:
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) || GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case Margin:
|
||||
if( GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case B_Cu:
|
||||
case F_Cu:
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer ) ||
|
||||
GetFlag( FL_USE_REALISTIC_MODE );
|
||||
break;
|
||||
|
||||
default:
|
||||
// the layer is an internal copper layer, used the visibility
|
||||
if( GetFlag( FL_SHOW_BOARD_BODY ) &&
|
||||
(m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) )
|
||||
{
|
||||
// Do not render internal layers if it is overlap with the board
|
||||
// (on OpenGL render)
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_board->GetDesignSettings().IsLayerVisible( aLayer );
|
||||
}
|
||||
|
||||
// The layer has a flag, return the flag
|
||||
return GetFlag( flg );
|
||||
}
|
||||
|
||||
|
||||
bool CINFO3D_VISU::GetFlag( DISPLAY3D_FLG aFlag ) const
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
return m_drawFlags[aFlag];
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::SetFlag( DISPLAY3D_FLG aFlag, bool aState )
|
||||
{
|
||||
wxASSERT( aFlag < FL_LAST );
|
||||
|
||||
m_drawFlags[aFlag] = aState;
|
||||
}
|
||||
|
||||
bool CINFO3D_VISU::ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const
|
||||
{
|
||||
if( ( ( aModuleAttributs == MOD_DEFAULT ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_CMS) == MOD_CMS ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT ) ) ||
|
||||
( ( ( aModuleAttributs & MOD_VIRTUAL) == MOD_VIRTUAL ) &&
|
||||
GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL ) ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// !TODO: define the actual copper thickness by user
|
||||
#define COPPER_THICKNESS KiROUND( 0.035 * IU_PER_MM ) // for 35 um
|
||||
#define TECH_LAYER_THICKNESS KiROUND( 0.04 * IU_PER_MM )
|
||||
|
||||
int CINFO3D_VISU::GetCopperThicknessBIU() const
|
||||
{
|
||||
return COPPER_THICKNESS;
|
||||
}
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( float aDiameter3DU ) const
|
||||
{
|
||||
wxASSERT( aDiameter3DU > 0.0f );
|
||||
|
||||
return GetNrSegmentsCircle( (int)( aDiameter3DU / m_biuTo3Dunits ) );
|
||||
}
|
||||
|
||||
|
||||
unsigned int CINFO3D_VISU::GetNrSegmentsCircle( int aDiameterBIU ) const
|
||||
{
|
||||
wxASSERT( aDiameterBIU > 0 );
|
||||
|
||||
return GetArcToSegmentCount( aDiameterBIU / 2, ARC_HIGH_DEF, 360.0 );
|
||||
}
|
||||
|
||||
|
||||
double CINFO3D_VISU::GetCircleCorrectionFactor( int aNrSides ) const
|
||||
{
|
||||
wxASSERT( aNrSides >= 3 );
|
||||
|
||||
return GetCircletoPolyCorrectionFactor( aNrSides );
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::InitSettings( REPORTER *aStatusTextReporter )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "CINFO3D_VISU::InitSettings" ) );
|
||||
|
||||
// Calculates the board bounding box
|
||||
// First, use only the board outlines
|
||||
EDA_RECT bbbox = m_board->ComputeBoundingBox( true );
|
||||
|
||||
// If no outlines, use the board with items
|
||||
if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
|
||||
bbbox = m_board->ComputeBoundingBox( false );
|
||||
|
||||
// Gives a non null size to avoid issues in zoom / scale calculations
|
||||
if( ( bbbox.GetWidth() == 0 ) && ( bbbox.GetHeight() == 0 ) )
|
||||
bbbox.Inflate( Millimeter2iu( 10 ) );
|
||||
|
||||
m_boardSize = bbbox.GetSize();
|
||||
m_boardPos = bbbox.Centre();
|
||||
|
||||
wxASSERT( (m_boardSize.x > 0) && (m_boardSize.y > 0) );
|
||||
|
||||
m_boardPos.y = -m_boardPos.y; // The y coord is inverted in 3D viewer
|
||||
|
||||
m_copperLayersCount = m_board->GetCopperLayerCount();
|
||||
|
||||
// Ensure the board has 2 sides for 3D views, because it is hard to find
|
||||
// a *really* single side board in the true life...
|
||||
if( m_copperLayersCount < 2 )
|
||||
m_copperLayersCount = 2;
|
||||
|
||||
// Calculate the convertion to apply to all positions.
|
||||
m_biuTo3Dunits = RANGE_SCALE_3D / std::max( m_boardSize.x, m_boardSize.y );
|
||||
|
||||
m_epoxyThickness3DU = m_board->GetDesignSettings().GetBoardThickness() *
|
||||
m_biuTo3Dunits;
|
||||
|
||||
// !TODO: use value defined by user (currently use default values by ctor
|
||||
m_copperThickness3DU = COPPER_THICKNESS * m_biuTo3Dunits;
|
||||
m_nonCopperLayerThickness3DU = TECH_LAYER_THICKNESS * m_biuTo3Dunits;
|
||||
|
||||
// Init Z position of each layer
|
||||
// calculate z position for each copper layer
|
||||
// Zstart = -m_epoxyThickness / 2.0 is the z position of the back (bottom layer) (layer id = 31)
|
||||
// Zstart = +m_epoxyThickness / 2.0 is the z position of the front (top layer) (layer id = 0)
|
||||
// all unused copper layer z position are set to 0
|
||||
|
||||
// ____==__________==________==______ <- Bottom = +m_epoxyThickness / 2.0,
|
||||
// | | Top = Bottom + m_copperThickness
|
||||
// |__________________________________|
|
||||
// == == == == <- Bottom = -m_epoxyThickness / 2.0,
|
||||
// Top = Bottom - m_copperThickness
|
||||
|
||||
unsigned int layer;
|
||||
|
||||
for( layer = 0; layer < m_copperLayersCount; ++layer )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = m_epoxyThickness3DU / 2.0f -
|
||||
(m_epoxyThickness3DU * layer / (m_copperLayersCount - 1) );
|
||||
|
||||
if( layer < (m_copperLayersCount / 2) )
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] + m_copperThickness3DU;
|
||||
else
|
||||
m_layerZcoordTop[layer] = m_layerZcoordBottom[layer] - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
#define layerThicknessMargin 1.1
|
||||
const float zpos_offset = m_nonCopperLayerThickness3DU * layerThicknessMargin;
|
||||
|
||||
// Fill remaining unused copper layers and back layer zpos
|
||||
// with -m_epoxyThickness / 2.0
|
||||
for( ; layer < MAX_CU_LAYERS; layer++ )
|
||||
{
|
||||
m_layerZcoordBottom[layer] = -(m_epoxyThickness3DU / 2.0f);
|
||||
m_layerZcoordTop[layer] = -(m_epoxyThickness3DU / 2.0f) - m_copperThickness3DU;
|
||||
}
|
||||
|
||||
// This is the top of the copper layer thickness.
|
||||
const float zpos_copperTop_back = m_layerZcoordTop[B_Cu];
|
||||
const float zpos_copperTop_front = m_layerZcoordTop[F_Cu];
|
||||
|
||||
// calculate z position for each non copper layer
|
||||
// Solder mask and Solder paste have the same Z position
|
||||
for( int layer_id = MAX_CU_LAYERS; layer_id < PCB_LAYER_ID_COUNT; ++layer_id )
|
||||
{
|
||||
float zposTop;
|
||||
float zposBottom;
|
||||
|
||||
switch( layer_id )
|
||||
{
|
||||
case B_Adhes:
|
||||
zposBottom = zpos_copperTop_back - 2.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Adhes:
|
||||
zposBottom = zpos_copperTop_front + 2.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case B_Mask:
|
||||
case B_Paste:
|
||||
zposBottom = zpos_copperTop_back;
|
||||
zposTop = zpos_copperTop_back - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_Mask:
|
||||
case F_Paste:
|
||||
zposTop = zpos_copperTop_front + m_nonCopperLayerThickness3DU;
|
||||
zposBottom = zpos_copperTop_front;
|
||||
break;
|
||||
|
||||
case B_SilkS:
|
||||
zposBottom = zpos_copperTop_back - 1.0f * zpos_offset;
|
||||
zposTop = zposBottom - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
case F_SilkS:
|
||||
zposBottom = zpos_copperTop_front + 1.0f * zpos_offset;
|
||||
zposTop = zposBottom + m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
|
||||
// !TODO: review
|
||||
default:
|
||||
zposTop = zpos_copperTop_front + (layer_id - MAX_CU_LAYERS + 3.0f) * zpos_offset;
|
||||
zposBottom = zposTop - m_nonCopperLayerThickness3DU;
|
||||
break;
|
||||
}
|
||||
|
||||
m_layerZcoordTop[layer_id] = zposTop;
|
||||
m_layerZcoordBottom[layer_id] = zposBottom;
|
||||
}
|
||||
|
||||
m_boardCenter = SFVEC3F( m_boardPos.x * m_biuTo3Dunits,
|
||||
m_boardPos.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
|
||||
SFVEC3F boardSize = SFVEC3F( m_boardSize.x * m_biuTo3Dunits,
|
||||
m_boardSize.y * m_biuTo3Dunits,
|
||||
0.0f );
|
||||
boardSize /= 2.0f;
|
||||
|
||||
SFVEC3F boardMin = (m_boardCenter - boardSize);
|
||||
SFVEC3F boardMax = (m_boardCenter + boardSize);
|
||||
|
||||
boardMin.z = m_layerZcoordTop[B_Adhes];
|
||||
boardMax.z = m_layerZcoordTop[F_Adhes];
|
||||
|
||||
m_boardBoudingBox = CBBOX( boardMin, boardMax );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_startCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Build board body" ) );
|
||||
|
||||
createBoardPolygon();
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateBoardPolyTime = GetRunningMicroSecs();
|
||||
unsigned stats_startCreateLayersTime = stats_stopCreateBoardPolyTime;
|
||||
#endif
|
||||
|
||||
if( aStatusTextReporter )
|
||||
aStatusTextReporter->Report( _( "Create layers" ) );
|
||||
|
||||
createLayers( aStatusTextReporter );
|
||||
|
||||
#ifdef PRINT_STATISTICS_3D_VIEWER
|
||||
unsigned stats_stopCreateLayersTime = GetRunningMicroSecs();
|
||||
|
||||
printf( "CINFO3D_VISU::InitSettings times\n" );
|
||||
printf( " CreateBoardPoly: %.3f ms\n",
|
||||
(float)( stats_stopCreateBoardPolyTime - stats_startCreateBoardPolyTime ) / 1e3 );
|
||||
printf( " CreateLayers and holes: %.3f ms\n",
|
||||
(float)( stats_stopCreateLayersTime - stats_startCreateLayersTime ) / 1e3 );
|
||||
printf( "\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::createBoardPolygon()
|
||||
{
|
||||
m_board_poly.RemoveAllContours();
|
||||
|
||||
wxString errmsg;
|
||||
|
||||
if( !m_board->GetBoardPolygonOutlines( m_board_poly, /*allLayerHoles,*/ &errmsg ) )
|
||||
{
|
||||
errmsg.append( wxT( "\n\n" ) );
|
||||
errmsg.append( _( "Cannot determine the board outline." ) );
|
||||
wxLogMessage( errmsg );
|
||||
}
|
||||
|
||||
// Be sure the polygon is strictly simple to avoid issues.
|
||||
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
Polygon_Calc_BBox_3DU( m_board_poly, m_board2dBBox3DU, m_biuTo3Dunits );
|
||||
}
|
||||
|
||||
|
||||
float CINFO3D_VISU::GetModulesZcoord3DIU( bool aIsFlipped ) const
|
||||
{
|
||||
if( aIsFlipped )
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordBottom[B_SilkS];
|
||||
else
|
||||
return m_layerZcoordBottom[B_Paste];
|
||||
}
|
||||
else
|
||||
{
|
||||
if( GetFlag( FL_SOLDERPASTE ) )
|
||||
return m_layerZcoordTop[F_SilkS];
|
||||
else
|
||||
return m_layerZcoordTop[F_Paste];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::CameraSetType( CAMERA_TYPE aCameraType )
|
||||
{
|
||||
switch( aCameraType )
|
||||
{
|
||||
case CAMERA_TRACKBALL:
|
||||
m_currentCamera = m_trackBallCamera;
|
||||
break;
|
||||
|
||||
default:
|
||||
wxLogMessage( wxT( "CINFO3D_VISU::CameraSetType() error: unknown camera type %d" ),
|
||||
(int)aCameraType );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetLayerColor( PCB_LAYER_ID aLayerId ) const
|
||||
{
|
||||
wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
|
||||
|
||||
const COLOR4D color = m_board->Colors().GetLayerColor( aLayerId );
|
||||
|
||||
return SFVEC3F( color.r, color.g, color.b );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetItemColor( int aItemId ) const
|
||||
{
|
||||
return GetColor( m_board->Colors().GetItemColor( aItemId ) );
|
||||
}
|
||||
|
||||
|
||||
SFVEC3F CINFO3D_VISU::GetColor( COLOR4D aColor ) const
|
||||
{
|
||||
return SFVEC3F( aColor.r, aColor.g, aColor.b );
|
||||
}
|
||||
@@ -0,0 +1,680 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file cinfo3d_visu.h
|
||||
* @brief Handles data related with the board to be visualized
|
||||
*/
|
||||
|
||||
#ifndef CINFO3D_VISU_H
|
||||
#define CINFO3D_VISU_H
|
||||
|
||||
#include <vector>
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer.h"
|
||||
#include "../3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||
#include "../3d_rendering/ccamera.h"
|
||||
#include "../3d_rendering/ctrack_ball.h"
|
||||
#include "../3d_enums.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <pcb_base_frame.h>
|
||||
#include <class_pcb_text.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_dimension.h>
|
||||
#include <class_zone.h>
|
||||
#include <class_module.h>
|
||||
#include <reporter.h>
|
||||
|
||||
/// A type that stores a container of 2d objects for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, CBVHCONTAINER2D *> MAP_CONTAINER_2D;
|
||||
|
||||
/// A type that stores polysets for each layer id
|
||||
typedef std::map< PCB_LAYER_ID, SHAPE_POLY_SET *> MAP_POLY;
|
||||
|
||||
/// This defines the range that all coord will have to be rendered.
|
||||
/// It will use this value to convert to a normalized value between
|
||||
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
/**
|
||||
* Class CINFO3D_VISU
|
||||
* Helper class to handle information needed to display 3D board
|
||||
*/
|
||||
class CINFO3D_VISU
|
||||
{
|
||||
public:
|
||||
|
||||
CINFO3D_VISU();
|
||||
|
||||
~CINFO3D_VISU();
|
||||
|
||||
/**
|
||||
* @brief Set3DCacheManager - Update the Cache manager pointer
|
||||
* @param aCachePointer: the pointer to the 3d cache manager
|
||||
*/
|
||||
void Set3DCacheManager( S3D_CACHE *aCachePointer ) { m_3d_model_manager = aCachePointer; }
|
||||
|
||||
/**
|
||||
* @brief Get3DCacheManager - Return the 3d cache manager pointer
|
||||
* @return
|
||||
*/
|
||||
S3D_CACHE *Get3DCacheManager( ) const { return m_3d_model_manager; }
|
||||
|
||||
/**
|
||||
* @brief GetFlag - get a configuration status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @return true if flag is set, false if not
|
||||
*/
|
||||
bool GetFlag( DISPLAY3D_FLG aFlag ) const ;
|
||||
|
||||
/**
|
||||
* @brief SetFlag - set the status of a flag
|
||||
* @param aFlag: the flag to get the status
|
||||
* @param aState: status to set
|
||||
*/
|
||||
void SetFlag( DISPLAY3D_FLG aFlag, bool aState );
|
||||
|
||||
/**
|
||||
* @brief Is3DLayerEnabled - Check if a layer is enabled
|
||||
* @param aLayer: layer ID to get status
|
||||
* @return true if layer should be displayed, false if not
|
||||
*/
|
||||
bool Is3DLayerEnabled( PCB_LAYER_ID aLayer ) const;
|
||||
|
||||
/**
|
||||
* @brief ShouldModuleBeDisplayed - Test if module should be displayed in
|
||||
* relation to attributs and the flags
|
||||
* @return true if module should be displayed, false if not
|
||||
*/
|
||||
bool ShouldModuleBeDisplayed( MODULE_ATTR_T aModuleAttributs ) const;
|
||||
|
||||
/**
|
||||
* @brief SetBoard - Set current board to be rendered
|
||||
* @param aBoard: board to process
|
||||
*/
|
||||
void SetBoard( BOARD *aBoard ) { m_board = aBoard; }
|
||||
|
||||
/**
|
||||
* @brief GetBoard - Get current board to be rendered
|
||||
* @return BOARD pointer
|
||||
*/
|
||||
const BOARD *GetBoard() const { return m_board; }
|
||||
|
||||
/**
|
||||
* @brief InitSettings - Function to be called by the render when it need to
|
||||
* reload the settings for the board.
|
||||
* @param aStatusTextReporter: the pointer for the status reporter
|
||||
*/
|
||||
void InitSettings( REPORTER *aStatusTextReporter );
|
||||
|
||||
/**
|
||||
* @brief BiuTo3Dunits - Board integer units To 3D units
|
||||
* @return the conversion factor to transform a position from the board to 3d units
|
||||
*/
|
||||
double BiuTo3Dunits() const { return m_biuTo3Dunits; }
|
||||
|
||||
/**
|
||||
* @brief GetBBox3DU - Get the bbox of the pcb board
|
||||
* @return the board bbox in 3d units
|
||||
*/
|
||||
const CBBOX &GetBBox3DU() const { return m_boardBoudingBox; }
|
||||
|
||||
/**
|
||||
* @brief GetEpoxyThickness3DU - Get the current epoxy thickness
|
||||
* @return thickness in 3d unities
|
||||
*/
|
||||
float GetEpoxyThickness3DU() const { return m_epoxyThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetNonCopperLayerThickness3DU - Get the current non copper layers thickness
|
||||
* @return thickness in 3d unities of non copperlayers
|
||||
*/
|
||||
float GetNonCopperLayerThickness3DU() const { return m_nonCopperLayerThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThickness3DU - Get the current copper layer thickness
|
||||
* @return thickness in 3d unities of copperlayers
|
||||
*/
|
||||
float GetCopperThickness3DU() const { return m_copperThickness3DU; }
|
||||
|
||||
/**
|
||||
* @brief GetCopperThicknessBIU - Get the current copper layer thickness
|
||||
* @return thickness in board unities
|
||||
*/
|
||||
int GetCopperThicknessBIU() const;
|
||||
|
||||
/**
|
||||
* @brief GetBoardSizeBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxSize GetBoardSizeBIU() const { return m_boardSize; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPosBIU - Get the board size
|
||||
* @return size in BIU unities
|
||||
*/
|
||||
wxPoint GetBoardPosBIU() const { return m_boardPos; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardCenter - the board center position in 3d units
|
||||
* @return board center vector position in 3d units
|
||||
*/
|
||||
const SFVEC3F &GetBoardCenter3DU() const { return m_boardCenter; }
|
||||
|
||||
/**
|
||||
* @brief GetModulesZcoord3DIU - Get the position of the module in 3d integer units
|
||||
* considering if it is flipped or not.
|
||||
* @param aIsFlipped: true for use in modules on Front (top) layer, false
|
||||
* if module is on back (bottom) layer
|
||||
* @return the Z position of 3D shapes, in 3D integer units
|
||||
*/
|
||||
float GetModulesZcoord3DIU( bool aIsFlipped ) const ;
|
||||
|
||||
/**
|
||||
* @brief CameraSetType - Set the camera type to use
|
||||
* @param aCameraType: camera type to use in this canvas
|
||||
*/
|
||||
void CameraSetType( CAMERA_TYPE aCameraType );
|
||||
|
||||
/**
|
||||
* @brief CameraGet - get current camera in use
|
||||
* @return a camera
|
||||
*/
|
||||
CCAMERA &CameraGet() const { return m_currentCamera; }
|
||||
|
||||
/**
|
||||
* @brief GridGet - get the current grid
|
||||
* @return space type of the grid
|
||||
*/
|
||||
GRID3D_TYPE GridGet() const { return m_3D_grid_type; }
|
||||
|
||||
/**
|
||||
* @brief GridSet - set the current grid
|
||||
* @param aGridType = the type space of the grid
|
||||
*/
|
||||
void GridSet( GRID3D_TYPE aGridType ) { m_3D_grid_type = aGridType; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineSet
|
||||
* @param aRenderEngine = the render engine mode selected
|
||||
*/
|
||||
void RenderEngineSet( RENDER_ENGINE aRenderEngine ) { m_render_engine = aRenderEngine; }
|
||||
|
||||
/**
|
||||
* @brief RenderEngineGet
|
||||
* @return render engine on use
|
||||
*/
|
||||
RENDER_ENGINE RenderEngineGet() const { return m_render_engine; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeSet
|
||||
* @param aMaterialMode = the render material mode
|
||||
*/
|
||||
void MaterialModeSet( MATERIAL_MODE aMaterialMode ) { m_material_mode = aMaterialMode; }
|
||||
|
||||
/**
|
||||
* @brief MaterialModeGet
|
||||
* @return material rendering mode
|
||||
*/
|
||||
MATERIAL_MODE MaterialModeGet() const { return m_material_mode; }
|
||||
|
||||
/**
|
||||
* @brief GetBoardPoly - Get the current polygon of the epoxy board
|
||||
* @return the shape polygon
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetBoardPoly() const { return m_board_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerColor - get the technical color of a layer
|
||||
* @param aLayerId: the layer to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetLayerColor( PCB_LAYER_ID aLayerId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetItemColor - get the technical color of a layer
|
||||
* @param aItemId: the item id to get the color information
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetItemColor( int aItemId ) const;
|
||||
|
||||
/**
|
||||
* @brief GetColor
|
||||
* @param aColor: the color mapped
|
||||
* @return the color in SFVEC3F format
|
||||
*/
|
||||
SFVEC3F GetColor( COLOR4D aColor ) const;
|
||||
|
||||
/**
|
||||
* @brief GetLayerTopZpos3DU - Get the top z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerTopZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordTop[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetLayerBottomZpos3DU - Get the bottom z position
|
||||
* @param aLayerId: layer id
|
||||
* @return position in 3D unities
|
||||
*/
|
||||
float GetLayerBottomZpos3DU( PCB_LAYER_ID aLayerId ) const { return m_layerZcoordBottom[aLayerId]; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayers - Get the map of container that have the objects per layer
|
||||
* @return the map containers of this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayers() const { return m_layers_container2D; }
|
||||
|
||||
/**
|
||||
* @brief GetMapLayersHoles -Get the map of container that have the holes per layer
|
||||
* @return the map containers of holes from this board
|
||||
*/
|
||||
const MAP_CONTAINER_2D &GetMapLayersHoles() const { return m_layers_holes2D; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer - Get the inflated ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Outer() const { return m_through_holes_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly() const { return m_through_outer_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Outer_poly_NPTH -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Outer_poly_NPTH() const {
|
||||
return m_through_outer_holes_poly_NPTH; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Outer() const { return m_through_holes_vias_outer; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner -
|
||||
* @return a container with via THT holes only
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Vias_Inner() const { return m_through_holes_vias_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Outer_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Outer_poly() const {
|
||||
return m_through_outer_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Vias_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Vias_Inner_poly() const {
|
||||
return m_through_inner_holes_vias_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner - Get the ThroughHole container
|
||||
* @return a container with holes
|
||||
*/
|
||||
const CBVHCONTAINER2D &GetThroughHole_Inner() const { return m_through_holes_inner; }
|
||||
|
||||
/**
|
||||
* @brief GetThroughHole_Inner_poly -
|
||||
* @return
|
||||
*/
|
||||
const SHAPE_POLY_SET &GetThroughHole_Inner_poly() const { return m_through_inner_holes_poly; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Vias - Get statistics of the nr of vias
|
||||
* @return number of vias
|
||||
*/
|
||||
unsigned int GetStats_Nr_Vias() const { return m_stats_nr_vias; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Nr_Holes - Get statistics of the nr of holes
|
||||
* @return number of holes
|
||||
*/
|
||||
unsigned int GetStats_Nr_Holes() const { return m_stats_nr_holes; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Via_Hole_Diameter3DU - Average diameter of the via holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Via_Hole_Diameter3DU() const { return m_stats_via_med_hole_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Hole_Diameter3DU - Average diameter of holes
|
||||
* @return dimension in 3D units
|
||||
*/
|
||||
float GetStats_Med_Hole_Diameter3DU() const { return m_stats_hole_med_diameter; }
|
||||
|
||||
/**
|
||||
* @brief GetStats_Med_Track_Width - Average width of the tracks
|
||||
* @return dimensions in 3D units
|
||||
*/
|
||||
float GetStats_Med_Track_Width() const { return m_stats_track_med_width; }
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameter3DU: diameter in 3DU
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( float aDiameter3DU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetNrSegmentsCircle
|
||||
* @param aDiameterBIU: diameter in board internal units
|
||||
* @return number of sides that should be used in that circle
|
||||
*/
|
||||
unsigned int GetNrSegmentsCircle( int aDiameterBIU ) const;
|
||||
|
||||
/**
|
||||
* @brief GetCircleCorrectionFactor - computes a angle correction
|
||||
* factor used when creating circles
|
||||
* @param aNrSides: the number of segments sides of the circle
|
||||
* @return a factor to apply to contour creation
|
||||
*/
|
||||
double GetCircleCorrectionFactor( int aNrSides ) const;
|
||||
|
||||
/**
|
||||
* @brief GetPolyMap - Get maps of polygons's layers
|
||||
* @return the map with polygons's layers
|
||||
*/
|
||||
const MAP_POLY &GetPolyMap() const { return m_layers_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Inner() const { return m_layers_inner_holes_poly; }
|
||||
|
||||
const MAP_POLY &GetPolyMapHoles_Outer() const { return m_layers_outer_holes_poly; }
|
||||
|
||||
private:
|
||||
void createBoardPolygon();
|
||||
void createLayers( REPORTER *aStatusTextReporter );
|
||||
void destroyLayers();
|
||||
|
||||
// Helper functions to create the board
|
||||
COBJECT2D *createNewTrack( const TRACK* aTrack , int aClearanceValue ) const;
|
||||
|
||||
void createNewPad( const D_PAD* aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aInflateValue ) const;
|
||||
|
||||
void createNewPadWithClearance( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
wxSize aClearanceValue ) const;
|
||||
|
||||
COBJECT2D *createNewPadDrill( const D_PAD* aPad, int aInflateValue );
|
||||
|
||||
void AddPadsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper );
|
||||
|
||||
void AddGraphicsShapesWithClearanceToContainer( const MODULE *aModule,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aInflateValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const TEXTE_PCB *aTextPCB,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DRAWSEGMENT *aDrawSegment,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddShapeWithClearanceToContainer( const DIMENSION *aDimension,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId,
|
||||
int aClearanceValue );
|
||||
|
||||
void AddSolidAreasShapesToContainer( const ZONE_CONTAINER *aZoneContainer,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
PCB_LAYER_ID aLayerId );
|
||||
|
||||
void TransformArcToSegments( const wxPoint &aCentre,
|
||||
const wxPoint &aStart,
|
||||
double aArcAngle,
|
||||
int aCircleToSegmentsCount,
|
||||
int aWidth,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
const BOARD_ITEM &aBoardItem );
|
||||
|
||||
void buildPadShapeThickOutlineAsSegments( const D_PAD *aPad,
|
||||
CGENERICCONTAINER2D *aDstContainer,
|
||||
int aWidth );
|
||||
|
||||
// Helper functions to create poly contours
|
||||
void buildPadShapeThickOutlineAsPolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aWidth) const;
|
||||
|
||||
void transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD> &aPads,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper) const;
|
||||
|
||||
void transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const;
|
||||
|
||||
void buildPadShapePolygon( const D_PAD *aPad,
|
||||
SHAPE_POLY_SET &aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const;
|
||||
|
||||
|
||||
public:
|
||||
SFVEC3D m_BgColorBot; ///< background bottom color
|
||||
SFVEC3D m_BgColorTop; ///< background top color
|
||||
SFVEC3D m_BoardBodyColor; ///< in realistic mode: FR4 board color
|
||||
SFVEC3D m_SolderMaskColor; ///< in realistic mode: solder mask color
|
||||
SFVEC3D m_SolderPasteColor; ///< in realistic mode: solder paste color
|
||||
SFVEC3D m_SilkScreenColor; ///< in realistic mode: SilkScreen color
|
||||
SFVEC3D m_CopperColor; ///< in realistic mode: copper color
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/// Current board
|
||||
BOARD *m_board;
|
||||
|
||||
/// pointer to the 3d model manager
|
||||
S3D_CACHE *m_3d_model_manager;
|
||||
|
||||
|
||||
// Render options
|
||||
|
||||
/// options flags to render the board
|
||||
std::vector< bool > m_drawFlags;
|
||||
|
||||
/// Stores the current grid type
|
||||
GRID3D_TYPE m_3D_grid_type;
|
||||
|
||||
/// render engine currently on use
|
||||
RENDER_ENGINE m_render_engine;
|
||||
|
||||
/// mode to render the 3d shape models material
|
||||
MATERIAL_MODE m_material_mode;
|
||||
|
||||
|
||||
// Pcb board position
|
||||
|
||||
/// center board actual position in board units
|
||||
wxPoint m_boardPos;
|
||||
|
||||
/// board actual size in board units
|
||||
wxSize m_boardSize;
|
||||
|
||||
/// 3d center position of the pcb board in 3d units
|
||||
SFVEC3F m_boardCenter;
|
||||
|
||||
|
||||
// Pcb board bounding boxes
|
||||
|
||||
/// 3d bouding box of the pcb board in 3d units
|
||||
CBBOX m_boardBoudingBox;
|
||||
|
||||
/// 2d bouding box of the pcb board in 3d units
|
||||
CBBOX2D m_board2dBBox3DU;
|
||||
|
||||
/// It contains polygon contours for each layer
|
||||
MAP_POLY m_layers_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (outer holes)
|
||||
MAP_POLY m_layers_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for holes of each layer (inner holes)
|
||||
MAP_POLY m_layers_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for (just) non plated through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly_NPTH;
|
||||
|
||||
/// It contains polygon contours for through holes (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (outer cylinder)
|
||||
SHAPE_POLY_SET m_through_outer_holes_vias_poly;
|
||||
|
||||
/// It contains polygon contours for through holes vias (inner cylinder)
|
||||
SHAPE_POLY_SET m_through_inner_holes_vias_poly;
|
||||
|
||||
/// PCB board outline polygon
|
||||
SHAPE_POLY_SET m_board_poly;
|
||||
|
||||
|
||||
// 2D element containers
|
||||
|
||||
/// It contains the 2d elements of each layer
|
||||
MAP_CONTAINER_2D m_layers_container2D;
|
||||
|
||||
/// It contains the holes per each layer
|
||||
MAP_CONTAINER_2D m_layers_holes2D;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_outer;
|
||||
|
||||
/// It contains the list of throughHoles of the board,
|
||||
/// the radius is the inner hole
|
||||
CBVHCONTAINER2D m_through_holes_inner;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole is inflated with the copper tickness
|
||||
CBVHCONTAINER2D m_through_holes_vias_outer;
|
||||
|
||||
/// It contains the list of throughHoles vias of the board,
|
||||
/// the radius of the hole
|
||||
CBVHCONTAINER2D m_through_holes_vias_inner;
|
||||
|
||||
|
||||
// Layers information
|
||||
|
||||
/// Number of copper layers actually used by the board
|
||||
unsigned int m_copperLayersCount;
|
||||
|
||||
/// Normalization scale to convert board internal units to 3D units to
|
||||
/// normalize 3D units between -1.0 and +1.0
|
||||
double m_biuTo3Dunits;
|
||||
|
||||
/// Top (End) Z position of each layer (normalized)
|
||||
float m_layerZcoordTop[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Bottom (Start) Z position of each layer (normalized)
|
||||
float m_layerZcoordBottom[PCB_LAYER_ID_COUNT];
|
||||
|
||||
/// Copper thickness (normalized)
|
||||
float m_copperThickness3DU;
|
||||
|
||||
/// Epoxy thickness (normalized)
|
||||
float m_epoxyThickness3DU;
|
||||
|
||||
/// Non copper layers thickness
|
||||
float m_nonCopperLayerThickness3DU;
|
||||
|
||||
|
||||
// Cameras
|
||||
|
||||
/// Holds a pointer to current camera in use.
|
||||
CCAMERA &m_currentCamera;
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// min factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_min_factor3DU;
|
||||
|
||||
/// max factor used for cicle segment approximation calculation
|
||||
float m_calc_seg_max_factor3DU;
|
||||
|
||||
|
||||
// Statistics
|
||||
|
||||
/// Number of tracks in the board
|
||||
unsigned int m_stats_nr_tracks;
|
||||
|
||||
/// Track average width
|
||||
float m_stats_track_med_width;
|
||||
|
||||
/// Nr of vias
|
||||
unsigned int m_stats_nr_vias;
|
||||
|
||||
/// Computed medium diameter of the via holes in 3D units
|
||||
float m_stats_via_med_hole_diameter;
|
||||
|
||||
/// number of holes in the board
|
||||
unsigned int m_stats_nr_holes;
|
||||
|
||||
/// Computed medium diameter of the holes in 3D units
|
||||
float m_stats_hole_med_diameter;
|
||||
|
||||
/**
|
||||
* 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_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
|
||||
};
|
||||
|
||||
/// This is a dummy visualization configuration
|
||||
extern CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||
|
||||
#endif // CINFO3D_VISU_H
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file create_layer_poly.cpp
|
||||
* @brief This file implements the creation of the pcb board items in the poly
|
||||
* contours format. It is based on the function found in the files:
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
* board_items_to_polygon_shape_transform.cpp
|
||||
*/
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include <convert_basic_shapes_to_polygon.h>
|
||||
#include <class_edge_mod.h>
|
||||
#include <class_module.h>
|
||||
|
||||
|
||||
// This is the same function as in board_items_to_polygon_shape_transform.cpp
|
||||
// but it adds the rect/trapezoid shapes with a different winding
|
||||
void CINFO3D_VISU::buildPadShapePolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
wxSize aInflateValue,
|
||||
int aSegmentsPerCircle,
|
||||
double aCorrectionFactor ) const
|
||||
{
|
||||
wxPoint corners[4];
|
||||
wxPoint PadShapePos = aPad->ShapePos(); /* Note: for pad having a shape offset,
|
||||
* the pad position is NOT the shape position */
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
case PAD_SHAPE_OVAL:
|
||||
case PAD_SHAPE_ROUNDRECT:
|
||||
{
|
||||
// We are using TransformShapeWithClearanceToPolygon to build the shape.
|
||||
// Currently, this method uses only the same inflate value for X and Y dirs.
|
||||
// so because here this is not the case, we use a inflated dummy pad to build
|
||||
// the polygonal shape
|
||||
// TODO: remove this dummy pad when TransformShapeWithClearanceToPolygon will use
|
||||
// a wxSize to inflate the pad size
|
||||
D_PAD dummy( *aPad );
|
||||
wxSize new_size = aPad->GetSize() + aInflateValue + aInflateValue;
|
||||
dummy.SetSize( new_size );
|
||||
dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, 0,
|
||||
aSegmentsPerCircle, aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_TRAPEZOID:
|
||||
case PAD_SHAPE_RECT:
|
||||
{
|
||||
SHAPE_LINE_CHAIN aLineChain;
|
||||
|
||||
aPad->BuildPadPolygon( corners, aInflateValue, aPad->GetOrientation() );
|
||||
|
||||
for( int ii = 0; ii < 4; ++ii )
|
||||
{
|
||||
corners[3-ii] += PadShapePos; // Shift origin to position
|
||||
aLineChain.Append( corners[3-ii].x, corners[3-ii].y );
|
||||
}
|
||||
|
||||
aLineChain.SetClosed( true );
|
||||
|
||||
aCornerBuffer.AddOutline( aLineChain );
|
||||
}
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_CUSTOM:
|
||||
{
|
||||
SHAPE_POLY_SET polyList; // Will contain the pad outlines in board coordinates
|
||||
polyList.Append( aPad->GetCustomShapeAsPolygon() );
|
||||
aPad->CustomShapeAsPolygonToBoardPosition( &polyList, aPad->ShapePos(), aPad->GetOrientation() );
|
||||
aCornerBuffer.Append( polyList );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CINFO3D_VISU::buildPadShapeThickOutlineAsPolygon( const D_PAD* aPad,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aWidth ) const
|
||||
{
|
||||
if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // Draw a ring
|
||||
{
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( ( aPad->GetSize().x / 2 +
|
||||
aWidth / 2 ) * 2 );
|
||||
|
||||
TransformRingToPolygon( aCornerBuffer, aPad->ShapePos(),
|
||||
aPad->GetSize().x / 2, nr_sides_per_circle, aWidth );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// For other shapes, draw polygon outlines
|
||||
SHAPE_POLY_SET corners;
|
||||
|
||||
unsigned int nr_sides_per_circle = GetNrSegmentsCircle( glm::min( aPad->GetSize().x,
|
||||
aPad->GetSize().y) );
|
||||
buildPadShapePolygon( aPad, corners, wxSize( 0, 0 ),
|
||||
nr_sides_per_circle,
|
||||
GetCircleCorrectionFactor( nr_sides_per_circle ) );
|
||||
|
||||
// Add outlines as thick segments in polygon buffer
|
||||
|
||||
const SHAPE_LINE_CHAIN& path = corners.COutline( 0 );
|
||||
|
||||
for( int ii = 0; ii < path.PointCount(); ++ii )
|
||||
{
|
||||
const VECTOR2I& a = path.CPoint( ii );
|
||||
const VECTOR2I& b = path.CPoint( ii + 1 );
|
||||
|
||||
TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
|
||||
wxPoint( a.x, a.y ),
|
||||
wxPoint( b.x, b.y ),
|
||||
nr_sides_per_circle,
|
||||
aWidth );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Based on the same function name in board_items_to_polyshape_transform.cpp
|
||||
// It was implemented here to allow dynamic segments count per pad shape
|
||||
void CINFO3D_VISU::transformPadsShapesWithClearanceToPolygon( const DLIST<D_PAD>& aPads, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aInflateValue,
|
||||
bool aSkipNPTHPadsWihNoCopper ) const
|
||||
{
|
||||
const D_PAD* pad = aPads;
|
||||
|
||||
wxSize margin;
|
||||
for( ; pad != NULL; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer(aLayer) )
|
||||
continue;
|
||||
|
||||
// NPTH pads are not drawn on layers if the shape size and pos is the same
|
||||
// as their hole:
|
||||
if( aSkipNPTHPadsWihNoCopper && (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED) )
|
||||
{
|
||||
if( (pad->GetDrillSize() == pad->GetSize()) &&
|
||||
(pad->GetOffset() == wxPoint( 0, 0 )) )
|
||||
{
|
||||
switch( pad->GetShape() )
|
||||
{
|
||||
case PAD_SHAPE_CIRCLE:
|
||||
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
case PAD_SHAPE_OVAL:
|
||||
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( aLayer )
|
||||
{
|
||||
case F_Mask:
|
||||
case B_Mask:
|
||||
margin.x = margin.y = pad->GetSolderMaskMargin() + aInflateValue;
|
||||
break;
|
||||
|
||||
case F_Paste:
|
||||
case B_Paste:
|
||||
margin = pad->GetSolderPasteMargin();
|
||||
margin.x += aInflateValue;
|
||||
margin.y += aInflateValue;
|
||||
break;
|
||||
|
||||
default:
|
||||
margin.x = margin.y = aInflateValue;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int aCircleToSegmentsCount = GetNrSegmentsCircle( pad->GetSize().x );
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
buildPadShapePolygon( pad, aCornerBuffer, margin,
|
||||
aCircleToSegmentsCount, aCorrectionFactor );
|
||||
}
|
||||
}
|
||||
|
||||
void CINFO3D_VISU::transformGraphicModuleEdgeToPolygonSet( const MODULE *aModule,
|
||||
PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aCornerBuffer ) const
|
||||
{
|
||||
for( const EDA_ITEM* item = aModule->GraphicalItemsList();
|
||||
item != NULL;
|
||||
item = item->Next() )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_MODULE_EDGE_T:
|
||||
{
|
||||
EDGE_MODULE*outline = (EDGE_MODULE*) item;
|
||||
|
||||
if( outline->GetLayer() != aLayer )
|
||||
break;
|
||||
|
||||
unsigned int aCircleToSegmentsCount =
|
||||
GetNrSegmentsCircle( outline->GetBoundingBox().GetSizeMax() );
|
||||
|
||||
double aCorrectionFactor = GetCircleCorrectionFactor( aCircleToSegmentsCount );
|
||||
|
||||
outline->TransformShapeWithClearanceToPolygon( aCornerBuffer,
|
||||
0,
|
||||
aCircleToSegmentsCount,
|
||||
aCorrectionFactor );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+144
-209
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 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
|
||||
@@ -22,73 +22,62 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_canvas.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef EDA_3D_CANVAS_H
|
||||
#define EDA_3D_CANVAS_H
|
||||
|
||||
#include <atomic>
|
||||
#include "board_adapter.h"
|
||||
#include "3d_rendering/raytracing/accelerators/accelerator_3d.h"
|
||||
#include "3d_rendering/render_3d_base.h"
|
||||
|
||||
#include "cinfo3d_visu.h"
|
||||
#include "3d_rendering/c3d_render_base.h"
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h"
|
||||
#include "3d_rendering/3d_render_raytracing/c3d_render_raytracing.h"
|
||||
#include "3d_cache/3d_cache.h"
|
||||
#include <gal/hidpi_gl_3D_canvas.h>
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dataobj.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/statusbr.h>
|
||||
#include <pcb_base_frame.h>
|
||||
|
||||
|
||||
class WX_INFOBAR;
|
||||
class wxStatusBar;
|
||||
class BOARD;
|
||||
class RENDER_3D_RAYTRACE_GL;
|
||||
class RENDER_3D_OPENGL;
|
||||
|
||||
|
||||
#define EDA_3D_CANVAS_ID wxID_HIGHEST + 1321
|
||||
|
||||
/**
|
||||
* Class EDA_3D_CANVAS
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class EDA_3D_CANVAS : public HIDPI_GL_3D_CANVAS
|
||||
class EDA_3D_CANVAS : public HIDPI_GL_CANVAS
|
||||
{
|
||||
public:
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Create a new 3D Canvas with an attribute list.
|
||||
*
|
||||
* @param aParent the parent creator of this canvas.
|
||||
* @param aGLAttribs openGL attributes created by #OGL_ATT_LIST::GetAttributesList.
|
||||
* @param aBoard The board.
|
||||
* @param aSettings the settings options to be used by this canvas.
|
||||
* @brief EDA_3D_CANVAS - Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent: the parent creator of this canvas
|
||||
* @param aAttribList: a list of openGL options created by GetOpenGL_AttributesList
|
||||
* @param aBoard: The board
|
||||
* @param aSettings: the settings options to be used by this canvas
|
||||
*/
|
||||
EDA_3D_CANVAS( wxWindow* aParent, const wxGLAttributes& aGLAttribs, BOARD_ADAPTER& aSettings,
|
||||
CAMERA& aCamera, S3D_CACHE* a3DCachePointer );
|
||||
EDA_3D_CANVAS( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
BOARD *aBoard = NULL,
|
||||
CINFO3D_VISU &aSettings = G_null_CINFO3D_VISU,
|
||||
S3D_CACHE *a3DCachePointer = NULL );
|
||||
|
||||
~EDA_3D_CANVAS();
|
||||
|
||||
/**
|
||||
* Set a dispatcher that processes events and forwards them to tools.
|
||||
*
|
||||
* #DRAW_PANEL_GAL does not take over the ownership. Passing NULL disconnects all event
|
||||
* handlers from the DRAW_PANEL_GAL and parent frame.
|
||||
*
|
||||
* @param aEventDispatcher is the object that will be used for dispatching events.
|
||||
*/
|
||||
void SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher );
|
||||
void SetStatusBar( wxStatusBar *aStatusBar ) { m_parentStatusBar = aStatusBar; }
|
||||
|
||||
void SetStatusBar( wxStatusBar* aStatusBar )
|
||||
{
|
||||
m_parentStatusBar = aStatusBar;
|
||||
}
|
||||
|
||||
void SetInfoBar( WX_INFOBAR* aInfoBar )
|
||||
{
|
||||
m_parentInfoBar = aInfoBar;
|
||||
}
|
||||
|
||||
void ReloadRequest( BOARD* aBoard = nullptr, S3D_CACHE* aCachePointer = nullptr );
|
||||
void ReloadRequest( BOARD *aBoard = NULL, S3D_CACHE *aCachePointer = NULL );
|
||||
|
||||
/**
|
||||
* Query if there is a pending reload request.
|
||||
*
|
||||
* @return true if it wants to reload, false if there is no reload pending.
|
||||
* @brief IsReloadRequestPending - Query if there is a pending reload request
|
||||
* @return true if it wants to reload, false if there is no reload pending
|
||||
*/
|
||||
bool IsReloadRequestPending() const
|
||||
{
|
||||
@@ -99,241 +88,187 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current render ( a RENDER_3D_RAYTRACE_GL* or a RENDER_3D_OPENGL* render )
|
||||
*/
|
||||
RENDER_3D_BASE* GetCurrentRender() const { return m_3d_render; }
|
||||
|
||||
/**
|
||||
* Request to render the current view in Raytracing mode.
|
||||
* @brief RenderRaytracingRequest - Request to render the current view in Raytracing mode
|
||||
*/
|
||||
void RenderRaytracingRequest();
|
||||
|
||||
/**
|
||||
* Request a screenshot and output it to the \a aDstImage.
|
||||
*
|
||||
* @param aDstImage - Screenshot destination image.
|
||||
* Request a screenshot and output it to the aDstImage
|
||||
* @param aDstImage - Screenshot destination image
|
||||
*/
|
||||
void GetScreenshot( wxImage& aDstImage );
|
||||
void GetScreenshot( wxImage &aDstImage );
|
||||
|
||||
/**
|
||||
* Select a specific 3D view or operation.
|
||||
*
|
||||
* @param aRequestedView the view to move to.
|
||||
* @return true if the view request was handled, false if no command found for this view.
|
||||
* @brief SetView3D - Helper function to call view commands
|
||||
* @param aKeycode: ascii key commands
|
||||
* @return true if the key code was handled,
|
||||
* false if no command found for this code.
|
||||
*/
|
||||
bool SetView3D( VIEW3D_TYPE aRequestedView );
|
||||
bool SetView3D( int aKeycode );
|
||||
|
||||
/**
|
||||
* Enable or disable camera animation when switching to a pre-defined view.
|
||||
*/
|
||||
void SetAnimationEnabled( bool aEnable ) { m_animation_enabled = aEnable; }
|
||||
bool GetAnimationEnabled() const { return m_animation_enabled; }
|
||||
|
||||
/**
|
||||
* Set the camera animation moving speed multiplier option.
|
||||
*
|
||||
* @param aMultiplier one of the possible integer options: [1,2,3,4,5].
|
||||
*/
|
||||
void SetMovingSpeedMultiplier( int aMultiplier ) { m_moving_speed_multiplier = aMultiplier; }
|
||||
int GetMovingSpeedMultiplier() const { return m_moving_speed_multiplier; }
|
||||
|
||||
int GetProjectionMode() const { return (int) m_camera.GetProjection(); };
|
||||
void SetProjectionMode( int aMode ) { m_camera.SetProjection( (PROJECTION_TYPE) aMode ); }
|
||||
|
||||
/**
|
||||
* Notify that the render engine was changed.
|
||||
* @brief RenderEngineChanged - Notify that the render engine was changed
|
||||
*/
|
||||
void RenderEngineChanged();
|
||||
|
||||
/**
|
||||
* Update the status bar with the position information.
|
||||
* @brief DisplayStatus - Update the status bar with the position information
|
||||
*/
|
||||
void DisplayStatus();
|
||||
|
||||
/**
|
||||
* Schedule a refresh update of the canvas.
|
||||
*
|
||||
* @param aRedrawImmediately true will request a redraw, false will schedule a redraw
|
||||
* after a short timeout.
|
||||
* @brief Request_refresh - Schedule a refresh update of the canvas
|
||||
* @param aRedrawImmediately - true will request a redraw, false will
|
||||
* schedule a redraw, after a short timeout.
|
||||
*/
|
||||
void Request_refresh( bool aRedrawImmediately = true );
|
||||
|
||||
/**
|
||||
* Used to forward events to the canvas from popups, etc.
|
||||
*/
|
||||
void OnEvent( wxEvent& aEvent );
|
||||
void OnKeyEvent( wxKeyEvent& event );
|
||||
|
||||
/**
|
||||
* Get information used to display 3D board.
|
||||
*/
|
||||
const BOARD_ADAPTER& GetBoardAdapter() const { return m_boardAdapter; }
|
||||
private:
|
||||
|
||||
/**
|
||||
* Get a value indicating whether to render the pivot.
|
||||
*/
|
||||
bool GetRenderPivot() { return m_render_pivot; }
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
/**
|
||||
* Set aValue indicating whether to render the pivot.
|
||||
*
|
||||
* @param aValue true will cause the pivot to be rendered on the next redraw.
|
||||
*/
|
||||
void SetRenderPivot( bool aValue ) { m_render_pivot = aValue; }
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
/**
|
||||
* Get a value indicating whether to render the 3dmouse pivot.
|
||||
*/
|
||||
bool GetRender3dmousePivot()
|
||||
{
|
||||
return m_render3dmousePivot;
|
||||
}
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT )
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Set aValue indicating whether to render the 3dmouse pivot.
|
||||
*
|
||||
* @param aValue true will cause the pivot to be rendered on the next redraw.
|
||||
*/
|
||||
void SetRender3dmousePivot( bool aValue )
|
||||
{
|
||||
m_render3dmousePivot = aValue;
|
||||
}
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
/**
|
||||
* Set the position of the the 3dmouse pivot.
|
||||
*
|
||||
* @param aPos is the position of the 3dmouse rotation pivot
|
||||
*/
|
||||
void Set3dmousePivotPos( const SFVEC3F& aPos )
|
||||
{
|
||||
m_3dmousePivotPos = aPos;
|
||||
}
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
/**
|
||||
* The actual function to repaint the canvas.
|
||||
*
|
||||
* It is usually called by OnPaint() but because it does not use a wxPaintDC it can be
|
||||
* called outside a wxPaintEvent
|
||||
*/
|
||||
void DoRePaint();
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnCloseWindow( wxCloseEvent& event );
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
private:
|
||||
// The wxPaintEvent event. mainly calls DoRePaint()
|
||||
void OnPaint( wxPaintEvent& aEvent );
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
void OnPopUpMenu( wxCommandEvent &event );
|
||||
|
||||
void OnRefreshRequest( wxEvent& aEvent );
|
||||
void OnCharHook( wxKeyEvent& event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent& event );
|
||||
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
void OnMouseMove( wxMouseEvent& event );
|
||||
void OnLeftDown( wxMouseEvent& event );
|
||||
void OnLeftUp( wxMouseEvent& event );
|
||||
void OnMiddleUp( wxMouseEvent& event );
|
||||
void OnMiddleDown( wxMouseEvent& event );
|
||||
void OnTimerTimeout_Editing( wxTimerEvent& event );
|
||||
void OnResize( wxSizeEvent& event );
|
||||
void OnTimerTimeout_Redraw( wxTimerEvent& event );
|
||||
|
||||
void OnZoomGesture( wxZoomGestureEvent& event );
|
||||
void OnPanGesture( wxPanGestureEvent& event );
|
||||
void OnRotateGesture( wxRotateGestureEvent& event );
|
||||
/**
|
||||
* @brief OnCloseWindow - called when the frame is closed
|
||||
* @param event
|
||||
*/
|
||||
void OnCloseWindow( wxCloseEvent &event );
|
||||
|
||||
void OnResize( wxSizeEvent &event );
|
||||
|
||||
void OnTimerTimeout_Redraw( wxTimerEvent& event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
*Stop the editing time so it will not timeout.
|
||||
* @brief stop_editingTimeOut_Timer - stop the editing time, so it will not timeout
|
||||
*/
|
||||
void stop_editingTimeOut_Timer();
|
||||
|
||||
|
||||
/**
|
||||
* Reset the editing timer.
|
||||
* @brief restart_editingTimeOut_Timer - reset the editing timer
|
||||
*/
|
||||
void restart_editingTimeOut_Timer();
|
||||
|
||||
/**
|
||||
* Start a camera movement.
|
||||
*
|
||||
* @param aMovingSpeed the time speed.
|
||||
* @param aRenderPivot if it should display pivot cursor while move.
|
||||
*/
|
||||
void request_start_moving_camera( float aMovingSpeed = 2.0f, bool aRenderPivot = true );
|
||||
|
||||
/**
|
||||
* This function hits a ray to the board and start a movement.
|
||||
* @brief request_start_moving_camera - start a camera movement
|
||||
* @param aMovingSpeed: the time speed
|
||||
* @param aRenderPivot: if it should display pivot cursor while move
|
||||
*/
|
||||
void request_start_moving_camera( float aMovingSpeed = 2.0f,
|
||||
bool aRenderPivot = true );
|
||||
|
||||
|
||||
/**
|
||||
* @brief move_pivot_based_on_cur_mouse_position -
|
||||
* This function hits a ray to the board and start a moviment
|
||||
*/
|
||||
void move_pivot_based_on_cur_mouse_position();
|
||||
|
||||
|
||||
/**
|
||||
* Render the pivot cursor.
|
||||
*
|
||||
* @param t time between 0.0 and 1.0.
|
||||
* @param aScale scale to apply on the cursor.
|
||||
* @brief render_pivot - render the pivot cursor
|
||||
* @param t: time between 0.0 and 1.0
|
||||
* @param aScale: scale to apply on the cursor
|
||||
*/
|
||||
void render_pivot( float t, float aScale );
|
||||
|
||||
/**
|
||||
* Render the 3dmouse pivot cursor.
|
||||
*
|
||||
* @param aScale scale to apply on the cursor.
|
||||
*/
|
||||
void render3dmousePivot( float aScale );
|
||||
|
||||
/**
|
||||
* @return true if OpenGL initialization succeeded.
|
||||
* @brief initializeOpenGL
|
||||
* @return if OpenGL initialization succeed
|
||||
*/
|
||||
bool initializeOpenGL();
|
||||
|
||||
/**
|
||||
* Free created targets and openGL context.
|
||||
* @brief releaseOpenGL - free created targets and openGL context
|
||||
*/
|
||||
void releaseOpenGL();
|
||||
|
||||
RAY getRayAtCurrentMousePosition();
|
||||
private:
|
||||
|
||||
private:
|
||||
TOOL_DISPATCHER* m_eventDispatcher;
|
||||
wxStatusBar* m_parentStatusBar; // Parent statusbar to report progress
|
||||
WX_INFOBAR* m_parentInfoBar;
|
||||
/// current OpenGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
wxGLContext* m_glRC; // Current OpenGL context
|
||||
bool m_is_opengl_initialized;
|
||||
bool m_is_opengl_version_supported;
|
||||
/// Parent statusbar to report progress
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
|
||||
wxTimer m_editing_timeout_timer; // Expires after some time signaling that
|
||||
// the mouse / keyboard movements are over
|
||||
wxTimer m_redraw_trigger_timer; // Used to schedule a redraw event
|
||||
std::atomic_flag m_is_currently_painting; // Avoid drawing twice at the same time
|
||||
/// Time timeout will expires after some time sinalizing that the mouse /
|
||||
/// keyboard movements are over.
|
||||
wxTimer m_editing_timeout_timer;
|
||||
|
||||
bool m_render_pivot; // Render the pivot while camera moving
|
||||
float m_camera_moving_speed; // 1.0f will be 1:1
|
||||
int64_t m_strtime_camera_movement; // Ticktime of camera movement start
|
||||
bool m_animation_enabled; // Camera animation enabled
|
||||
int m_moving_speed_multiplier; // Camera animation speed multiplier option
|
||||
/// This timer will be used to schedule a redraw event
|
||||
wxTimer m_redraw_trigger_timer;
|
||||
|
||||
BOARD_ADAPTER& m_boardAdapter; // Pre-computed 3D info and settings
|
||||
RENDER_3D_BASE* m_3d_render;
|
||||
RENDER_3D_RAYTRACE_GL* m_3d_render_raytracing;
|
||||
RENDER_3D_OPENGL* m_3d_render_opengl;
|
||||
/// true if mouse activity is on progress
|
||||
bool m_mouse_is_moving;
|
||||
|
||||
bool m_opengl_supports_raytracing;
|
||||
bool m_render_raytracing_was_requested;
|
||||
/// true if there was some type of activity, it will be used to render in
|
||||
/// preview mode
|
||||
bool m_mouse_was_moved;
|
||||
|
||||
ACCELERATOR_3D* m_accelerator3DShapes; // used for mouse over searching
|
||||
/// true if camera animation is ongoing
|
||||
bool m_camera_is_moving;
|
||||
|
||||
BOARD_ITEM* m_currentRollOverItem;
|
||||
/// activated the render of pivot while camera moving
|
||||
bool m_render_pivot;
|
||||
|
||||
bool m_render3dmousePivot = false; // Render the 3dmouse pivot
|
||||
SFVEC3F m_3dmousePivotPos; // The position of the 3dmouse pivot
|
||||
/// 1.0f will be 1:1
|
||||
float m_camera_moving_speed;
|
||||
|
||||
/// Used to track gesture events.
|
||||
double m_gestureLastZoomFactor = 1.0;
|
||||
double m_gestureLastAngle = 0.0;
|
||||
/// Stores the ticktime when the camera star its movement
|
||||
unsigned m_strtime_camera_movement;
|
||||
|
||||
/// Stores all pre-computed 3D information and visualization settings to render the board
|
||||
CINFO3D_VISU &m_settings;
|
||||
|
||||
/// The current render in used for this canvas
|
||||
C3D_RENDER_BASE *m_3d_render;
|
||||
|
||||
/// Raytracing render class
|
||||
C3D_RENDER_RAYTRACING *m_3d_render_raytracing;
|
||||
|
||||
/// OpenGL legacy render class
|
||||
C3D_RENDER_OGL_LEGACY *m_3d_render_ogl_legacy;
|
||||
|
||||
/// Flag to store if opengl was initialized already
|
||||
bool m_is_opengl_initialized;
|
||||
|
||||
/// Step factor to used with cursor on relation to the current zoom
|
||||
static const float m_delta_move_step_factor;
|
||||
|
||||
/// Flags that the user requested the current view to be render with raytracing
|
||||
bool m_render_raytracing_was_requested;
|
||||
|
||||
/**
|
||||
* Trace mask used to enable or disable the trace output of this class.
|
||||
@@ -341,7 +276,7 @@ private:
|
||||
* "KI_TRACE_EDA_3D_CANVAS". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 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
|
||||
@@ -35,26 +35,26 @@
|
||||
static void pivot_render_triangles( float t )
|
||||
{
|
||||
wxASSERT( t >= 0.0f );
|
||||
|
||||
|
||||
SFVEC3F vertexPointer[12];
|
||||
|
||||
const float u = 1.0f / 6.0f;
|
||||
|
||||
vertexPointer[0] = SFVEC3F( ( -3.0f + t ) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[1] = SFVEC3F( ( -3.0f + t ) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[2] = SFVEC3F( ( -1.0f + t ) * u, 0.0f * u, 0.0f );
|
||||
vertexPointer[0] = SFVEC3F( (-3.0f + t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[1] = SFVEC3F( (-3.0f + t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[2] = SFVEC3F( (-1.0f + t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[3] = SFVEC3F( -2.0f * u, ( -3.0f + t ) * u, 0.0f );
|
||||
vertexPointer[4] = SFVEC3F( 2.0f * u, ( -3.0f + t ) * u, 0.0f );
|
||||
vertexPointer[5] = SFVEC3F( 0.0f * u, ( -1.0f + t ) * u, 0.0f );
|
||||
vertexPointer[3] = SFVEC3F( -2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[4] = SFVEC3F( 2.0f * u, (-3.0f + t) * u, 0.0f );
|
||||
vertexPointer[5] = SFVEC3F( 0.0f * u, (-1.0f + t) * u, 0.0f );
|
||||
|
||||
vertexPointer[6] = SFVEC3F( ( 3.0f - t ) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[7] = SFVEC3F( ( 3.0f - t ) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[8] = SFVEC3F( ( 1.0f - t ) * u, 0.0f * u, 0.0f );
|
||||
vertexPointer[6] = SFVEC3F( (3.0f - t) * u, -2.0f * u, 0.0f );
|
||||
vertexPointer[7] = SFVEC3F( (3.0f - t) * u, 2.0f * u, 0.0f );
|
||||
vertexPointer[8] = SFVEC3F( (1.0f - t) * u, 0.0f * u, 0.0f );
|
||||
|
||||
vertexPointer[9] = SFVEC3F( 2.0f * u, ( 3.0f - t ) * u, 0.0f );
|
||||
vertexPointer[10] = SFVEC3F( -2.0f * u, ( 3.0f - t ) * u, 0.0f );
|
||||
vertexPointer[11] = SFVEC3F( 0.0f * u, ( 1.0f - t ) * u, 0.0f );
|
||||
vertexPointer[9] = SFVEC3F( 2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[10] = SFVEC3F( -2.0f * u, (3.0f - t) * u, 0.0f );
|
||||
vertexPointer[11] = SFVEC3F( 0.0f * u, (1.0f - t) * u, 0.0f );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
@@ -73,7 +73,7 @@ static void pivot_render_triangles( float t )
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::render_pivot( float t, float aScale )
|
||||
void EDA_3D_CANVAS::render_pivot( float t , float aScale )
|
||||
{
|
||||
wxASSERT( aScale >= 0.0f );
|
||||
wxASSERT( t >= 0.0f );
|
||||
@@ -81,27 +81,29 @@ void EDA_3D_CANVAS::render_pivot( float t, float aScale )
|
||||
if( t > 1.0f )
|
||||
t = 1.0f;
|
||||
|
||||
const SFVEC3F &lookAtPos = m_camera.GetLookAtPos_T1();
|
||||
const SFVEC3F &lookAtPos = m_settings.CameraGet().GetLookAtPos_T1();
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_CULL_FACE );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetProjectionMatrix() ) );
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetViewMatrix() ) );
|
||||
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( 0.0f, 1.0f, 0.0f, 0.75f - t * 0.75f );
|
||||
|
||||
// Translate to the look at position
|
||||
glTranslatef( lookAtPos.x, lookAtPos.y, lookAtPos.z );
|
||||
|
||||
|
||||
glScalef( aScale, aScale, aScale );
|
||||
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
|
||||
t = t * 0.80f;
|
||||
@@ -118,44 +120,3 @@ void EDA_3D_CANVAS::render_pivot( float t, float aScale )
|
||||
pivot_render_triangles( t * 0.5f );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_CANVAS::render3dmousePivot( float aScale )
|
||||
{
|
||||
wxASSERT( aScale >= 0.0f );
|
||||
|
||||
glDisable( GL_LIGHTING );
|
||||
glDisable( GL_DEPTH_TEST );
|
||||
glDisable( GL_CULL_FACE );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
glLoadMatrixf( glm::value_ptr( m_camera.GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColor4f( 0.0f, 0.667f, 0.902f, 0.75f );
|
||||
|
||||
// Translate to the look at position
|
||||
glTranslatef( m_3dmousePivotPos.x, m_3dmousePivotPos.y, m_3dmousePivotPos.z );
|
||||
|
||||
glPointSize( 16.0f );
|
||||
glEnable( GL_POINT_SMOOTH );
|
||||
glHint( GL_POINT_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glScalef( aScale, aScale, aScale );
|
||||
|
||||
// Draw a point at the look at position.
|
||||
glBegin( GL_POINTS );
|
||||
glVertex3f( 0, 0, 0 );
|
||||
glEnd();
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glDisable( GL_POINT_SMOOTH );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 1992-2016 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file status_text_reporter.h
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef STATUS_TEXT_REPORTER_H_
|
||||
#define STATUS_TEXT_REPORTER_H_
|
||||
|
||||
#include <reporter.h>
|
||||
|
||||
/**
|
||||
* Class STATUS_TEXT_REPORTER
|
||||
* is a wrapper for reporting to a wxString in a wxFrame status text.
|
||||
*/
|
||||
class STATUS_TEXT_REPORTER : public REPORTER
|
||||
{
|
||||
private:
|
||||
wxStatusBar *m_parentStatusBar;
|
||||
int m_position;
|
||||
bool m_hasMessage;
|
||||
|
||||
public:
|
||||
STATUS_TEXT_REPORTER( wxStatusBar* aParentStatusBar, int aPosition = 0 ) :
|
||||
REPORTER(),
|
||||
m_parentStatusBar( aParentStatusBar ), m_position( aPosition )
|
||||
{
|
||||
m_hasMessage = false;
|
||||
}
|
||||
|
||||
REPORTER& Report( const wxString& aText, SEVERITY aSeverity = RPT_UNDEFINED ) override
|
||||
{
|
||||
if( !aText.IsEmpty() )
|
||||
m_hasMessage = true;
|
||||
|
||||
if( m_parentStatusBar )
|
||||
m_parentStatusBar->SetStatusText( aText, m_position );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasMessage() const override { return m_hasMessage; }
|
||||
};
|
||||
|
||||
|
||||
#endif // STATUS_TEXT_REPORTER_H_
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2016 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file 3d_enums.h
|
||||
* @brief declared enumerations and flags
|
||||
*/
|
||||
|
||||
#ifndef _3D_ENUMS_H_
|
||||
#define _3D_ENUMS_H_
|
||||
|
||||
/// Flags used in rendering options
|
||||
enum DISPLAY3D_FLG {
|
||||
FL_AXIS=0, FL_ZONE,
|
||||
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
|
||||
FL_COMMENTS, FL_ECO,
|
||||
|
||||
FL_MODULE_ATTRIBUTES_NORMAL,
|
||||
FL_MODULE_ATTRIBUTES_NORMAL_INSERT,
|
||||
FL_MODULE_ATTRIBUTES_VIRTUAL,
|
||||
|
||||
FL_SHOW_BOARD_BODY,
|
||||
FL_MOUSEWHEEL_PANNING,
|
||||
FL_USE_REALISTIC_MODE,
|
||||
|
||||
// OpenGL options
|
||||
FL_RENDER_OPENGL_SHOW_MODEL_BBOX,
|
||||
FL_RENDER_OPENGL_COPPER_THICKNESS,
|
||||
|
||||
// Raytracing options
|
||||
FL_RENDER_RAYTRACING_SHADOWS,
|
||||
FL_RENDER_RAYTRACING_BACKFLOOR,
|
||||
FL_RENDER_RAYTRACING_REFRACTIONS,
|
||||
FL_RENDER_RAYTRACING_REFLECTIONS,
|
||||
FL_RENDER_RAYTRACING_POST_PROCESSING,
|
||||
FL_RENDER_RAYTRACING_ANTI_ALIASING,
|
||||
FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES,
|
||||
FL_LAST
|
||||
};
|
||||
|
||||
|
||||
/// Camera types
|
||||
enum CAMERA_TYPE
|
||||
{
|
||||
CAMERA_TRACKBALL
|
||||
};
|
||||
|
||||
|
||||
/// Grid types
|
||||
enum GRID3D_TYPE
|
||||
{
|
||||
GRID3D_NONE,
|
||||
GRID3D_1MM,
|
||||
GRID3D_2P5MM,
|
||||
GRID3D_5MM,
|
||||
GRID3D_10MM
|
||||
};
|
||||
|
||||
|
||||
/// Render engine mode
|
||||
enum RENDER_ENGINE
|
||||
{
|
||||
RENDER_ENGINE_OPENGL_LEGACY,
|
||||
RENDER_ENGINE_RAYTRACING,
|
||||
};
|
||||
|
||||
|
||||
/// Render 3d model shape materials mode
|
||||
enum MATERIAL_MODE
|
||||
{
|
||||
MATERIAL_MODE_NORMAL, ///< Use all material properties from model file
|
||||
MATERIAL_MODE_DIFFUSE_ONLY, ///< Use only diffuse material properties
|
||||
MATERIAL_MODE_CAD_MODE ///< Use a gray shading based on diffuse material
|
||||
};
|
||||
|
||||
#endif // _3D_ENUMS_H_
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 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
|
||||
@@ -30,9 +30,9 @@
|
||||
#ifndef _3D_FASTMATH_H
|
||||
#define _3D_FASTMATH_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
// Define this flag to use fast math optimizations
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 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
|
||||
|
||||
+39
-30
@@ -2,7 +2,7 @@
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 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
|
||||
@@ -33,43 +33,44 @@
|
||||
#include <plugins/3dapi/xv3d_types.h>
|
||||
#include "3d_fastmath.h"
|
||||
|
||||
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
/**
|
||||
* https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||
*
|
||||
* @brief SphericalToCartesian
|
||||
* @param aInclination θ ∈ [0, π]
|
||||
* @param aAzimuth φ ∈ [0, 2π]
|
||||
* @return Cartesian coordinates
|
||||
* @return Cartesian cordinates
|
||||
*/
|
||||
inline SFVEC3F SphericalToCartesian( float aInclination, float aAzimuth )
|
||||
{
|
||||
float sinInc = glm::sin( aInclination );
|
||||
|
||||
return SFVEC3F( sinInc * glm::cos( aAzimuth ), sinInc * glm::sin( aAzimuth ),
|
||||
return SFVEC3F( sinInc * glm::cos( aAzimuth ),
|
||||
sinInc * glm::sin( aAzimuth ),
|
||||
glm::cos( aInclination ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @todo This is not correct because it is not a gaussian random.
|
||||
*/
|
||||
inline SFVEC3F UniformRandomHemisphereDirection()
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
// !TODO: this is not correct because it is not a gaussian random
|
||||
inline SFVEC3F UniformRandomHemisphereDirection( )
|
||||
{
|
||||
// It was experienced that this function is slow! do not use it :/
|
||||
// SFVEC3F b( (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f,
|
||||
// (rand()/(float)RAND_MAX) - 0.5f );
|
||||
|
||||
SFVEC3F b( Fast_RandFloat() * 0.5f, Fast_RandFloat() * 0.5f, Fast_RandFloat() * 0.5f );
|
||||
SFVEC3F b( Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f,
|
||||
Fast_RandFloat() * 0.5f );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F& n )
|
||||
inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F &n )
|
||||
{
|
||||
const float Xi1 = (float) rand() / (float) RAND_MAX;
|
||||
const float Xi2 = (float) rand() / (float) RAND_MAX;
|
||||
const float Xi1 = (float)rand() / (float)RAND_MAX;
|
||||
const float Xi2 = (float)rand() / (float)RAND_MAX;
|
||||
|
||||
const float theta = acos( sqrt( 1.0f - Xi1 ) );
|
||||
const float phi = 2.0f * glm::pi<float>() * Xi2;
|
||||
@@ -98,19 +99,21 @@ inline SFVEC3F CosWeightedRandomHemisphereDirection( const SFVEC3F& n )
|
||||
|
||||
|
||||
/**
|
||||
* @brief Refract
|
||||
* Based on:
|
||||
* https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h
|
||||
* See also:
|
||||
* http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_3_Refractions_and_Beers_Law.shtml
|
||||
*
|
||||
* @param aInVector incoming vector.
|
||||
* @param aNormal normal in the intersection point.
|
||||
* @param aRin_over_Rout incoming refraction index / out refraction index.
|
||||
* @param aOutVector the refracted vector.
|
||||
* @param aInVector incoming vector
|
||||
* @param aNormal normal in the intersection point
|
||||
* @param aRin_over_Rout incoming refraction index / out refraction index
|
||||
* @param aOutVector the refracted vector
|
||||
* @return true
|
||||
*/
|
||||
inline bool Refract( const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRin_over_Rout,
|
||||
SFVEC3F& aOutVector )
|
||||
inline bool Refract( const SFVEC3F &aInVector,
|
||||
const SFVEC3F &aNormal,
|
||||
float aRin_over_Rout,
|
||||
SFVEC3F &aOutVector )
|
||||
{
|
||||
float cosThetaI = -glm::dot( aNormal, aInVector );
|
||||
float sin2ThetaI = glm::max( 0.0f, 1.0f - cosThetaI * cosThetaI );
|
||||
@@ -130,7 +133,11 @@ inline bool Refract( const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRi
|
||||
}
|
||||
|
||||
|
||||
inline float mapf( float x, float in_min, float in_max, float out_min, float out_max )
|
||||
inline float mapf( float x,
|
||||
float in_min,
|
||||
float in_max,
|
||||
float out_min,
|
||||
float out_max)
|
||||
{
|
||||
x = glm::clamp( x, in_min, in_max );
|
||||
|
||||
@@ -147,15 +154,17 @@ inline float RGBtoGray( const SFVEC3F &aColor )
|
||||
inline SFVEC3F MaterialDiffuseToColorCAD( const SFVEC3F &aDiffuseColor )
|
||||
{
|
||||
// convert to a discret scale of grays
|
||||
const float luminance = glm::min(
|
||||
( ( (float) ( (unsigned int) ( 4.0f * RGBtoGray( aDiffuseColor ) ) ) + 0.5f ) / 4.0f )
|
||||
* 1.0f,
|
||||
1.0f );
|
||||
const float luminance = glm::min( (((float)((unsigned int) ( 4.0f *
|
||||
RGBtoGray( aDiffuseColor ) ) ) + 0.5f) /
|
||||
4.0f) * 1.0f,
|
||||
1.0f );
|
||||
|
||||
const float maxValue = glm::max( glm::max( glm::max( aDiffuseColor.r, aDiffuseColor.g ),
|
||||
aDiffuseColor.b ), FLT_EPSILON );
|
||||
const float maxValue = glm::max( glm::max( glm::max( aDiffuseColor.r,
|
||||
aDiffuseColor.g),
|
||||
aDiffuseColor.b ),
|
||||
FLT_EPSILON );
|
||||
|
||||
return ( aDiffuseColor / SFVEC3F( maxValue ) ) * 0.125f + luminance * 0.875f;
|
||||
return (aDiffuseColor / SFVEC3F(maxValue) ) * 0.125f + luminance* 0.875f;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +179,7 @@ inline float QuadricEasingInOut( float t )
|
||||
{
|
||||
t = t - 1.0f;
|
||||
|
||||
return -2.0f * ( t * t ) + 1.0f;
|
||||
return -2.0f * (t * t) + 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2017 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.cpp
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h"
|
||||
#include "c3d_model_viewer.h"
|
||||
#include "../3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include "common_ogl/ogl_utils.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include <base_units.h>
|
||||
#include <gl_context_mgr.h>
|
||||
|
||||
/**
|
||||
* Scale convertion from 3d model units to pcb units
|
||||
*/
|
||||
#define UNITS3D_TO_UNITSPCB (IU_PER_MM)
|
||||
|
||||
/**
|
||||
* 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_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
const wxChar * C3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( C3D_MODEL_VIEWER, wxGLCanvas )
|
||||
EVT_PAINT( C3D_MODEL_VIEWER::OnPaint )
|
||||
|
||||
// mouse events
|
||||
EVT_LEFT_DOWN( C3D_MODEL_VIEWER::OnLeftDown )
|
||||
EVT_LEFT_UP( C3D_MODEL_VIEWER::OnLeftUp )
|
||||
EVT_MIDDLE_UP( C3D_MODEL_VIEWER::OnMiddleUp )
|
||||
EVT_MIDDLE_DOWN(C3D_MODEL_VIEWER::OnMiddleDown)
|
||||
EVT_RIGHT_DOWN( C3D_MODEL_VIEWER::OnRightClick )
|
||||
EVT_MOUSEWHEEL( C3D_MODEL_VIEWER::OnMouseWheel )
|
||||
EVT_MOTION( C3D_MODEL_VIEWER::OnMouseMove )
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( C3D_MODEL_VIEWER::OnMagnify )
|
||||
#endif
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( C3D_MODEL_VIEWER::OnEraseBackground )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
// This defines the range that all coord will have to be rendered.
|
||||
// It will use this value to convert to a normalized value between
|
||||
// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::C3D_MODEL_VIEWER(wxWindow *aParent,
|
||||
const int *aAttribList , S3D_CACHE *aCacheManager) :
|
||||
|
||||
HIDPI_GL_CANVAS( aParent,
|
||||
wxID_ANY,
|
||||
aAttribList,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 2.0f ),
|
||||
m_cacheManager(aCacheManager)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::C3D_MODEL_VIEWER" ) );
|
||||
|
||||
m_ogl_initialized = false;
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = NULL;
|
||||
m_3d_model = NULL;
|
||||
m_BiuTo3Dunits = 1.0;
|
||||
|
||||
m_glRC = NULL;
|
||||
}
|
||||
|
||||
|
||||
C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER" ) );
|
||||
|
||||
if( m_glRC )
|
||||
{
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
GL_CONTEXT_MANAGER::Get().DestroyCtx( m_glRC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel( const S3DMODEL &a3DModel )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != NULL );
|
||||
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
// Delete the old model
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||
{
|
||||
m_3d_model = &a3DModel;
|
||||
m_reload_is_needed = true;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Set3DModel(const wxString &aModelPathName)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel with a wxString" ) );
|
||||
|
||||
if( m_cacheManager )
|
||||
{
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName );
|
||||
|
||||
if( model )
|
||||
Set3DModel( (const S3DMODEL &)*model );
|
||||
else
|
||||
Clear3DModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::Clear3DModel()
|
||||
{
|
||||
// Delete the old model
|
||||
m_reload_is_needed = false;
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = NULL;
|
||||
|
||||
m_3d_model = NULL;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_initialize()
|
||||
{
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
//glDepthFunc( GL_LEQUAL );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
// Setup light
|
||||
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
const GLfloat ambient[] = { 0.01f, 0.01f, 0.01f, 1.0f };
|
||||
const GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
// defines a directional light that points along the negative z-axis
|
||||
const GLfloat position[] = { 0.0f, 0.0f, 2.0f * RANGE_SCALE_3D, 0.0f };
|
||||
|
||||
const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, position );
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::ogl_set_arrow_material()
|
||||
{
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
||||
{
|
||||
wxPaintDC( this );
|
||||
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint !IsShown" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// "Makes the OpenGL state that is represented by the OpenGL rendering
|
||||
// context context current, i.e. it will be used by all subsequent OpenGL calls.
|
||||
// This function may only be called when the window is shown on screen"
|
||||
if( m_glRC == NULL )
|
||||
m_glRC = GL_CONTEXT_MANAGER::Get().CreateCtx( this );
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().LockCtx( m_glRC, this );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
// This is done here rather than in a wxSizeEvent handler because our
|
||||
// OpenGL rendering context (and thus viewport setting) is used with
|
||||
// multiple canvases: If we updated the viewport in the wxSizeEvent
|
||||
// handler, changing the size of one canvas causes a viewport setting that
|
||||
// is wrong when next another canvas is repainted.
|
||||
wxSize clientSize = GetClientSize();
|
||||
|
||||
if( !m_ogl_initialized )
|
||||
{
|
||||
m_ogl_initialized = true;
|
||||
ogl_initialize();
|
||||
}
|
||||
|
||||
if( m_reload_is_needed )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = new C_OGL_3DMODEL( *m_3d_model, MATERIAL_MODE_NORMAL );
|
||||
|
||||
// It convert a model as it was a board, so get the max size dimension of the board
|
||||
// and compute the conversion scale
|
||||
m_BiuTo3Dunits = (double)RANGE_SCALE_3D /
|
||||
( (double)m_ogl_3dmodel->GetBBox().GetMaxDimension() *
|
||||
UNITS3D_TO_UNITSPCB );
|
||||
}
|
||||
|
||||
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( clientSize );
|
||||
|
||||
// clear color and depth buffers
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
|
||||
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||
glClearDepth( 1.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Set projection and modelview matrixes
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
|
||||
// Render Model
|
||||
if( m_ogl_3dmodel )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
double modelunit_to_3d_units_factor = m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScaled( modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor );
|
||||
|
||||
// Center model in the render viewport
|
||||
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
|
||||
|
||||
glTranslatef( -model_center.x, -model_center.y, -model_center.z );
|
||||
|
||||
m_ogl_3dmodel->Draw_opaque();
|
||||
m_ogl_3dmodel->Draw_transparent();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
// YxY squared view port
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 );
|
||||
glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
const glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f),
|
||||
SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) );
|
||||
|
||||
const glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix();
|
||||
|
||||
glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
|
||||
|
||||
ogl_set_arrow_material();
|
||||
|
||||
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||
SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ),
|
||||
0.275f );
|
||||
|
||||
// "Swaps the double-buffer of this window, making the back-buffer the
|
||||
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||
// commands is displayed on the window."
|
||||
SwapBuffers();
|
||||
|
||||
GL_CONTEXT_MANAGER::Get().UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent &event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnMouseWheel" ) );
|
||||
|
||||
if( event.ShiftDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() < 0 )
|
||||
//SetView3D( WXK_UP ); // move up
|
||||
//else
|
||||
//SetView3D( WXK_DOWN ); // move down
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() > 0 )
|
||||
//SetView3D( WXK_RIGHT ); // move right
|
||||
//else
|
||||
//SetView3D( WXK_LEFT ); // move left
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackBallCamera.Zoom( event.GetWheelRotation() > 0 ? 1.1f : 1/1.1f );
|
||||
|
||||
//DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void C3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
/*
|
||||
double magnification = ( event.GetMagnification() + 1.0f );
|
||||
GetPrm3DVisu().m_Zoom /= magnification;
|
||||
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||
GetPrm3DVisu().m_Zoom = 0.01;
|
||||
DisplayStatus();
|
||||
Refresh( false );
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent &event )
|
||||
{
|
||||
m_trackBallCamera.SetCurWindowSize( GetClientSize() );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() ) // Drag
|
||||
m_trackBallCamera.Drag( event.GetPosition() );
|
||||
//else if( event.MiddleIsDown() ) // Pan
|
||||
// m_trackBallCamera.Pan( event.GetPosition() );
|
||||
|
||||
// orientation has changed, redraw mesh
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = true;
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent &event )
|
||||
{
|
||||
//m_is_moving_mouse = false;
|
||||
//Refresh( false );
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void C3D_MODEL_VIEWER::OnRightClick( wxMouseEvent &event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright (C) 1992-2019 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file c3d_model_viewer.h
|
||||
* @brief Implements a model viewer canvas. The propose of model viewer is to
|
||||
* render 3d models that come in the original data from the files without any
|
||||
* transformations.
|
||||
*/
|
||||
|
||||
#ifndef _C3D_MODEL_VIEWER_H_
|
||||
#define _C3D_MODEL_VIEWER_H_
|
||||
|
||||
#include "3d_rendering/ctrack_ball.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class C_OGL_3DMODEL;
|
||||
|
||||
/**
|
||||
* Class C3D_MODEL_VIEWER
|
||||
* Implement a canvas based on a wxGLCanvas
|
||||
*/
|
||||
class C3D_MODEL_VIEWER : public HIDPI_GL_CANVAS
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new 3D Canvas with a attribute list
|
||||
* @param aParent = the parent creator of this canvas
|
||||
* @param aAttribList = a list of openGL options created by
|
||||
* COGL_ATT_LIST::GetAttributesList
|
||||
*/
|
||||
C3D_MODEL_VIEWER( wxWindow *aParent,
|
||||
const int *aAttribList = 0,
|
||||
S3D_CACHE *aCacheManager = NULL );
|
||||
|
||||
~C3D_MODEL_VIEWER();
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param a3DModel - 3d model data
|
||||
*/
|
||||
void Set3DModel( const S3DMODEL &a3DModel );
|
||||
|
||||
/**
|
||||
* @brief Set3DModel - Set this model to be displayed
|
||||
* @param aModelPathName - 3d model path name
|
||||
*/
|
||||
void Set3DModel( wxString const& aModelPathName );
|
||||
|
||||
/**
|
||||
* @brief Clear3DModel - Unloads the displayed 3d model
|
||||
*/
|
||||
void Clear3DModel();
|
||||
|
||||
private:
|
||||
void ogl_initialize();
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
private:
|
||||
|
||||
void OnPaint( wxPaintEvent &event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent &event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent &event );
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent &event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent &event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent &event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent &event );
|
||||
|
||||
void OnRightClick( wxMouseEvent &event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
|
||||
private:
|
||||
/// openGL context
|
||||
wxGLContext *m_glRC;
|
||||
|
||||
/// Camera used in this canvas
|
||||
CTRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// Original 3d model data
|
||||
const S3DMODEL *m_3d_model;
|
||||
|
||||
/// Class holder for 3d model to display on openGL
|
||||
C_OGL_3DMODEL *m_ogl_3dmodel;
|
||||
|
||||
/// Flag that we have a new model and it need to be reloaded when the paint is called
|
||||
bool m_reload_is_needed;
|
||||
|
||||
/// Flag if open gl was initialized
|
||||
bool m_ogl_initialized;
|
||||
|
||||
/// factor to convert the model or any other items to keep it in relation to
|
||||
/// the +/-RANGE_SCALE_3D
|
||||
/// (it is named same as the board render for better understanding proposes)
|
||||
double m_BiuTo3Dunits;
|
||||
|
||||
/// Optional cache manager
|
||||
S3D_CACHE* m_cacheManager;
|
||||
|
||||
/**
|
||||
* 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_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar *m_logTrace;
|
||||
};
|
||||
|
||||
#endif // _C3D_MODEL_VIEWER_H_
|
||||
@@ -1,483 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Implements a model viewer canvas. The purpose of the model viewer is to render
|
||||
* 3d models that come in the original data from the files without any transformations.
|
||||
*/
|
||||
|
||||
#include <gal/opengl/kiglew.h> // Must be included first
|
||||
#include <iostream>
|
||||
#include "3d_rendering/opengl/3d_model.h"
|
||||
#include "eda_3d_model_viewer.h"
|
||||
#include "../3d_rendering/opengl/opengl_utils.h"
|
||||
#include "../3d_cache/3d_cache.h"
|
||||
#include <wx/dcclient.h>
|
||||
#include <base_units.h>
|
||||
#include <build_version.h>
|
||||
#include <gal/opengl/gl_context_mgr.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <pgm_base.h>
|
||||
#include <dpi_scaling_common.h>
|
||||
#include <class_draw_panel_gal.h>
|
||||
#include <macros.h>
|
||||
|
||||
/**
|
||||
* Scale conversion from 3d model units to pcb units
|
||||
*/
|
||||
#define UNITS3D_TO_UNITSPCB ( pcbIUScale.IU_PER_MM )
|
||||
|
||||
/**
|
||||
* 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_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*
|
||||
* @ingroup trace_env_vars
|
||||
*/
|
||||
const wxChar* EDA_3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||
|
||||
|
||||
BEGIN_EVENT_TABLE( EDA_3D_MODEL_VIEWER, wxGLCanvas )
|
||||
EVT_PAINT( EDA_3D_MODEL_VIEWER::OnPaint )
|
||||
|
||||
// mouse events
|
||||
EVT_LEFT_DOWN( EDA_3D_MODEL_VIEWER::OnLeftDown )
|
||||
EVT_LEFT_UP( EDA_3D_MODEL_VIEWER::OnLeftUp )
|
||||
EVT_MIDDLE_UP( EDA_3D_MODEL_VIEWER::OnMiddleUp )
|
||||
EVT_MIDDLE_DOWN( EDA_3D_MODEL_VIEWER::OnMiddleDown)
|
||||
EVT_RIGHT_DOWN( EDA_3D_MODEL_VIEWER::OnRightClick )
|
||||
EVT_MOUSEWHEEL( EDA_3D_MODEL_VIEWER::OnMouseWheel )
|
||||
EVT_MOTION( EDA_3D_MODEL_VIEWER::OnMouseMove )
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
EVT_MAGNIFY( EDA_3D_MODEL_VIEWER::OnMagnify )
|
||||
#endif
|
||||
|
||||
// other events
|
||||
EVT_ERASE_BACKGROUND( EDA_3D_MODEL_VIEWER::OnEraseBackground )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
// This defines the range that all coord will have to be rendered.
|
||||
// It will use this value to convert to a normalized value between
|
||||
// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||
#define RANGE_SCALE_3D 8.0f
|
||||
|
||||
|
||||
EDA_3D_MODEL_VIEWER::EDA_3D_MODEL_VIEWER( wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
||||
S3D_CACHE* aCacheManager ) :
|
||||
HIDPI_GL_CANVAS( EDA_DRAW_PANEL_GAL::GetVcSettings(), aParent, aGLAttribs, wxID_ANY,
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxFULL_REPAINT_ON_RESIZE ),
|
||||
m_trackBallCamera( RANGE_SCALE_3D * 4.0f ),
|
||||
m_cacheManager( aCacheManager )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::EDA_3D_MODEL_VIEWER" ) );
|
||||
|
||||
m_ogl_initialized = false;
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
m_3d_model = nullptr;
|
||||
m_BiuTo3dUnits = 1.0;
|
||||
|
||||
m_glRC = nullptr;
|
||||
}
|
||||
|
||||
|
||||
EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER()
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::~EDA_3D_MODEL_VIEWER" ) );
|
||||
GL_CONTEXT_MANAGER* gl_mgr = Pgm().GetGLContextManager();
|
||||
|
||||
if( m_glRC )
|
||||
{
|
||||
gl_mgr->LockCtx( m_glRC, this );
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
gl_mgr->UnlockCtx( m_glRC );
|
||||
gl_mgr->DestroyCtx( m_glRC );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Set3DModel( const S3DMODEL& a3DModel )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::Set3DModel with a S3DMODEL" ) );
|
||||
|
||||
// Validate a3DModel pointers
|
||||
wxASSERT( a3DModel.m_Materials != nullptr );
|
||||
wxASSERT( a3DModel.m_Meshes != nullptr );
|
||||
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||
|
||||
// Delete the old model
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
m_3d_model = nullptr;
|
||||
|
||||
if( ( a3DModel.m_Materials != nullptr ) && ( a3DModel.m_Meshes != nullptr )
|
||||
&& ( a3DModel.m_MaterialsSize > 0 ) && ( a3DModel.m_MeshesSize > 0 ) )
|
||||
{
|
||||
m_3d_model = &a3DModel;
|
||||
m_reload_is_needed = true;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Set3DModel( const wxString& aModelPathName)
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::Set3DModel with a wxString" ) );
|
||||
|
||||
if( m_cacheManager )
|
||||
{
|
||||
const S3DMODEL* model = m_cacheManager->GetModel( aModelPathName, wxEmptyString, nullptr );
|
||||
|
||||
if( model )
|
||||
Set3DModel( (const S3DMODEL &)*model );
|
||||
else
|
||||
Clear3DModel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::Clear3DModel()
|
||||
{
|
||||
// Delete the old model
|
||||
m_reload_is_needed = false;
|
||||
|
||||
delete m_ogl_3dmodel;
|
||||
m_ogl_3dmodel = nullptr;
|
||||
|
||||
m_3d_model = nullptr;
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::ogl_initialize()
|
||||
{
|
||||
const GLenum err = glewInit();
|
||||
|
||||
if( GLEW_OK != err )
|
||||
{
|
||||
const wxString msgError = (const char*) glewGetErrorString( err );
|
||||
|
||||
wxLogMessage( msgError );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::ogl_initialize Using GLEW version %s" ),
|
||||
From_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
|
||||
}
|
||||
|
||||
SetOpenGLInfo( (const char*) glGetString( GL_VENDOR ), (const char*) glGetString( GL_RENDERER ),
|
||||
(const char*) glGetString( GL_VERSION ) );
|
||||
|
||||
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||
|
||||
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glEnable( GL_CULL_FACE );
|
||||
glShadeModel( GL_SMOOTH );
|
||||
glEnable( GL_LINE_SMOOTH );
|
||||
glEnable( GL_NORMALIZE );
|
||||
|
||||
// Setup light
|
||||
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||
const GLfloat ambient[] = { 0.01f, 0.01f, 0.01f, 1.0f };
|
||||
const GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
// defines a directional light that points along the negative z-axis
|
||||
const GLfloat position[] = { 0.0f, 0.0f, 2.0f * RANGE_SCALE_3D, 0.0f };
|
||||
|
||||
const GLfloat lmodel_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||
glLightfv( GL_LIGHT0, GL_POSITION, position );
|
||||
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::ogl_set_arrow_material()
|
||||
{
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||
|
||||
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnPaint( wxPaintEvent& event )
|
||||
{
|
||||
event.Skip( false );
|
||||
|
||||
// SwapBuffer requires the window to be shown before calling
|
||||
if( !IsShownOnScreen() )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint !IsShown" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
// "Makes the OpenGL state that is represented by the OpenGL rendering
|
||||
// context context current, i.e. it will be used by all subsequent OpenGL calls.
|
||||
// This function may only be called when the window is shown on screen"
|
||||
if( m_glRC == nullptr )
|
||||
m_glRC = Pgm().GetGLContextManager()->CreateCtx( this );
|
||||
|
||||
// CreateCtx could and does fail per sentry crash events, lets be graceful
|
||||
if( m_glRC == nullptr )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint creating gl context failed" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Pgm().GetGLContextManager()->LockCtx( m_glRC, this );
|
||||
|
||||
// Set the OpenGL viewport according to the client size of this canvas.
|
||||
// This is done here rather than in a wxSizeEvent handler because our
|
||||
// OpenGL rendering context (and thus viewport setting) is used with
|
||||
// multiple canvases: If we updated the viewport in the wxSizeEvent
|
||||
// handler, changing the size of one canvas causes a viewport setting that
|
||||
// is wrong when next another canvas is repainted.
|
||||
wxSize clientSize = GetNativePixelSize();
|
||||
|
||||
if( !m_ogl_initialized )
|
||||
{
|
||||
m_ogl_initialized = true;
|
||||
ogl_initialize();
|
||||
}
|
||||
|
||||
if( m_reload_is_needed )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||
|
||||
m_reload_is_needed = false;
|
||||
m_ogl_3dmodel = new MODEL_3D( *m_3d_model, MATERIAL_MODE::NORMAL );
|
||||
|
||||
// It convert a model as it was a board, so get the max size dimension of the board
|
||||
// and compute the conversion scale
|
||||
m_BiuTo3dUnits =
|
||||
(double) RANGE_SCALE_3D
|
||||
/ ( (double) m_ogl_3dmodel->GetBBox().GetMaxDimension() * UNITS3D_TO_UNITSPCB );
|
||||
}
|
||||
|
||||
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( clientSize );
|
||||
|
||||
// clear color and depth buffers
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
glClearDepth( 1.0f );
|
||||
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
// Set projection and modelview matrices
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) );
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||
glEnable( GL_LIGHTING );
|
||||
glEnable( GL_LIGHT0 );
|
||||
|
||||
// Render Model
|
||||
if( m_ogl_3dmodel )
|
||||
{
|
||||
glPushMatrix();
|
||||
|
||||
double modelunit_to_3d_units_factor = m_BiuTo3dUnits * UNITS3D_TO_UNITSPCB;
|
||||
|
||||
glScaled( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor,
|
||||
modelunit_to_3d_units_factor );
|
||||
|
||||
// Center model in the render viewport
|
||||
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
|
||||
|
||||
glTranslatef( -model_center.x, -model_center.y, -model_center.z );
|
||||
|
||||
m_ogl_3dmodel->BeginDrawMulti( true );
|
||||
|
||||
m_ogl_3dmodel->DrawOpaque( false );
|
||||
|
||||
glDepthMask( GL_FALSE );
|
||||
glEnable( GL_BLEND );
|
||||
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
m_ogl_3dmodel->DrawTransparent( 1.0f, false );
|
||||
|
||||
glDisable( GL_BLEND );
|
||||
glDepthMask( GL_TRUE );
|
||||
|
||||
m_ogl_3dmodel->EndDrawMulti();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// YxY squared view port
|
||||
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 );
|
||||
glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
glMatrixMode( GL_PROJECTION );
|
||||
glLoadIdentity();
|
||||
gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f );
|
||||
|
||||
glMatrixMode( GL_MODELVIEW );
|
||||
glLoadIdentity();
|
||||
|
||||
const glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f),
|
||||
SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) );
|
||||
|
||||
const glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix();
|
||||
|
||||
glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
|
||||
|
||||
ogl_set_arrow_material();
|
||||
|
||||
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||
DrawRoundArrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||
DrawRoundArrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ),
|
||||
0.275f );
|
||||
|
||||
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||
DrawRoundArrow( SFVEC3F( 0.0f, 0.0f, 0.0f ), SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ),
|
||||
0.275f );
|
||||
|
||||
// "Swaps the double-buffer of this window, making the back-buffer the
|
||||
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||
// commands is displayed on the window."
|
||||
SwapBuffers();
|
||||
|
||||
Pgm().GetGLContextManager()->UnlockCtx( m_glRC );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent& event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||
// Do nothing, to avoid flashing.
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent& event )
|
||||
{
|
||||
wxLogTrace( m_logTrace, wxT( "EDA_3D_MODEL_VIEWER::OnMouseWheel" ) );
|
||||
|
||||
if( event.ShiftDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() < 0 )
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_UP ); // move up
|
||||
//else
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_DOWN ); // move down
|
||||
}
|
||||
else if( event.ControlDown() )
|
||||
{
|
||||
//if( event.GetWheelRotation() > 0 )
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_RIGHT ); // move right
|
||||
//else
|
||||
//SetView3D( VIEW_3D_TYPE::VIEW3D_PAN_LEFT ); // move left
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackBallCamera.Zoom( event.GetWheelRotation() > 0 ? 1.1f : 1/1.1f );
|
||||
|
||||
//DisplayStatus();
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void EDA_3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent& event )
|
||||
{
|
||||
const wxSize& nativeWinSize = GetNativePixelSize();
|
||||
const wxPoint& nativePosition = GetNativePosition( event.GetPosition() );
|
||||
|
||||
m_trackBallCamera.SetCurWindowSize( nativeWinSize );
|
||||
|
||||
if( event.Dragging() )
|
||||
{
|
||||
if( event.LeftIsDown() ) // Drag
|
||||
m_trackBallCamera.Drag( nativePosition );
|
||||
|
||||
// orientation has changed, redraw mesh
|
||||
Refresh( false );
|
||||
}
|
||||
|
||||
m_trackBallCamera.SetCurMousePosition( nativePosition );
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
|
||||
void EDA_3D_MODEL_VIEWER::OnRightClick( wxMouseEvent& event )
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||
* Copyright The 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 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eda_3d_model_viewer.h
|
||||
* @brief Implements a model viewer canvas.
|
||||
*
|
||||
* The purpose of model viewer is to render 3d models that come in the original data from
|
||||
* the files without any transformations.
|
||||
*/
|
||||
|
||||
#ifndef _C3D_MODEL_VIEWER_H_
|
||||
#define _C3D_MODEL_VIEWER_H_
|
||||
|
||||
#include "3d_rendering/track_ball.h"
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
|
||||
class S3D_CACHE;
|
||||
class MODEL_3D;
|
||||
|
||||
/**
|
||||
* Implement a canvas based on a wxGLCanvas.
|
||||
*/
|
||||
class EDA_3D_MODEL_VIEWER : public HIDPI_GL_CANVAS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create a new 3D Canvas with a attribute list.
|
||||
*
|
||||
* @param aParent the parent creator of this canvas.
|
||||
* @param aGLAttribs openGL attributes created by #OGL_ATT_LIST::GetAttributesList.
|
||||
*/
|
||||
EDA_3D_MODEL_VIEWER( wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
||||
S3D_CACHE* aCacheManager = nullptr );
|
||||
|
||||
~EDA_3D_MODEL_VIEWER();
|
||||
|
||||
/**
|
||||
* Set this model to be displayed.
|
||||
*
|
||||
* @param a3DModel 3D model data.
|
||||
*/
|
||||
void Set3DModel( const S3DMODEL& a3DModel );
|
||||
|
||||
/**
|
||||
* Set this model to be displayed.
|
||||
*
|
||||
* N.B. This will not load a model from the internal cache. Only from on disk.
|
||||
*
|
||||
* @param aModelPathName 3D model path name. Must be a file on disk.
|
||||
*/
|
||||
void Set3DModel( const wxString& aModelPathName );
|
||||
|
||||
/**
|
||||
* Unload the displayed 3D model.
|
||||
*/
|
||||
void Clear3DModel();
|
||||
|
||||
private:
|
||||
void ogl_initialize();
|
||||
void ogl_set_arrow_material();
|
||||
|
||||
void OnPaint( wxPaintEvent& event );
|
||||
|
||||
void OnEraseBackground( wxEraseEvent& event );
|
||||
|
||||
void OnMouseWheel( wxMouseEvent& event );
|
||||
|
||||
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||
void OnMagnify( wxMouseEvent& event );
|
||||
#endif
|
||||
|
||||
void OnMouseMove( wxMouseEvent& event );
|
||||
|
||||
void OnLeftDown( wxMouseEvent& event );
|
||||
|
||||
void OnLeftUp( wxMouseEvent& event );
|
||||
|
||||
void OnMiddleUp( wxMouseEvent& event );
|
||||
|
||||
void OnMiddleDown( wxMouseEvent& event );
|
||||
|
||||
void OnRightClick( wxMouseEvent& event );
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
/// openGL context
|
||||
wxGLContext* m_glRC;
|
||||
|
||||
/// Camera used in this canvas
|
||||
TRACK_BALL m_trackBallCamera;
|
||||
|
||||
/// Original 3d model data
|
||||
const S3DMODEL* m_3d_model;
|
||||
|
||||
/// Class holder for 3d model to display on openGL
|
||||
MODEL_3D* m_ogl_3dmodel;
|
||||
|
||||
/// Flag that we have a new model and it need to be reloaded when the paint is called
|
||||
bool m_reload_is_needed;
|
||||
|
||||
/// Flag if open gl was initialized
|
||||
bool m_ogl_initialized;
|
||||
|
||||
/// factor to convert the model or any other items to keep it in relation to
|
||||
/// the +/-RANGE_SCALE_3D
|
||||
/// (it is named same as the board render for better understanding proposes)
|
||||
double m_BiuTo3dUnits;
|
||||
|
||||
/// Optional cache manager
|
||||
S3D_CACHE* m_cacheManager;
|
||||
|
||||
/**
|
||||
* 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_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||
* more information.
|
||||
*/
|
||||
static const wxChar* m_logTrace;
|
||||
};
|
||||
|
||||
#endif // _C3D_MODEL_VIEWER_H_
|
||||
@@ -1,27 +0,0 @@
|
||||
add_library(3d-viewer_navlib STATIC
|
||||
"nl_3d_viewer_plugin.cpp"
|
||||
"nl_3d_viewer_plugin_impl.cpp"
|
||||
"nl_footprint_properties_plugin.cpp"
|
||||
"nl_footprint_properties_plugin_impl.cpp"
|
||||
)
|
||||
|
||||
# 3d-viewer_navlib depends on make_lexer outputs in common
|
||||
add_dependencies( 3d-viewer_navlib pcbcommon )
|
||||
|
||||
# Find the 3DxWare SDK component 3DxWare::NlClient
|
||||
# find_package(TDxWare_SDK 4.0 REQUIRED COMPONENTS 3DxWare::Navlib)
|
||||
target_compile_definitions(3d-viewer_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_DEFINITIONS>
|
||||
)
|
||||
target_compile_options(3d-viewer_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_COMPILE_OPTIONS>
|
||||
)
|
||||
target_include_directories(3d-viewer_navlib PRIVATE
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_INCLUDE_DIRECTORIES>
|
||||
$<TARGET_PROPERTY:pcbnew_kiface_objects,INCLUDE_DIRECTORIES>
|
||||
)
|
||||
target_link_libraries(3d-viewer_navlib
|
||||
$<TARGET_PROPERTY:3DxWare::Navlib,INTERFACE_LINK_LIBRARIES>
|
||||
3DxWare::Navlib
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user