From b92a1fa558998cb0f5975ed3e0c21958695414ae Mon Sep 17 00:00:00 2001 From: Ivan Pelipenko Date: Tue, 25 Aug 2020 22:24:02 +0300 Subject: [PATCH] moved to shstk --- .gitignore | 3 - .gitmodules | 3 - CMakeLists.txt | 281 +-- Jenkinsfile | 62 - README.md | 50 +- SDKMacros.cmake | 107 - cd_utils/CMakeLists.txt | 37 - cd_utils/cdtest.h | 10 - cd_utils/cdutils_c.cpp | 41 - cd_utils/cdutils_c.h | 46 - cd_utils/cdutils_core.cpp | 606 ----- cd_utils/cdutils_core.h | 147 -- cd_utils/cdutils_interface.cpp | 217 -- cd_utils/cdutils_interface.h | 96 - cd_utils/cdutils_k.cpp | 20 - cd_utils/cdutils_k.h | 47 - cd_utils/cdutils_m.cpp | 22 - cd_utils/cdutils_m.h | 56 - cd_utils/cdutils_parser.cpp | 196 -- cd_utils/cdutils_parser.h | 39 - cd_utils/cdutils_protocol.h | 73 - cd_utils/cdutils_types.cpp | 762 ------ cd_utils/cdutils_types.h | 193 -- cd_utils/cdutils_x.cpp | 55 - cd_utils/cdutils_x.h | 57 - cd_utils/cdutilstest.cpp | 97 - cd_utils/k_description.h | 147 -- {qad/cmake => cmake}/FindQAD.cmake | 0 {qad/cmake => cmake}/QADMacros.cmake | 0 {qad/cmake => cmake}/QtWraps.cmake | 1622 ++++++------ cmake_android.bat | 50 - cmake_android.sh | 3 - docker/android-libs/Dockerfile | 43 - docker/debian-libs/Dockerfile | 17 - docker/osx-libs/Dockerfile | 21 - docker/pi-libs/Dockerfile | 21 - docker/windows-libs/Dockerfile | 21 - {qad/icons => icons}/align-bottom-center.png | Bin {qad/icons => icons}/align-bottom-left.png | Bin {qad/icons => icons}/align-bottom-right.png | Bin {qad/icons => icons}/align-center-center.png | Bin {qad/icons => icons}/align-center-left.png | Bin {qad/icons => icons}/align-center-right.png | Bin {qad/icons => icons}/align-hor.png | Bin {qad/icons => icons}/align-top-center.png | Bin {qad/icons => icons}/align-top-left.png | Bin {qad/icons => icons}/align-top-right.png | Bin {qad/icons => icons}/align-ver.png | Bin {kx_utils/icons => icons}/alpha.png | Bin {qad/icons => icons}/application-exit.png | Bin {qad/icons => icons}/archive-extract.png | Bin .../archive-insert-directory.png | Bin {qad/icons => icons}/archive-insert.png | Bin {qad/icons => icons}/arrow-down.png | Bin {qad/icons => icons}/arrow-up.png | Bin {qad/icons => icons}/axis_x.png | Bin {qad/icons => icons}/axis_y.png | Bin {qad/icons => icons}/blockview.png | Bin {qad/icons => icons}/blockview.xcf | Bin {qad/icons => icons}/border-line.png | Bin {qad/icons => icons}/button.png | Bin {qad/icons => icons}/case-sensitive.png | Bin {qad/icons => icons}/chardialog.png | Bin {qad/icons => icons}/checkbox-unchecked.png | Bin {qad/icons => icons}/checkbox.png | Bin {qad/icons => icons}/clear-history.png | Bin {qad/icons => icons}/clineedit.png | Bin {qad/icons => icons}/code-error.png | Bin {qad/icons => icons}/code-parents.png | Bin {qad/icons => icons}/code-struct.png | Bin {qad/icons => icons}/code-union.png | Bin {qad/icons => icons}/code-variable.png | Bin {qad/icons => icons}/code-word.png | Bin {qad/icons => icons}/colorbutton.png | Bin {qad/icons => icons}/configure.png | Bin {qad/icons => icons}/configure_16.png | Bin {qad/icons => icons}/database.png | Bin {qad/icons => icons}/dialog-cancel.png | Bin {qad/icons => icons}/dialog-close.png | Bin {qad/icons => icons}/dialog-information.png | Bin {qad/icons => icons}/dialog-ok-apply.png | Bin {qad/icons => icons}/dialog-warning.png | Bin {qad/icons => icons}/document-close.png | Bin {qad/icons => icons}/document-edit.png | Bin {qad/icons => icons}/document-new.png | Bin {qad/icons => icons}/document-open-recent.png | Bin {qad/icons => icons}/document-open.png | Bin {qad/icons => icons}/document-open_16.png | Bin {qad/icons => icons}/document-print.png | Bin {qad/icons => icons}/document-revert.png | Bin {qad/icons => icons}/document-save-all.png | Bin {qad/icons => icons}/document-save-as.png | Bin {qad/icons => icons}/document-save.png | Bin {qad/icons => icons}/draw-ellipse.png | Bin {qad/icons => icons}/draw-line.png | Bin {qad/icons => icons}/draw-rectangle.png | Bin {qad/icons => icons}/draw-text.png | Bin {qad/icons => icons}/ecombobox.png | Bin .../edit-clear-locationbar-rtl.png | Bin {qad/icons => icons}/edit-clear.png | Bin {qad/icons => icons}/edit-copy.png | Bin {qad/icons => icons}/edit-delete.png | Bin {project_fs/icons => icons}/edit-find.png | Bin {qad/icons => icons}/edit-find_16.png | Bin {qad/icons => icons}/edit-guides.png | Bin {qad/icons => icons}/edit-paste.png | Bin {qad/icons => icons}/edit-redo.png | Bin .../edit-table-insert-row-below.png | Bin {qad/icons => icons}/edit-undo.png | Bin {qad/icons => icons}/edockwidget.png | Bin {qad/icons => icons}/etabwidget.png | Bin {qad/icons => icons}/evalspinbox.png | Bin {qad/icons => icons}/expand_s_x.png | Bin {qad/icons => icons}/expand_s_y.png | Bin {qad/icons => icons}/expand_x.png | Bin {qad/icons => icons}/expand_y.png | Bin {qad/icons => icons}/f1.png | Bin {qad/icons => icons}/format-fill-color.png | Bin {qad/icons => icons}/format-stroke-color.png | Bin .../icons => icons}/format-text-subscript.png | Bin {qad/icons => icons}/games-solve.png | Bin {qad/icons => icons}/go-next.png | Bin {qad/icons => icons}/go-previous.png | Bin {qad/icons => icons}/graphic.png | Bin {qad/icons => icons}/graphics.png | Bin {qad/icons => icons}/historyview.png | Bin {qad/icons => icons}/icons.xcf | Bin {kx_utils/icons => icons}/item-add.png | Bin {kx_utils/icons => icons}/item.png | Bin {qad/icons => icons}/lastmoves.png | Bin {qad/icons => icons}/layer-visible-off.png | Bin {qad/icons => icons}/layer-visible-on.png | Bin {qad/icons => icons}/led_3.png | Bin {qad/icons => icons}/led_gray.png | Bin {qad/icons => icons}/led_off.png | Bin {qad/icons => icons}/led_on.png | Bin {qad/icons => icons}/legend.png | Bin {qad/icons => icons}/list-add.png | Bin {qad/icons => icons}/list-remove.png | Bin {qad/icons => icons}/log_parser.png | Bin {qad/icons => icons}/logview.png | Bin {qad/icons => icons}/mail.png | Bin {qad/icons => icons}/media-playback-pause.png | Bin {qad/icons => icons}/media-playback-start.png | Bin {qad/icons => icons}/media-playback-stop.png | Bin {qad/icons => icons}/media-record.png | Bin {qad/icons => icons}/media-skip-forward.png | Bin {kx_utils/icons => icons}/node-add.png | Bin {kx_utils/icons => icons}/node.png | Bin {qad/icons => icons}/pause-back.png | Bin {qad/icons => icons}/pause-front.png | Bin {qad/icons => icons}/qcodeedit.png | Bin {qad/icons => icons}/qpiconsole.png | Bin {qad/icons => icons}/qt.png | Bin {qad/icons => icons}/quickopen.png | Bin {qad/icons => icons}/qvariantedit.png | Bin {qad/icons => icons}/scroll_spin.png | Bin {qad/icons => icons}/select-all.png | Bin {qad/icons => icons}/select-none.png | Bin {qad/icons => icons}/spinslider.png | Bin {qad/icons => icons}/sql_table.png | Bin {qad/icons => icons}/tools-wizard.png | Bin {qad/icons => icons}/touchbuttframe.png | Bin {qad/icons => icons}/touchbutton.png | Bin {qad/icons => icons}/touchslider.png | Bin {qad/icons => icons}/transform-move.png | Bin {qad/icons => icons}/variable-add.png | Bin {qad/icons => icons}/variable-copy.png | Bin {qad/icons => icons}/variable-edit.png | Bin {qad/icons => icons}/variable-remove.png | Bin {qad/icons => icons}/view-autofit.png | Bin {qad/icons => icons}/view-fullscreen.png | Bin {qad/icons => icons}/view-grid.png | Bin {qad/icons => icons}/view-preview.png | Bin {qad/icons => icons}/view-refresh.png | Bin {qad/icons => icons}/z-bottom.png | Bin {qad/icons => icons}/z-down.png | Bin {qad/icons => icons}/z-top.png | Bin {qad/icons => icons}/z-up.png | Bin {qad/icons => icons}/zoom-draw.png | Bin {qad/icons => icons}/zoom-fit-best.png | Bin {qad/icons => icons}/zoom-in.png | Bin {qad/icons => icons}/zoom-original.png | Bin {qad/icons => icons}/zoom-out.png | Bin {qad/icons => icons}/zoom-range.png | Bin {qad/icons => icons}/zoom-rect.png | Bin {qad/icons => icons}/zoom-select.png | Bin kx_utils/CMakeLists.txt | 76 - kx_utils/clean | 4 - kx_utils/clean.bat | 4 - kx_utils/icons/accessories-calculator.png | Bin 1525 -> 0 bytes kx_utils/icons/archive-extract.png | Bin 1005 -> 0 bytes kx_utils/icons/document-export.png | Bin 1106 -> 0 bytes kx_utils/icons/document-import.png | Bin 1017 -> 0 bytes kx_utils/icons/document-open.png | Bin 1798 -> 0 bytes kx_utils/icons/document-save-.png | Bin 1263 -> 0 bytes kx_utils/icons/edit-clear-.png | Bin 2066 -> 0 bytes kx_utils/icons/edit-find-.png | Bin 1631 -> 0 bytes kx_utils/icons/expand_s_x.png | Bin 571 -> 0 bytes kx_utils/icons/expand_s_y.png | Bin 577 -> 0 bytes kx_utils/icons/expand_x.png | Bin 579 -> 0 bytes kx_utils/icons/expand_y.png | Bin 577 -> 0 bytes kx_utils/icons/layer-visible-off.png | Bin 1766 -> 0 bytes kx_utils/icons/layer-visible-on.png | Bin 2001 -> 0 bytes kx_utils/icons/media-playback-pause.png | Bin 1145 -> 0 bytes kx_utils/icons/media-playback-stop.png | Bin 1165 -> 0 bytes kx_utils/icons/media-record.png | Bin 1843 -> 0 bytes kx_utils/icons/view-refresh.png | Bin 2182 -> 0 bytes kx_utils/icons/zoom-fit-height.png | Bin 929 -> 0 bytes kx_utils/kx_coeffs.cpp | 194 -- kx_utils/kx_coeffs.h | 95 - kx_utils/kx_protocol_c.h | 126 - kx_utils/kx_protocol_x.h | 121 - kx_utils/kx_pult.conf | 0 kx_utils/kx_pult.cpp | 848 ------- kx_utils/kx_pult.h | 170 -- kx_utils/kx_pult.qrc | 40 - kx_utils/kx_pult.ui | 1311 ---------- kx_utils/main_kx_pult.cpp | 10 - kx_utils/make_lib.bat | 1 - kx_utils/piprotocol.cpp | 718 ------ kx_utils/piprotocol.h | 238 -- {qad/libs => libs}/CMakeLists.txt | 0 {qad/libs => libs}/application/CMakeLists.txt | 0 .../libs => libs}/application/aboutwindow.cpp | 0 {qad/libs => libs}/application/aboutwindow.h | 0 {qad/libs => libs}/application/aboutwindow.ui | 0 .../libs => libs}/application/edockwidget.cpp | 0 {qad/libs => libs}/application/edockwidget.h | 0 .../libs => libs}/application/emainwindow.cpp | 0 {qad/libs => libs}/application/emainwindow.h | 0 {qad/libs => libs}/application/etabwidget.cpp | 0 {qad/libs => libs}/application/etabwidget.h | 0 .../libs => libs}/application/historyview.cpp | 0 {qad/libs => libs}/application/historyview.h | 0 .../application/lang/qad_application_en.ts | 0 .../application/lang/qad_application_ru.ts | 0 .../libs => libs}/application/lang/update.bat | 0 {qad/libs => libs}/application/logview.cpp | 0 {qad/libs => libs}/application/logview.h | 0 {qad/libs => libs}/application/logview.ui | 0 .../application/plugin/CMakeLists.txt | 0 .../application/plugin/edockwidgetplugin.cpp | 0 .../application/plugin/edockwidgetplugin.h | 0 .../application/plugin/emainwindowplugin.cpp | 0 .../application/plugin/emainwindowplugin.h | 0 .../application/plugin/historyviewplugin.cpp | 0 .../application/plugin/historyviewplugin.h | 0 .../application/plugin/logviewplugin.cpp | 0 .../application/plugin/logviewplugin.h | 0 .../application/plugin/qad_application.cpp | 0 .../application/plugin/qad_application.h | 0 .../application/qad_application.qrc | 0 .../application/qsingleapplication.cpp | 0 .../application/qsingleapplication.h | 0 {qad/libs => libs}/application/ribbon.cpp | 0 {qad/libs => libs}/application/ribbon.h | 0 {qad/libs => libs}/blockview/CMakeLists.txt | 0 .../blockview/alignedtextitem.cpp | 0 .../libs => libs}/blockview/alignedtextitem.h | 0 {qad/libs => libs}/blockview/blockbase.cpp | 0 {qad/libs => libs}/blockview/blockbase.h | 0 {qad/libs => libs}/blockview/blockbusitem.cpp | 0 {qad/libs => libs}/blockview/blockbusitem.h | 0 {qad/libs => libs}/blockview/blockeditor.cpp | 0 {qad/libs => libs}/blockview/blockeditor.h | 0 {qad/libs => libs}/blockview/blockeditor.ui | 0 {qad/libs => libs}/blockview/blockitem.cpp | 0 {qad/libs => libs}/blockview/blockitem.h | 0 {qad/libs => libs}/blockview/blockitempin.cpp | 0 {qad/libs => libs}/blockview/blockitempin.h | 0 {qad/libs => libs}/blockview/blockview.cpp | 0 {qad/libs => libs}/blockview/blockview.h | 0 .../blockview/blockviewwavetrace.cpp | 0 .../blockview/blockviewwavetrace.h | 0 {qad/libs => libs}/blockview/drawtools.cpp | 0 {qad/libs => libs}/blockview/drawtools.h | 0 {qad/libs => libs}/blockview/drawtools.ui | 0 .../blockview/lang/qad_blockview_en.ts | 0 .../blockview/lang/qad_blockview_ru.ts | 0 {qad/libs => libs}/blockview/lang/update.bat | 0 .../blockview/plugin/CMakeLists.txt | 0 .../blockview/plugin/blockviewplugin.cpp | 0 .../blockview/plugin/blockviewplugin.h | 0 .../blockview/plugin/qad_blockview.cpp | 0 .../blockview/plugin/qad_blockview.h | 0 .../libs => libs}/blockview/qad_blockview.qrc | 0 {qad/libs => libs}/doc/CMakeLists.txt | 0 {qad/libs => libs}/doc/markdown.cpp | 0 {qad/libs => libs}/doc/markdown.h | 0 {qad/libs => libs}/graphic/CMakeLists.txt | 0 {qad/libs => libs}/graphic/graphic.cpp | 0 {qad/libs => libs}/graphic/graphic.h | 0 {qad/libs => libs}/graphic/graphic.ui | 0 {qad/libs => libs}/graphic/graphic_conf.cpp | 0 {qad/libs => libs}/graphic/graphic_conf.h | 0 {qad/libs => libs}/graphic/graphic_conf.ui | 0 .../graphic/lang/qad_graphic_en.ts | 0 .../graphic/lang/qad_graphic_ru.ts | 0 {qad/libs => libs}/graphic/lang/update.bat | 0 .../graphic/plugin/CMakeLists.txt | 0 .../graphic/plugin/graphicplugin.cpp | 0 .../graphic/plugin/graphicplugin.h | 0 .../graphic/plugin/qad_graphic.cpp | 0 .../graphic/plugin/qad_graphic.h | 0 {qad/libs => libs}/graphic/qad_graphic.qrc | 0 {qad/libs => libs}/graphic/uglwidget.h | 0 {qad/libs => libs}/graphic/uwidget.h | 0 {piqt/libs/core => libs/piqt}/CMakeLists.txt | 0 {piqt/libs/core => libs/piqt}/piqt.cpp | 0 {piqt/libs/core => libs/piqt}/piqt.h | 0 .../libs/core => libs/piqt}/qpiconnection.cpp | 0 {piqt/libs/core => libs/piqt}/qpiconnection.h | 0 .../piqt_widgets}/CMakeLists.txt | 0 .../piqt_widgets}/piqt_connection_edit.cpp | 0 .../piqt_widgets}/piqt_connection_edit.h | 0 .../piqt_widgets}/piqt_connection_edit.ui | 0 .../piqt_widgets}/piqt_connection_view.cpp | 0 .../piqt_widgets}/piqt_connection_view.h | 0 .../piqt_widgets}/piqt_highlighter.cpp | 0 .../piqt_widgets}/piqt_highlighter.h | 0 .../piqt_widgets}/piqt_iodevice_edit.cpp | 0 .../piqt_widgets}/piqt_iodevice_edit.h | 0 .../piqt_iodevice_edit_dialog.cpp | 0 .../piqt_widgets}/piqt_iodevice_edit_dialog.h | 0 .../piqt_iodevice_edit_dialog.ui | 0 {piqt/libs => libs}/qcd/CMakeLists.txt | 0 {piqt/libs => libs}/qcd/qcd_core.cpp | 0 {piqt/libs => libs}/qcd/qcd_core.h | 0 {piqt/libs => libs}/qcd/qcd_graphic.cpp | 0 {piqt/libs => libs}/qcd/qcd_graphic.h | 0 {piqt/libs => libs}/qcd/qcd_graphic.ui | 0 {piqt/libs => libs}/qcd/qcd_modedialog.cpp | 0 {piqt/libs => libs}/qcd/qcd_modedialog.h | 0 {piqt/libs => libs}/qcd/qcd_modedialog.ui | 0 {piqt/libs => libs}/qcd/qcd_model.cpp | 0 {piqt/libs => libs}/qcd/qcd_model.h | 0 {piqt/libs => libs}/qcd/qcd_view.cpp | 0 {piqt/libs => libs}/qcd/qcd_view.h | 0 {qglview => libs/qglview}/CMakeLists.txt | 16 +- {cd_utils => libs/qglview}/LICENSE.txt | 0 {qglview => libs/qglview}/glcamera.cpp | 0 {qglview => libs/qglview}/glcamera.h | 0 {qglview => libs/qglview}/glframebuffer.cpp | 0 {qglview => libs/qglview}/glframebuffer.h | 0 {qglview => libs/qglview}/glmaterial.cpp | 0 {qglview => libs/qglview}/glmaterial.h | 0 {qglview => libs/qglview}/globject.cpp | 0 {qglview => libs/qglview}/globject.h | 0 {qglview => libs/qglview}/globject_editor.cpp | 0 {qglview => libs/qglview}/globject_editor.h | 0 {qglview => libs/qglview}/globject_editor.ui | 0 .../qglview}/glparticles_system.cpp | 0 .../qglview}/glparticles_system.h | 0 {qglview => libs/qglview}/glprimitives.cpp | 0 {qglview => libs/qglview}/glprimitives.h | 0 {qglview => libs/qglview}/glrendererbase.cpp | 0 {qglview => libs/qglview}/glrendererbase.h | 0 {qglview => libs/qglview}/glshaders.cpp | 0 {qglview => libs/qglview}/glshaders.h | 0 .../qglview}/gltexture_manager.cpp | 0 {qglview => libs/qglview}/gltexture_manager.h | 0 {qglview => libs/qglview}/gltypes.cpp | 0 {qglview => libs/qglview}/gltypes.h | 0 {qglview => libs/qglview}/glvbo.cpp | 0 {qglview => libs/qglview}/glvbo.h | 0 {qglview => libs/qglview}/glwidget.cpp | 472 ++-- {qglview => libs/qglview}/glwidget.h | 176 +- {qad => libs/qglview}/icons/alpha.png | Bin .../qglview}/icons/application-exit.png | Bin .../qglview}/icons/configure.png | Bin .../qglview}/icons/dialog-close.png | Bin .../qglview}/icons/document-import.png | Bin .../qglview}/icons/document-new.png | Bin .../qglview}/icons/document-open.png | Bin .../qglview}/icons/document-save-.png | Bin .../qglview}/icons/document-save-all.png | Bin .../qglview}/icons/document-save.png | Bin .../icons/edit-clear-locationbar-rtl.png | Bin .../qglview}/icons/edit-clear.png | Bin .../qglview}/icons/edit-copy.png | Bin .../qglview}/icons/edit-delete.png | Bin .../qglview}/icons/edit-find.png | Bin .../qglview}/icons/edit-guides.png | Bin .../qglview}/icons/edit-paste.png | Bin {qad => libs/qglview}/icons/item-add.png | Bin {qad => libs/qglview}/icons/item.png | Bin {kx_utils => libs/qglview}/icons/list-add.png | Bin {qad => libs/qglview}/icons/node-add.png | Bin {qad => libs/qglview}/icons/node.png | Bin {qglengine => libs/qglview}/icons/qglview.png | Bin {qglengine => libs/qglview}/icons/qglview.xcf | Bin .../qglview}/icons/type-camera.png | Bin {qglview => libs/qglview}/icons/type-geo.png | Bin .../qglview}/icons/type-light.png | Bin .../qglview}/icons/view-grid.png | Bin .../qglview}/icons/zoom-fit-best.png | Bin {qglview => libs/qglview}/loader_3ds.cpp | 0 {qglview => libs/qglview}/loader_3ds.h | 0 {qglview => libs/qglview}/loader_ase.cpp | 0 {qglview => libs/qglview}/loader_ase.h | 0 {qglview => libs/qglview}/loader_dae.cpp | 0 {qglview => libs/qglview}/loader_dae.h | 0 {qglview => libs/qglview}/loader_obj.cpp | 0 {qglview => libs/qglview}/loader_obj.h | 0 {qglview => libs/qglview}/loader_qgl.cpp | 0 {qglview => libs/qglview}/loader_qgl.h | 0 {qglview => libs/qglview}/material_editor.cpp | 0 {qglview => libs/qglview}/material_editor.h | 0 {qglview => libs/qglview}/material_editor.ui | 0 .../qglview}/material_map_editor.cpp | 0 .../qglview}/material_map_editor.h | 0 .../qglview}/material_map_editor.ui | 0 {qglview => libs/qglview}/openglwindow.cpp | 192 +- {qglview => libs/qglview}/openglwindow.h | 72 +- .../qglview}/plugin/CMakeLists.txt | 2 +- .../plugin/qglview_designerplugin.cpp | 0 .../qglview}/plugin/qglview_designerplugin.h | 0 .../qglview}/plugin/qglviewplugin.cpp | 0 .../qglview}/plugin/qglviewplugin.h | 0 {qglview => libs/qglview}/propertyeditor.cpp | 0 {qglview => libs/qglview}/propertyeditor.h | 0 {qglview => libs/qglview}/qglview.cpp | 1692 ++++++------- {qglview => libs/qglview}/qglview.h | 602 ++--- {qglview => libs/qglview}/qglview.qrc | 0 .../qglview}/qglview_test/main.cpp | 0 .../qglview}/qglview_test/qglview_window.cpp | 0 .../qglview}/qglview_test/qglview_window.h | 0 .../qglview}/qglview_test/qglview_window.ui | 0 .../qglview}/renderer_deferred_shading.cpp | 0 .../qglview}/renderer_deferred_shading.h | 0 {qglview => libs/qglview}/renderer_simple.cpp | 0 {qglview => libs/qglview}/renderer_simple.h | 0 {qglview => libs/qglview}/shaders/FXAA.frag | 0 {qglview => libs/qglview}/shaders/FXAA.vert | 0 .../qglview}/shaders/bloom_0.frag | 0 .../qglview}/shaders/bloom_1.frag | 0 .../qglview}/shaders/bloom_pass_0.frag | 0 .../qglview}/shaders/bloom_pass_0.vert | 0 .../qglview}/shaders/bloom_pass_1.frag | 0 .../qglview}/shaders/bloom_pass_1.vert | 0 {qglview => libs/qglview}/shaders/dof.frag | 0 {qglview => libs/qglview}/shaders/dof.vert | 0 .../qglview}/shaders/downscale.frag | 0 .../qglview}/shaders/downscale.vert | 0 .../qglview}/shaders/dsl_pass_0.frag | 0 .../qglview}/shaders/dsl_pass_0.vert | 0 .../qglview}/shaders/dsl_pass_1.frag | 0 .../qglview}/shaders/dsl_pass_1.vert | 0 .../qglview}/shaders/dsl_pass_2.frag | 0 .../qglview}/shaders/dsl_pass_2.vert | 0 .../qglview}/shaders/fbo_add.frag | 0 .../qglview}/shaders/fbo_add.vert | 0 {qglengine => libs/qglview}/shaders/fxaa_v3.h | 0 {qglview => libs/qglview}/shaders/hdr.frag | 0 {qglview => libs/qglview}/shaders/hdr.vert | 0 .../qglview}/shaders/hdr_scale_0.frag | 0 .../qglview}/shaders/hdr_scale_1.frag | 0 .../qglview}/shaders/light_models.frag | 0 .../qglview}/shaders/motion_blur.frag | 0 .../qglview}/shaders/motion_blur.vert | 0 {qglview => libs/qglview}/shaders/post.frag | 0 {qglview => libs/qglview}/shaders/ppl.frag | 0 {qglview => libs/qglview}/shaders/ppl.vert | 0 .../qglview}/shaders/selection.frag | 0 .../qglview}/shaders/selection.vert | 0 .../qglview}/shaders/selection_halo.frag | 0 .../qglview}/shaders/selection_halo.vert | 0 {qglview => libs/qglview}/shaders/shadow.frag | 0 {qglview => libs/qglview}/shaders/shadow.vert | 0 .../qglview}/shaders/ssao_blur.frag | 0 .../qglview}/shaders/ssao_blur.vert | 0 .../qglview}/shaders/ssao_merge.frag | 0 .../qglview}/shaders/ssao_merge.vert | 0 {qglview => libs/qglview}/shaders/ssr.frag | 0 {qglview => libs/qglview}/shaders/ssr.vert | 0 .../qglview}/shaders/ssr_blur.frag | 0 .../qglview}/shaders/ssr_blur.vert | 0 .../qglview}/shaders/ssr_merge.frag | 0 .../qglview}/shaders/ssr_merge.vert | 0 {qad/libs => libs}/sql_table/CMakeLists.txt | 0 .../sql_table/lang/qad_sql_table_en.ts | 0 .../sql_table/lang/qad_sql_table_ru.ts | 0 {qad/libs => libs}/sql_table/lang/update.bat | 0 .../sql_table/plugin/CMakeLists.txt | 0 .../sql_table/plugin/qad_sql_table.cpp | 0 .../sql_table/plugin/qad_sql_table.h | 0 .../sql_table/plugin/sql_record_plugin.cpp | 0 .../sql_table/plugin/sql_record_plugin.h | 0 .../sql_table/plugin/sql_table_plugin.cpp | 0 .../sql_table/plugin/sql_table_plugin.h | 0 .../libs => libs}/sql_table/qad_sql_table.qrc | 0 .../sql_table/sql_record_widget.cpp | 0 .../sql_table/sql_record_widget.h | 0 .../sql_table/sql_table_widget.cpp | 0 .../sql_table/sql_table_widget.h | 0 .../sql_table/sql_table_widget.ui | 0 .../touch_widgets/CMakeLists.txt | 0 .../touch_widgets/plugin/CMakeLists.txt | 0 .../plugin/qad_touch_widgets.cpp | 0 .../touch_widgets/plugin/qad_touch_widgets.h | 0 .../plugin/touchbuttframeplugin.cpp | 0 .../plugin/touchbuttframeplugin.h | 0 .../plugin/touchbuttonplugin.cpp | 0 .../touch_widgets/plugin/touchbuttonplugin.h | 0 .../plugin/touchsliderplugin.cpp | 0 .../touch_widgets/plugin/touchsliderplugin.h | 0 {qad/libs => libs}/touch_widgets/touch_bar.h | 0 .../touch_widgets/touch_widgets.qrc | 0 .../touch_widgets/touchbuttframe.cpp | 0 .../touch_widgets/touchbuttframe.h | 0 .../touch_widgets/touchbutton.cpp | 0 .../libs => libs}/touch_widgets/touchbutton.h | 0 .../touch_widgets/touchslider.cpp | 0 .../libs => libs}/touch_widgets/touchslider.h | 0 .../touch_widgets/touchslider.ui | 0 {qad/libs => libs}/utils/CMakeLists.txt | 0 {qad/libs => libs}/utils/chunkstream.cpp | 0 {qad/libs => libs}/utils/chunkstream.h | 0 .../libs => libs}/utils/plugin/CMakeLists.txt | 0 {qad/libs => libs}/utils/plugin/qad_utils.cpp | 0 {qad/libs => libs}/utils/plugin/qad_utils.h | 0 {qad/libs => libs}/utils/propertystorage.cpp | 0 {qad/libs => libs}/utils/propertystorage.h | 0 {qad/libs => libs}/utils/qad_locations.cpp | 0 {qad/libs => libs}/utils/qad_locations.h | 0 {qad/libs => libs}/utils/qad_types.cpp | 0 {qad/libs => libs}/utils/qad_types.h | 0 {qad/libs => libs}/utils/qad_utils.qrc | 0 {qad/libs => libs}/utils/qpiconfig.cpp | 0 {qad/libs => libs}/utils/qpiconfig.h | 0 {qad/libs => libs}/utils/qpievaluator.cpp | 0 {qad/libs => libs}/utils/qpievaluator.h | 0 {qad/libs => libs}/widgets/CMakeLists.txt | 0 {qad/libs => libs}/widgets/chardialog.cpp | 0 {qad/libs => libs}/widgets/chardialog.h | 0 {qad/libs => libs}/widgets/chardialog.ui | 0 {qad/libs => libs}/widgets/clineedit.cpp | 0 {qad/libs => libs}/widgets/clineedit.h | 0 {qad/libs => libs}/widgets/colorbutton.cpp | 0 {qad/libs => libs}/widgets/colorbutton.h | 0 {qad/libs => libs}/widgets/ecombobox.cpp | 0 {qad/libs => libs}/widgets/ecombobox.h | 0 {qad/libs => libs}/widgets/evalspinbox.cpp | 0 {qad/libs => libs}/widgets/evalspinbox.h | 0 {qad/libs => libs}/widgets/iconedlabel.cpp | 0 {qad/libs => libs}/widgets/iconedlabel.h | 0 {qad/libs => libs}/widgets/image_view.cpp | 0 {qad/libs => libs}/widgets/image_view.h | 0 .../widgets/lang/qad_widgets_en.ts | 0 .../widgets/lang/qad_widgets_ru.ts | 0 {qad/libs => libs}/widgets/lang/update.bat | 0 {qad/libs => libs}/widgets/mathmatrixedit.cpp | 0 {qad/libs => libs}/widgets/mathmatrixedit.h | 0 {qad/libs => libs}/widgets/mathvectoredit.cpp | 0 {qad/libs => libs}/widgets/mathvectoredit.h | 0 {qad/libs => libs}/widgets/matrixedit.cpp | 0 {qad/libs => libs}/widgets/matrixedit.h | 0 {qad/libs => libs}/widgets/matrixedit.ui | 0 .../widgets/plugin/CMakeLists.txt | 0 .../widgets/plugin/chardialogplugin.cpp | 0 .../widgets/plugin/chardialogplugin.h | 0 .../widgets/plugin/clineeditplugin.cpp | 0 .../widgets/plugin/clineeditplugin.h | 0 .../widgets/plugin/colorbuttonplugin.cpp | 0 .../widgets/plugin/colorbuttonplugin.h | 0 .../widgets/plugin/ecomboboxplugin.cpp | 0 .../widgets/plugin/ecomboboxplugin.h | 0 .../widgets/plugin/evalspinboxplugin.cpp | 0 .../widgets/plugin/evalspinboxplugin.h | 0 .../widgets/plugin/iconedlabelplugin.h | 0 .../widgets/plugin/imageviewplugin.cpp | 0 .../widgets/plugin/imageviewplugin.h | 0 .../widgets/plugin/lconedlabelplugin.cpp | 0 .../widgets/plugin/qad_widgets.cpp | 0 .../widgets/plugin/qad_widgets.h | 0 .../widgets/plugin/qcodeeditplugin.cpp | 0 .../widgets/plugin/qcodeeditplugin.h | 0 .../widgets/plugin/qipeditplugin.cpp | 0 .../widgets/plugin/qipeditplugin.h | 0 .../widgets/plugin/qpiconfigplugin.cpp | 0 .../widgets/plugin/qpiconfigplugin.h | 0 .../widgets/plugin/qpiconsoleplugin.cpp | 0 .../widgets/plugin/qpiconsoleplugin.h | 0 .../widgets/plugin/qpointeditplugin.cpp | 0 .../widgets/plugin/qpointeditplugin.h | 0 .../widgets/plugin/qrecteditplugin.cpp | 0 .../widgets/plugin/qrecteditplugin.h | 0 .../widgets/plugin/qvarianteditplugin.cpp | 0 .../widgets/plugin/qvarianteditplugin.h | 0 .../widgets/plugin/scroll_spin_boxplugin.cpp | 0 .../widgets/plugin/scroll_spin_boxplugin.h | 0 .../widgets/plugin/shortcutsplugin.cpp | 0 .../widgets/plugin/shortcutsplugin.h | 0 .../widgets/plugin/spinsliderplugin.cpp | 0 .../widgets/plugin/spinsliderplugin.h | 0 .../widgets/propertystorage_editor.cpp | 0 .../widgets/propertystorage_editor.h | 0 {qad/libs => libs}/widgets/qad_widgets.qrc | 0 {qad/libs => libs}/widgets/qcodeedit.cpp | 0 {qad/libs => libs}/widgets/qcodeedit.h | 0 {qad/libs => libs}/widgets/qcodeedit.ui | 0 {qad/libs => libs}/widgets/qipedit.cpp | 0 {qad/libs => libs}/widgets/qipedit.h | 0 .../widgets/qpiconfignewdialog.cpp | 0 .../widgets/qpiconfignewdialog.h | 0 .../widgets/qpiconfignewdialog.ui | 0 .../widgets/qpiconfigvaluewidget.cpp | 0 .../widgets/qpiconfigvaluewidget.h | 0 .../libs => libs}/widgets/qpiconfigwidget.cpp | 0 {qad/libs => libs}/widgets/qpiconfigwidget.h | 0 {qad/libs => libs}/widgets/qpiconsole.cpp | 0 {qad/libs => libs}/widgets/qpiconsole.h | 0 {qad/libs => libs}/widgets/qpointedit.cpp | 0 {qad/libs => libs}/widgets/qpointedit.h | 0 {qad/libs => libs}/widgets/qrectedit.cpp | 0 {qad/libs => libs}/widgets/qrectedit.h | 0 {qad/libs => libs}/widgets/qvariantedit.cpp | 0 {qad/libs => libs}/widgets/qvariantedit.h | 0 .../widgets/qvariantedit_custom.cpp | 0 .../widgets/qvariantedit_custom.h | 0 .../libs => libs}/widgets/scroll_spin_box.cpp | 0 {qad/libs => libs}/widgets/scroll_spin_box.h | 0 {qad/libs => libs}/widgets/scroll_spin_box.ui | 0 .../libs => libs}/widgets/session_manager.cpp | 0 {qad/libs => libs}/widgets/session_manager.h | 0 {qad/libs => libs}/widgets/shortcuts.cpp | 0 {qad/libs => libs}/widgets/shortcuts.h | 0 {qad/libs => libs}/widgets/spinslider.cpp | 0 {qad/libs => libs}/widgets/spinslider.h | 0 logo.png | Bin 13843 -> 23645 bytes make_libs.bat | 6 - make_libs.sh | 6 - make_libs32.bat | 1 - make_libs64.bat | 1 - make_libs_all.bat | 2 - make_libs_android.bat | 6 - make_libs_android_all.bat | 4 - pip | 1 - piqt/CMakeLists.txt | 21 - piqt/LICENSE.txt | 165 -- piqt/libs/CMakeLists.txt | 1 - piqt/utils/CMakeLists.txt | 1 - project_fs/ProjectFilesystemPlugin.json.in | 11 - project_fs/filterdialog.cpp | 91 - project_fs/filterdialog.h | 37 - project_fs/filterdialog.ui | 226 -- project_fs/icons/utilities-terminal.png | Bin 15685 -> 0 bytes project_fs/projectfilesystem.qrc | 6 - project_fs/projectfilesystemplugin.cpp | 89 - project_fs/projectfilesystemplugin.h | 29 - project_fs/projectfilesystemplugin.pro | 61 - project_fs/projectfilesystemplugin_global.h | 9 - project_fs/projectfilesystempluginconstants.h | 10 - project_fs/projectfilesystemwidget.cpp | 328 --- project_fs/projectfilesystemwidget.h | 68 - project_fs/projectfilesystemwidget.ui | 183 -- project_fs/projectfilesystemwidgetplugin.cpp | 57 - project_fs/projectfilesystemwidgetplugin.h | 18 - qad/CMakeLists.txt | 40 - qad/LICENSE.txt | 165 -- qad/icons/edit-find.png | Bin 43469 -> 0 bytes qglengine/CMakeLists.txt | 55 - qglengine/LICENSE.txt | 165 -- qglengine/coeffs_brdf.png | Bin 32788 -> 0 bytes qglengine/core/glbuffer.cpp | 88 - qglengine/core/glbuffer.h | 58 - qglengine/core/glcubemap.cpp | 281 --- qglengine/core/glcubemap.h | 67 - qglengine/core/glframebuffer.cpp | 315 --- qglengine/core/glframebuffer.h | 89 - qglengine/core/glframebuffer_mipmap.cpp | 50 - qglengine/core/glframebuffer_mipmap.h | 50 - qglengine/core/glmaterial.cpp | 151 -- qglengine/core/glmaterial.h | 124 - qglengine/core/glmesh.cpp | 426 ---- qglengine/core/glmesh.h | 110 - qglengine/core/glprimitives.cpp | 437 ---- qglengine/core/glprimitives.h | 104 - qglengine/core/glshaders.cpp | 146 -- qglengine/core/glshaders.h | 31 - qglengine/core/glshaders_headers.h | 127 - qglengine/core/glshaders_types.cpp | 97 - qglengine/core/glshaders_types.h | 144 -- qglengine/core/gltexturearray.cpp | 96 - qglengine/core/gltexturearray.h | 56 - qglengine/core/gltransform.cpp | 441 ---- qglengine/core/gltransform.h | 119 - qglengine/core/gltypes.cpp | 373 --- qglengine/core/gltypes.h | 303 --- qglengine/core/glvertexobject.cpp | 119 - qglengine/core/glvertexobject.h | 64 - qglengine/core/hdr.cpp | 125 - qglengine/core/hdr_p.h | 26 - qglengine/formats/loader_assimp.cpp | 267 -- qglengine/formats/loader_assimp.h | 27 - qglengine/formats/loader_qgl.cpp | 67 - qglengine/formats/loader_qgl.h | 28 - qglengine/glcamera.cpp | 110 - qglengine/glcamera.h | 70 - qglengine/globject.cpp | 717 ------ qglengine/globject.h | 313 --- qglengine/glrendererbase.cpp | 294 --- qglengine/glrendererbase.h | 80 - qglengine/glscene.cpp | 540 ---- qglengine/glscene.h | 146 -- qglengine/gltexture_manager.cpp | 201 -- qglengine/gltexture_manager.h | 65 - qglengine/glwidget.cpp | 240 -- qglengine/glwidget.h | 104 - qglengine/icons/add-type-camera.png | Bin 14827 -> 0 bytes qglengine/icons/add-type-empty.png | Bin 10989 -> 0 bytes qglengine/icons/add-type-geo.png | Bin 10226 -> 0 bytes qglengine/icons/add-type-light.png | Bin 14284 -> 0 bytes qglengine/icons/alpha.png | Bin 158 -> 0 bytes qglengine/icons/application-exit.png | Bin 32537 -> 0 bytes qglengine/icons/collapse.png | Bin 13144 -> 0 bytes qglengine/icons/configure.png | Bin 32993 -> 0 bytes qglengine/icons/dialog-cancel.png | Bin 45200 -> 0 bytes qglengine/icons/dialog-close.png | Bin 39321 -> 0 bytes qglengine/icons/document-edit.png | Bin 30106 -> 0 bytes qglengine/icons/document-import.png | Bin 16611 -> 0 bytes qglengine/icons/document-new.png | Bin 24844 -> 0 bytes qglengine/icons/document-open.png | Bin 8621 -> 0 bytes qglengine/icons/document-save-all.png | Bin 26721 -> 0 bytes qglengine/icons/document-save.png | Bin 22676 -> 0 bytes .../icons/edit-clear-locationbar-rtl.png | Bin 20226 -> 0 bytes qglengine/icons/edit-clear.png | Bin 54801 -> 0 bytes qglengine/icons/edit-copy.png | Bin 14072 -> 0 bytes qglengine/icons/edit-delete.png | Bin 22776 -> 0 bytes qglengine/icons/edit-find.png | Bin 43469 -> 0 bytes qglengine/icons/edit-paste.png | Bin 14413 -> 0 bytes qglengine/icons/edit-rename.png | Bin 4859 -> 0 bytes qglengine/icons/expand.png | Bin 14692 -> 0 bytes qglengine/icons/format-fill-color.png | Bin 44130 -> 0 bytes qglengine/icons/go-jump.png | Bin 7200 -> 0 bytes qglengine/icons/go-top.png | Bin 31581 -> 0 bytes qglengine/icons/group.png | Bin 12826 -> 0 bytes qglengine/icons/layer-visible-off.png | Bin 53079 -> 0 bytes qglengine/icons/layer-visible-on.png | Bin 49905 -> 0 bytes qglengine/icons/light-+.png | Bin 16851 -> 0 bytes qglengine/icons/list-add.png | Bin 35372 -> 0 bytes qglengine/icons/object-flip-horizontal.png | Bin 25165 -> 0 bytes qglengine/icons/object-flip-vertical.png | Bin 22264 -> 0 bytes qglengine/icons/picker.png | Bin 26844 -> 0 bytes qglengine/icons/transform-move.png | Bin 24712 -> 0 bytes qglengine/icons/transform-rotate.png | Bin 20621 -> 0 bytes qglengine/icons/transform-scale.png | Bin 8092 -> 0 bytes qglengine/icons/type-camera.png | Bin 33163 -> 0 bytes qglengine/icons/type-empty.png | Bin 2071 -> 0 bytes qglengine/icons/type-geo.png | Bin 5538 -> 0 bytes qglengine/icons/type-light.png | Bin 2899 -> 0 bytes qglengine/icons/view-refresh.png | Bin 40505 -> 0 bytes qglengine/mouse_controller.cpp | 289 --- qglengine/mouse_controller.h | 84 - qglengine/openglwindow.cpp | 113 - qglengine/openglwindow.h | 54 - qglengine/plugin/CMakeLists.txt | 18 - qglengine/plugin/qglviewplugin.cpp | 95 - qglengine/qglview.cpp | 299 --- qglengine/qglview.h | 293 --- qglengine/qglview.qrc | 46 - qglengine/qglview_test/main.cpp | 34 - qglengine/qglview_test/qglview_window.cpp | 251 -- qglengine/qglview_test/qglview_window.h | 119 - qglengine/qglview_test/qglview_window.ui | 978 -------- qglengine/renderer.cpp | 382 --- qglengine/renderer.h | 136 - qglengine/renderer_base.cpp | 442 ---- qglengine/renderer_base.h | 68 - qglengine/renderer_material.cpp | 132 - qglengine/renderer_material.h | 54 - qglengine/renderer_selection.cpp | 218 -- qglengine/renderer_selection.h | 68 - qglengine/renderer_service.cpp | 490 ---- qglengine/renderer_service.h | 108 - qglengine/shaders.qrc | 19 - qglengine/shaders/ds_final.glsl | 22 - qglengine/shaders/ds_geom.glsl | 71 - qglengine/shaders/ds_light.glsl | 181 -- qglengine/shaders/ds_tonemap.glsl | 25 - qglengine/shaders/fxaa.frag | 2223 ----------------- qglengine/shaders/fxaa.vert | 11 - qglengine/shaders/selection.glsl | 19 - qglengine/shaders/selection_apply.glsl | 25 - qglengine/shaders/selection_frame.glsl | 24 - qglengine/shaders/selection_halo.glsl | 42 - qglengine/shaders/service_fill.glsl | 24 - qglengine/shaders/service_frame.glsl | 51 - qglengine/shaders/service_line.glsl | 17 - qglengine/shaders/sum.glsl | 25 - qglengine/tonemapping_proc.cpp | 186 -- qglengine/tonemapping_proc.h | 66 - qglengine/widgets/CMakeLists.txt | 26 - qglengine/widgets/material_editor.cpp | 237 -- qglengine/widgets/material_editor.h | 67 - qglengine/widgets/material_editor.ui | 637 ----- qglengine/widgets/material_map_editor.cpp | 150 -- qglengine/widgets/material_map_editor.h | 60 - qglengine/widgets/material_map_editor.ui | 506 ---- qglengine/widgets/materials_editor.cpp | 207 -- qglengine/widgets/materials_editor.h | 66 - qglengine/widgets/materials_editor.ui | 251 -- qglengine/widgets/object_editor.cpp | 268 -- qglengine/widgets/object_editor.h | 62 - qglengine/widgets/object_editor.ui | 782 ------ qglengine/widgets/primitiveeditor.cpp | 259 -- qglengine/widgets/primitiveeditor.h | 68 - qglengine/widgets/primitiveeditor.ui | 597 ----- qglengine/widgets/propertyeditor.cpp | 426 ---- qglengine/widgets/propertyeditor.h | 95 - qglengine/widgets/scene_tree.cpp | 504 ---- qglengine/widgets/scene_tree.h | 100 - qglengine/widgets/scene_tree.ui | 425 ---- qglengine/widgets/treewidget_p.h | 51 - qglengine/widgets/view_editor.cpp | 179 -- qglengine/widgets/view_editor.h | 67 - qglengine/widgets/view_editor.ui | 511 ---- qglengine/widgets/widgets.qrc | 18 - qglview/LICENSE.txt | 165 -- qglview/icons/alpha.png | Bin 158 -> 0 bytes qglview/icons/application-exit.png | Bin 1134 -> 0 bytes qglview/icons/configure.png | Bin 717 -> 0 bytes qglview/icons/dialog-close.png | Bin 813 -> 0 bytes qglview/icons/document-save.png | Bin 563 -> 0 bytes qglview/icons/edit-clear-locationbar-rtl.png | Bin 644 -> 0 bytes qglview/icons/edit-clear.png | Bin 802 -> 0 bytes qglview/icons/edit-copy.png | Bin 485 -> 0 bytes qglview/icons/edit-delete.png | Bin 640 -> 0 bytes qglview/icons/edit-find.png | Bin 634 -> 0 bytes qglview/icons/edit-guides.png | Bin 544 -> 0 bytes qglview/icons/edit-paste.png | Bin 529 -> 0 bytes qglview/icons/item-add.png | Bin 639 -> 0 bytes qglview/icons/item.png | Bin 448 -> 0 bytes qglview/icons/list-add.png | Bin 564 -> 0 bytes qglview/icons/node-add.png | Bin 694 -> 0 bytes qglview/icons/node.png | Bin 658 -> 0 bytes qglview/icons/qglview.png | Bin 82318 -> 0 bytes qglview/icons/qglview.xcf | Bin 170453 -> 0 bytes qglview/icons/view-grid.png | Bin 691 -> 0 bytes qglview/icons/zoom-fit-best.png | Bin 539 -> 0 bytes qglview/plugin/qglview_designerplugin.cpp | 14 - qglview/plugin/qglview_designerplugin.h | 22 - qglview/plugin/qglviewplugin.h | 33 - qglview/shaders/fxaa_v3.h | 2048 --------------- {qad/utils => utils}/CMakeLists.txt | 0 .../blockeditor/CMakeLists.txt | 0 .../blockeditor/blockeditor_main.cpp | 0 .../blockeditor/icons/blockview.ico | Bin .../blockeditor/icons/blockview.png | Bin {piqt/utils => utils}/cd_pult/CMakeLists.txt | 0 {piqt/utils => utils}/cd_pult/cddirectk.cpp | 0 {piqt/utils => utils}/cd_pult/cddirectk.h | 0 {piqt/utils => utils}/cd_pult/cddirectk.ui | 0 .../cd_pult/cddirectk_type_dialog.cpp | 0 .../cd_pult/cddirectk_type_dialog.h | 0 .../cd_pult/cddirectk_type_dialog.ui | 0 {piqt/utils => utils}/cd_pult/cdgraphics.cpp | 0 {piqt/utils => utils}/cd_pult/cdgraphics.h | 0 {piqt/utils => utils}/cd_pult/cdgraphics.ui | 0 {piqt/utils => utils}/cd_pult/cdpult.qrc | 0 .../utils => utils}/cd_pult/cdpultwindow.cpp | 0 {piqt/utils => utils}/cd_pult/cdpultwindow.h | 0 {piqt/utils => utils}/cd_pult/cdpultwindow.ui | 0 .../utils => utils}/cd_pult/cdviewwidget.cpp | 0 {piqt/utils => utils}/cd_pult/cdviewwidget.h | 0 {piqt/utils => utils}/cd_pult/cdviewwidget.ui | 0 .../Apps-accessories-calculator-icon.png | Bin .../cd_pult/icons/accessories-text-editor.png | Bin .../cd_pult/icons/db-export.png | Bin .../cd_pult/icons/db-import.png | Bin {piqt/utils => utils}/cd_pult/icons/flame.png | Bin {piqt/utils => utils}/cd_pult/icons/timer.png | Bin {piqt/utils => utils}/cd_pult/main.cpp | 0 .../utils => utils}/piconnedit/CMakeLists.txt | 0 .../utils => utils}/piconnedit/piconnedit.qrc | 0 .../piconnedit/piconnedit_main.cpp | 0 {piqt/utils => utils}/pidumper/CMakeLists.txt | 0 {piqt/utils => utils}/pidumper/pidumper.cpp | 0 {piqt/utils => utils}/pidumper/pidumper.h | 0 {piqt/utils => utils}/pidumper/pidumper.ui | 0 .../pidumper/pidumper_main.cpp | 0 .../piintrospector/CMakeLists.txt | 0 .../piintrospector/containers_view.cpp | 0 .../piintrospector/containers_view.h | 0 .../piintrospector/containers_view.ui | 0 .../piintrospector/objects_view.cpp | 0 .../piintrospector/objects_view.h | 0 .../piintrospector/objects_view.ui | 0 .../piintrospector/piintrospector.cpp | 0 .../piintrospector/piintrospector.h | 0 .../piintrospector/piintrospector.ui | 0 .../piintrospector/piintrospector_main.cpp | 0 .../piintrospector/threads_view.cpp | 0 .../piintrospector/threads_view.h | 0 .../piintrospector/threads_view.ui | 0 .../qpicalculator/CMakeLists.txt | 0 .../qpicalculator/icons/qpicalculator.ico | Bin .../qpicalculator/icons/qpicalculator.png | Bin {qad/utils => utils}/qpicalculator/main.cpp | 0 .../qpicalculator/mainwindow.cpp | 0 .../qpicalculator/mainwindow.h | 0 .../qpicalculator/mainwindow.ui | 0 .../qpicalculator/qpicalculator.qrc | 0 904 files changed, 2448 insertions(+), 36452 deletions(-) delete mode 100644 .gitmodules delete mode 100644 Jenkinsfile delete mode 100644 SDKMacros.cmake delete mode 100644 cd_utils/CMakeLists.txt delete mode 100644 cd_utils/cdtest.h delete mode 100644 cd_utils/cdutils_c.cpp delete mode 100644 cd_utils/cdutils_c.h delete mode 100644 cd_utils/cdutils_core.cpp delete mode 100644 cd_utils/cdutils_core.h delete mode 100644 cd_utils/cdutils_interface.cpp delete mode 100644 cd_utils/cdutils_interface.h delete mode 100644 cd_utils/cdutils_k.cpp delete mode 100644 cd_utils/cdutils_k.h delete mode 100644 cd_utils/cdutils_m.cpp delete mode 100644 cd_utils/cdutils_m.h delete mode 100644 cd_utils/cdutils_parser.cpp delete mode 100644 cd_utils/cdutils_parser.h delete mode 100644 cd_utils/cdutils_protocol.h delete mode 100644 cd_utils/cdutils_types.cpp delete mode 100644 cd_utils/cdutils_types.h delete mode 100644 cd_utils/cdutils_x.cpp delete mode 100644 cd_utils/cdutils_x.h delete mode 100644 cd_utils/cdutilstest.cpp delete mode 100644 cd_utils/k_description.h rename {qad/cmake => cmake}/FindQAD.cmake (100%) rename {qad/cmake => cmake}/QADMacros.cmake (100%) rename {qad/cmake => cmake}/QtWraps.cmake (96%) delete mode 100644 cmake_android.bat delete mode 100755 cmake_android.sh delete mode 100644 docker/android-libs/Dockerfile delete mode 100644 docker/debian-libs/Dockerfile delete mode 100644 docker/osx-libs/Dockerfile delete mode 100644 docker/pi-libs/Dockerfile delete mode 100644 docker/windows-libs/Dockerfile rename {qad/icons => icons}/align-bottom-center.png (100%) rename {qad/icons => icons}/align-bottom-left.png (100%) rename {qad/icons => icons}/align-bottom-right.png (100%) rename {qad/icons => icons}/align-center-center.png (100%) rename {qad/icons => icons}/align-center-left.png (100%) rename {qad/icons => icons}/align-center-right.png (100%) rename {qad/icons => icons}/align-hor.png (100%) rename {qad/icons => icons}/align-top-center.png (100%) rename {qad/icons => icons}/align-top-left.png (100%) rename {qad/icons => icons}/align-top-right.png (100%) rename {qad/icons => icons}/align-ver.png (100%) rename {kx_utils/icons => icons}/alpha.png (100%) rename {qad/icons => icons}/application-exit.png (100%) rename {qad/icons => icons}/archive-extract.png (100%) rename {qad/icons => icons}/archive-insert-directory.png (100%) rename {qad/icons => icons}/archive-insert.png (100%) rename {qad/icons => icons}/arrow-down.png (100%) rename {qad/icons => icons}/arrow-up.png (100%) rename {qad/icons => icons}/axis_x.png (100%) rename {qad/icons => icons}/axis_y.png (100%) rename {qad/icons => icons}/blockview.png (100%) rename {qad/icons => icons}/blockview.xcf (100%) rename {qad/icons => icons}/border-line.png (100%) rename {qad/icons => icons}/button.png (100%) rename {qad/icons => icons}/case-sensitive.png (100%) rename {qad/icons => icons}/chardialog.png (100%) rename {qad/icons => icons}/checkbox-unchecked.png (100%) rename {qad/icons => icons}/checkbox.png (100%) rename {qad/icons => icons}/clear-history.png (100%) rename {qad/icons => icons}/clineedit.png (100%) rename {qad/icons => icons}/code-error.png (100%) rename {qad/icons => icons}/code-parents.png (100%) rename {qad/icons => icons}/code-struct.png (100%) rename {qad/icons => icons}/code-union.png (100%) rename {qad/icons => icons}/code-variable.png (100%) rename {qad/icons => icons}/code-word.png (100%) rename {qad/icons => icons}/colorbutton.png (100%) rename {qad/icons => icons}/configure.png (100%) rename {qad/icons => icons}/configure_16.png (100%) rename {qad/icons => icons}/database.png (100%) rename {qad/icons => icons}/dialog-cancel.png (100%) rename {qad/icons => icons}/dialog-close.png (100%) rename {qad/icons => icons}/dialog-information.png (100%) rename {qad/icons => icons}/dialog-ok-apply.png (100%) rename {qad/icons => icons}/dialog-warning.png (100%) rename {qad/icons => icons}/document-close.png (100%) rename {qad/icons => icons}/document-edit.png (100%) rename {qad/icons => icons}/document-new.png (100%) rename {qad/icons => icons}/document-open-recent.png (100%) rename {qad/icons => icons}/document-open.png (100%) rename {qad/icons => icons}/document-open_16.png (100%) rename {qad/icons => icons}/document-print.png (100%) rename {qad/icons => icons}/document-revert.png (100%) rename {qad/icons => icons}/document-save-all.png (100%) rename {qad/icons => icons}/document-save-as.png (100%) rename {qad/icons => icons}/document-save.png (100%) rename {qad/icons => icons}/draw-ellipse.png (100%) rename {qad/icons => icons}/draw-line.png (100%) rename {qad/icons => icons}/draw-rectangle.png (100%) rename {qad/icons => icons}/draw-text.png (100%) rename {qad/icons => icons}/ecombobox.png (100%) rename {qad/icons => icons}/edit-clear-locationbar-rtl.png (100%) rename {qad/icons => icons}/edit-clear.png (100%) rename {qad/icons => icons}/edit-copy.png (100%) rename {qad/icons => icons}/edit-delete.png (100%) rename {project_fs/icons => icons}/edit-find.png (100%) rename {qad/icons => icons}/edit-find_16.png (100%) rename {qad/icons => icons}/edit-guides.png (100%) rename {qad/icons => icons}/edit-paste.png (100%) rename {qad/icons => icons}/edit-redo.png (100%) rename {qad/icons => icons}/edit-table-insert-row-below.png (100%) rename {qad/icons => icons}/edit-undo.png (100%) rename {qad/icons => icons}/edockwidget.png (100%) rename {qad/icons => icons}/etabwidget.png (100%) rename {qad/icons => icons}/evalspinbox.png (100%) rename {qad/icons => icons}/expand_s_x.png (100%) rename {qad/icons => icons}/expand_s_y.png (100%) rename {qad/icons => icons}/expand_x.png (100%) rename {qad/icons => icons}/expand_y.png (100%) rename {qad/icons => icons}/f1.png (100%) rename {qad/icons => icons}/format-fill-color.png (100%) rename {qad/icons => icons}/format-stroke-color.png (100%) rename {qad/icons => icons}/format-text-subscript.png (100%) rename {qad/icons => icons}/games-solve.png (100%) rename {qad/icons => icons}/go-next.png (100%) rename {qad/icons => icons}/go-previous.png (100%) rename {qad/icons => icons}/graphic.png (100%) rename {qad/icons => icons}/graphics.png (100%) rename {qad/icons => icons}/historyview.png (100%) rename {qad/icons => icons}/icons.xcf (100%) rename {kx_utils/icons => icons}/item-add.png (100%) rename {kx_utils/icons => icons}/item.png (100%) rename {qad/icons => icons}/lastmoves.png (100%) rename {qad/icons => icons}/layer-visible-off.png (100%) rename {qad/icons => icons}/layer-visible-on.png (100%) rename {qad/icons => icons}/led_3.png (100%) rename {qad/icons => icons}/led_gray.png (100%) rename {qad/icons => icons}/led_off.png (100%) rename {qad/icons => icons}/led_on.png (100%) rename {qad/icons => icons}/legend.png (100%) rename {qad/icons => icons}/list-add.png (100%) rename {qad/icons => icons}/list-remove.png (100%) rename {qad/icons => icons}/log_parser.png (100%) rename {qad/icons => icons}/logview.png (100%) rename {qad/icons => icons}/mail.png (100%) rename {qad/icons => icons}/media-playback-pause.png (100%) rename {qad/icons => icons}/media-playback-start.png (100%) rename {qad/icons => icons}/media-playback-stop.png (100%) rename {qad/icons => icons}/media-record.png (100%) rename {qad/icons => icons}/media-skip-forward.png (100%) rename {kx_utils/icons => icons}/node-add.png (100%) rename {kx_utils/icons => icons}/node.png (100%) rename {qad/icons => icons}/pause-back.png (100%) rename {qad/icons => icons}/pause-front.png (100%) rename {qad/icons => icons}/qcodeedit.png (100%) rename {qad/icons => icons}/qpiconsole.png (100%) rename {qad/icons => icons}/qt.png (100%) rename {qad/icons => icons}/quickopen.png (100%) rename {qad/icons => icons}/qvariantedit.png (100%) rename {qad/icons => icons}/scroll_spin.png (100%) rename {qad/icons => icons}/select-all.png (100%) rename {qad/icons => icons}/select-none.png (100%) rename {qad/icons => icons}/spinslider.png (100%) rename {qad/icons => icons}/sql_table.png (100%) rename {qad/icons => icons}/tools-wizard.png (100%) rename {qad/icons => icons}/touchbuttframe.png (100%) rename {qad/icons => icons}/touchbutton.png (100%) rename {qad/icons => icons}/touchslider.png (100%) rename {qad/icons => icons}/transform-move.png (100%) rename {qad/icons => icons}/variable-add.png (100%) rename {qad/icons => icons}/variable-copy.png (100%) rename {qad/icons => icons}/variable-edit.png (100%) rename {qad/icons => icons}/variable-remove.png (100%) rename {qad/icons => icons}/view-autofit.png (100%) rename {qad/icons => icons}/view-fullscreen.png (100%) rename {qad/icons => icons}/view-grid.png (100%) rename {qad/icons => icons}/view-preview.png (100%) rename {qad/icons => icons}/view-refresh.png (100%) rename {qad/icons => icons}/z-bottom.png (100%) rename {qad/icons => icons}/z-down.png (100%) rename {qad/icons => icons}/z-top.png (100%) rename {qad/icons => icons}/z-up.png (100%) rename {qad/icons => icons}/zoom-draw.png (100%) rename {qad/icons => icons}/zoom-fit-best.png (100%) rename {qad/icons => icons}/zoom-in.png (100%) rename {qad/icons => icons}/zoom-original.png (100%) rename {qad/icons => icons}/zoom-out.png (100%) rename {qad/icons => icons}/zoom-range.png (100%) rename {qad/icons => icons}/zoom-rect.png (100%) rename {qad/icons => icons}/zoom-select.png (100%) delete mode 100644 kx_utils/CMakeLists.txt delete mode 100644 kx_utils/clean delete mode 100644 kx_utils/clean.bat delete mode 100644 kx_utils/icons/accessories-calculator.png delete mode 100644 kx_utils/icons/archive-extract.png delete mode 100644 kx_utils/icons/document-export.png delete mode 100644 kx_utils/icons/document-import.png delete mode 100644 kx_utils/icons/document-open.png delete mode 100644 kx_utils/icons/document-save-.png delete mode 100644 kx_utils/icons/edit-clear-.png delete mode 100644 kx_utils/icons/edit-find-.png delete mode 100644 kx_utils/icons/expand_s_x.png delete mode 100644 kx_utils/icons/expand_s_y.png delete mode 100644 kx_utils/icons/expand_x.png delete mode 100644 kx_utils/icons/expand_y.png delete mode 100644 kx_utils/icons/layer-visible-off.png delete mode 100644 kx_utils/icons/layer-visible-on.png delete mode 100644 kx_utils/icons/media-playback-pause.png delete mode 100644 kx_utils/icons/media-playback-stop.png delete mode 100644 kx_utils/icons/media-record.png delete mode 100644 kx_utils/icons/view-refresh.png delete mode 100644 kx_utils/icons/zoom-fit-height.png delete mode 100644 kx_utils/kx_coeffs.cpp delete mode 100644 kx_utils/kx_coeffs.h delete mode 100644 kx_utils/kx_protocol_c.h delete mode 100644 kx_utils/kx_protocol_x.h delete mode 100644 kx_utils/kx_pult.conf delete mode 100644 kx_utils/kx_pult.cpp delete mode 100644 kx_utils/kx_pult.h delete mode 100644 kx_utils/kx_pult.qrc delete mode 100644 kx_utils/kx_pult.ui delete mode 100644 kx_utils/main_kx_pult.cpp delete mode 100644 kx_utils/make_lib.bat delete mode 100644 kx_utils/piprotocol.cpp delete mode 100644 kx_utils/piprotocol.h rename {qad/libs => libs}/CMakeLists.txt (100%) rename {qad/libs => libs}/application/CMakeLists.txt (100%) rename {qad/libs => libs}/application/aboutwindow.cpp (100%) rename {qad/libs => libs}/application/aboutwindow.h (100%) rename {qad/libs => libs}/application/aboutwindow.ui (100%) rename {qad/libs => libs}/application/edockwidget.cpp (100%) rename {qad/libs => libs}/application/edockwidget.h (100%) rename {qad/libs => libs}/application/emainwindow.cpp (100%) rename {qad/libs => libs}/application/emainwindow.h (100%) rename {qad/libs => libs}/application/etabwidget.cpp (100%) rename {qad/libs => libs}/application/etabwidget.h (100%) rename {qad/libs => libs}/application/historyview.cpp (100%) rename {qad/libs => libs}/application/historyview.h (100%) rename {qad/libs => libs}/application/lang/qad_application_en.ts (100%) rename {qad/libs => libs}/application/lang/qad_application_ru.ts (100%) rename {qad/libs => libs}/application/lang/update.bat (100%) rename {qad/libs => libs}/application/logview.cpp (100%) rename {qad/libs => libs}/application/logview.h (100%) rename {qad/libs => libs}/application/logview.ui (100%) rename {qad/libs => libs}/application/plugin/CMakeLists.txt (100%) rename {qad/libs => libs}/application/plugin/edockwidgetplugin.cpp (100%) rename {qad/libs => libs}/application/plugin/edockwidgetplugin.h (100%) rename {qad/libs => libs}/application/plugin/emainwindowplugin.cpp (100%) rename {qad/libs => libs}/application/plugin/emainwindowplugin.h (100%) rename {qad/libs => libs}/application/plugin/historyviewplugin.cpp (100%) rename {qad/libs => libs}/application/plugin/historyviewplugin.h (100%) rename {qad/libs => libs}/application/plugin/logviewplugin.cpp (100%) rename {qad/libs => libs}/application/plugin/logviewplugin.h (100%) rename {qad/libs => libs}/application/plugin/qad_application.cpp (100%) rename {qad/libs => libs}/application/plugin/qad_application.h (100%) rename {qad/libs => libs}/application/qad_application.qrc (100%) rename {qad/libs => libs}/application/qsingleapplication.cpp (100%) rename {qad/libs => libs}/application/qsingleapplication.h (100%) rename {qad/libs => libs}/application/ribbon.cpp (100%) rename {qad/libs => libs}/application/ribbon.h (100%) rename {qad/libs => libs}/blockview/CMakeLists.txt (100%) rename {qad/libs => libs}/blockview/alignedtextitem.cpp (100%) rename {qad/libs => libs}/blockview/alignedtextitem.h (100%) rename {qad/libs => libs}/blockview/blockbase.cpp (100%) rename {qad/libs => libs}/blockview/blockbase.h (100%) rename {qad/libs => libs}/blockview/blockbusitem.cpp (100%) rename {qad/libs => libs}/blockview/blockbusitem.h (100%) rename {qad/libs => libs}/blockview/blockeditor.cpp (100%) rename {qad/libs => libs}/blockview/blockeditor.h (100%) rename {qad/libs => libs}/blockview/blockeditor.ui (100%) rename {qad/libs => libs}/blockview/blockitem.cpp (100%) rename {qad/libs => libs}/blockview/blockitem.h (100%) rename {qad/libs => libs}/blockview/blockitempin.cpp (100%) rename {qad/libs => libs}/blockview/blockitempin.h (100%) rename {qad/libs => libs}/blockview/blockview.cpp (100%) rename {qad/libs => libs}/blockview/blockview.h (100%) rename {qad/libs => libs}/blockview/blockviewwavetrace.cpp (100%) rename {qad/libs => libs}/blockview/blockviewwavetrace.h (100%) rename {qad/libs => libs}/blockview/drawtools.cpp (100%) rename {qad/libs => libs}/blockview/drawtools.h (100%) rename {qad/libs => libs}/blockview/drawtools.ui (100%) rename {qad/libs => libs}/blockview/lang/qad_blockview_en.ts (100%) rename {qad/libs => libs}/blockview/lang/qad_blockview_ru.ts (100%) rename {qad/libs => libs}/blockview/lang/update.bat (100%) rename {qad/libs => libs}/blockview/plugin/CMakeLists.txt (100%) rename {qad/libs => libs}/blockview/plugin/blockviewplugin.cpp (100%) rename {qad/libs => libs}/blockview/plugin/blockviewplugin.h (100%) rename {qad/libs => libs}/blockview/plugin/qad_blockview.cpp (100%) rename {qad/libs => libs}/blockview/plugin/qad_blockview.h (100%) rename {qad/libs => libs}/blockview/qad_blockview.qrc (100%) rename {qad/libs => libs}/doc/CMakeLists.txt (100%) rename {qad/libs => libs}/doc/markdown.cpp (100%) rename {qad/libs => libs}/doc/markdown.h (100%) rename {qad/libs => libs}/graphic/CMakeLists.txt (100%) rename {qad/libs => libs}/graphic/graphic.cpp (100%) rename {qad/libs => libs}/graphic/graphic.h (100%) rename {qad/libs => libs}/graphic/graphic.ui (100%) rename {qad/libs => libs}/graphic/graphic_conf.cpp (100%) rename {qad/libs => libs}/graphic/graphic_conf.h (100%) rename {qad/libs => libs}/graphic/graphic_conf.ui (100%) rename {qad/libs => libs}/graphic/lang/qad_graphic_en.ts (100%) rename {qad/libs => libs}/graphic/lang/qad_graphic_ru.ts (100%) rename {qad/libs => libs}/graphic/lang/update.bat (100%) rename {qad/libs => libs}/graphic/plugin/CMakeLists.txt (100%) rename {qad/libs => libs}/graphic/plugin/graphicplugin.cpp (100%) rename {qad/libs => libs}/graphic/plugin/graphicplugin.h (100%) rename {qad/libs => libs}/graphic/plugin/qad_graphic.cpp (100%) rename {qad/libs => libs}/graphic/plugin/qad_graphic.h (100%) rename {qad/libs => libs}/graphic/qad_graphic.qrc (100%) rename {qad/libs => libs}/graphic/uglwidget.h (100%) rename {qad/libs => libs}/graphic/uwidget.h (100%) rename {piqt/libs/core => libs/piqt}/CMakeLists.txt (100%) rename {piqt/libs/core => libs/piqt}/piqt.cpp (100%) rename {piqt/libs/core => libs/piqt}/piqt.h (100%) rename {piqt/libs/core => libs/piqt}/qpiconnection.cpp (100%) rename {piqt/libs/core => libs/piqt}/qpiconnection.h (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/CMakeLists.txt (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_connection_edit.cpp (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_connection_edit.h (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_connection_edit.ui (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_connection_view.cpp (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_connection_view.h (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_highlighter.cpp (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_highlighter.h (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_iodevice_edit.cpp (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_iodevice_edit.h (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_iodevice_edit_dialog.cpp (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_iodevice_edit_dialog.h (100%) rename {piqt/libs/widgets => libs/piqt_widgets}/piqt_iodevice_edit_dialog.ui (100%) rename {piqt/libs => libs}/qcd/CMakeLists.txt (100%) rename {piqt/libs => libs}/qcd/qcd_core.cpp (100%) rename {piqt/libs => libs}/qcd/qcd_core.h (100%) rename {piqt/libs => libs}/qcd/qcd_graphic.cpp (100%) rename {piqt/libs => libs}/qcd/qcd_graphic.h (100%) rename {piqt/libs => libs}/qcd/qcd_graphic.ui (100%) rename {piqt/libs => libs}/qcd/qcd_modedialog.cpp (100%) rename {piqt/libs => libs}/qcd/qcd_modedialog.h (100%) rename {piqt/libs => libs}/qcd/qcd_modedialog.ui (100%) rename {piqt/libs => libs}/qcd/qcd_model.cpp (100%) rename {piqt/libs => libs}/qcd/qcd_model.h (100%) rename {piqt/libs => libs}/qcd/qcd_view.cpp (100%) rename {piqt/libs => libs}/qcd/qcd_view.h (100%) rename {qglview => libs/qglview}/CMakeLists.txt (97%) rename {cd_utils => libs/qglview}/LICENSE.txt (100%) rename {qglview => libs/qglview}/glcamera.cpp (100%) rename {qglview => libs/qglview}/glcamera.h (100%) rename {qglview => libs/qglview}/glframebuffer.cpp (100%) rename {qglview => libs/qglview}/glframebuffer.h (100%) rename {qglview => libs/qglview}/glmaterial.cpp (100%) rename {qglview => libs/qglview}/glmaterial.h (100%) rename {qglview => libs/qglview}/globject.cpp (100%) rename {qglview => libs/qglview}/globject.h (100%) rename {qglview => libs/qglview}/globject_editor.cpp (100%) rename {qglview => libs/qglview}/globject_editor.h (100%) rename {qglview => libs/qglview}/globject_editor.ui (100%) rename {qglview => libs/qglview}/glparticles_system.cpp (100%) rename {qglview => libs/qglview}/glparticles_system.h (100%) rename {qglview => libs/qglview}/glprimitives.cpp (100%) rename {qglview => libs/qglview}/glprimitives.h (100%) rename {qglview => libs/qglview}/glrendererbase.cpp (100%) rename {qglview => libs/qglview}/glrendererbase.h (100%) rename {qglview => libs/qglview}/glshaders.cpp (100%) rename {qglview => libs/qglview}/glshaders.h (100%) rename {qglview => libs/qglview}/gltexture_manager.cpp (100%) rename {qglview => libs/qglview}/gltexture_manager.h (100%) rename {qglview => libs/qglview}/gltypes.cpp (100%) rename {qglview => libs/qglview}/gltypes.h (100%) rename {qglview => libs/qglview}/glvbo.cpp (100%) rename {qglview => libs/qglview}/glvbo.h (100%) rename {qglview => libs/qglview}/glwidget.cpp (94%) rename {qglview => libs/qglview}/glwidget.h (97%) rename {qad => libs/qglview}/icons/alpha.png (100%) rename {kx_utils => libs/qglview}/icons/application-exit.png (100%) rename {kx_utils => libs/qglview}/icons/configure.png (100%) rename {kx_utils => libs/qglview}/icons/dialog-close.png (100%) rename {qglview => libs/qglview}/icons/document-import.png (100%) rename {qglview => libs/qglview}/icons/document-new.png (100%) rename {qglview => libs/qglview}/icons/document-open.png (100%) rename {qglview => libs/qglview}/icons/document-save-.png (100%) rename {qglview => libs/qglview}/icons/document-save-all.png (100%) rename {kx_utils => libs/qglview}/icons/document-save.png (100%) rename {kx_utils => libs/qglview}/icons/edit-clear-locationbar-rtl.png (100%) rename {kx_utils => libs/qglview}/icons/edit-clear.png (100%) rename {kx_utils => libs/qglview}/icons/edit-copy.png (100%) rename {kx_utils => libs/qglview}/icons/edit-delete.png (100%) rename {kx_utils => libs/qglview}/icons/edit-find.png (100%) rename {kx_utils => libs/qglview}/icons/edit-guides.png (100%) rename {kx_utils => libs/qglview}/icons/edit-paste.png (100%) rename {qad => libs/qglview}/icons/item-add.png (100%) rename {qad => libs/qglview}/icons/item.png (100%) rename {kx_utils => libs/qglview}/icons/list-add.png (100%) rename {qad => libs/qglview}/icons/node-add.png (100%) rename {qad => libs/qglview}/icons/node.png (100%) rename {qglengine => libs/qglview}/icons/qglview.png (100%) rename {qglengine => libs/qglview}/icons/qglview.xcf (100%) rename {qglview => libs/qglview}/icons/type-camera.png (100%) rename {qglview => libs/qglview}/icons/type-geo.png (100%) rename {qglview => libs/qglview}/icons/type-light.png (100%) rename {kx_utils => libs/qglview}/icons/view-grid.png (100%) rename {kx_utils => libs/qglview}/icons/zoom-fit-best.png (100%) rename {qglview => libs/qglview}/loader_3ds.cpp (100%) rename {qglview => libs/qglview}/loader_3ds.h (100%) rename {qglview => libs/qglview}/loader_ase.cpp (100%) rename {qglview => libs/qglview}/loader_ase.h (100%) rename {qglview => libs/qglview}/loader_dae.cpp (100%) rename {qglview => libs/qglview}/loader_dae.h (100%) rename {qglview => libs/qglview}/loader_obj.cpp (100%) rename {qglview => libs/qglview}/loader_obj.h (100%) rename {qglview => libs/qglview}/loader_qgl.cpp (100%) rename {qglview => libs/qglview}/loader_qgl.h (100%) rename {qglview => libs/qglview}/material_editor.cpp (100%) rename {qglview => libs/qglview}/material_editor.h (100%) rename {qglview => libs/qglview}/material_editor.ui (100%) rename {qglview => libs/qglview}/material_map_editor.cpp (100%) rename {qglview => libs/qglview}/material_map_editor.h (100%) rename {qglview => libs/qglview}/material_map_editor.ui (100%) rename {qglview => libs/qglview}/openglwindow.cpp (95%) rename {qglview => libs/qglview}/openglwindow.h (94%) rename {qglview => libs/qglview}/plugin/CMakeLists.txt (98%) rename {qglengine => libs/qglview}/plugin/qglview_designerplugin.cpp (100%) rename {qglengine => libs/qglview}/plugin/qglview_designerplugin.h (100%) rename {qglview => libs/qglview}/plugin/qglviewplugin.cpp (100%) rename {qglengine => libs/qglview}/plugin/qglviewplugin.h (100%) rename {qglview => libs/qglview}/propertyeditor.cpp (100%) rename {qglview => libs/qglview}/propertyeditor.h (100%) rename {qglview => libs/qglview}/qglview.cpp (96%) rename {qglview => libs/qglview}/qglview.h (97%) rename {qglview => libs/qglview}/qglview.qrc (100%) rename {qglview => libs/qglview}/qglview_test/main.cpp (100%) rename {qglview => libs/qglview}/qglview_test/qglview_window.cpp (100%) rename {qglview => libs/qglview}/qglview_test/qglview_window.h (100%) rename {qglview => libs/qglview}/qglview_test/qglview_window.ui (100%) rename {qglview => libs/qglview}/renderer_deferred_shading.cpp (100%) rename {qglview => libs/qglview}/renderer_deferred_shading.h (100%) rename {qglview => libs/qglview}/renderer_simple.cpp (100%) rename {qglview => libs/qglview}/renderer_simple.h (100%) rename {qglview => libs/qglview}/shaders/FXAA.frag (100%) rename {qglview => libs/qglview}/shaders/FXAA.vert (100%) rename {qglview => libs/qglview}/shaders/bloom_0.frag (100%) rename {qglview => libs/qglview}/shaders/bloom_1.frag (100%) rename {qglview => libs/qglview}/shaders/bloom_pass_0.frag (100%) rename {qglview => libs/qglview}/shaders/bloom_pass_0.vert (100%) rename {qglview => libs/qglview}/shaders/bloom_pass_1.frag (100%) rename {qglview => libs/qglview}/shaders/bloom_pass_1.vert (100%) rename {qglview => libs/qglview}/shaders/dof.frag (100%) rename {qglview => libs/qglview}/shaders/dof.vert (100%) rename {qglview => libs/qglview}/shaders/downscale.frag (100%) rename {qglview => libs/qglview}/shaders/downscale.vert (100%) rename {qglview => libs/qglview}/shaders/dsl_pass_0.frag (100%) rename {qglview => libs/qglview}/shaders/dsl_pass_0.vert (100%) rename {qglview => libs/qglview}/shaders/dsl_pass_1.frag (100%) rename {qglview => libs/qglview}/shaders/dsl_pass_1.vert (100%) rename {qglview => libs/qglview}/shaders/dsl_pass_2.frag (100%) rename {qglview => libs/qglview}/shaders/dsl_pass_2.vert (100%) rename {qglview => libs/qglview}/shaders/fbo_add.frag (100%) rename {qglview => libs/qglview}/shaders/fbo_add.vert (100%) rename {qglengine => libs/qglview}/shaders/fxaa_v3.h (100%) rename {qglview => libs/qglview}/shaders/hdr.frag (100%) rename {qglview => libs/qglview}/shaders/hdr.vert (100%) rename {qglview => libs/qglview}/shaders/hdr_scale_0.frag (100%) rename {qglview => libs/qglview}/shaders/hdr_scale_1.frag (100%) rename {qglview => libs/qglview}/shaders/light_models.frag (100%) rename {qglview => libs/qglview}/shaders/motion_blur.frag (100%) rename {qglview => libs/qglview}/shaders/motion_blur.vert (100%) rename {qglview => libs/qglview}/shaders/post.frag (100%) rename {qglview => libs/qglview}/shaders/ppl.frag (100%) rename {qglview => libs/qglview}/shaders/ppl.vert (100%) rename {qglview => libs/qglview}/shaders/selection.frag (100%) rename {qglview => libs/qglview}/shaders/selection.vert (100%) rename {qglview => libs/qglview}/shaders/selection_halo.frag (100%) rename {qglview => libs/qglview}/shaders/selection_halo.vert (100%) rename {qglview => libs/qglview}/shaders/shadow.frag (100%) rename {qglview => libs/qglview}/shaders/shadow.vert (100%) rename {qglview => libs/qglview}/shaders/ssao_blur.frag (100%) rename {qglview => libs/qglview}/shaders/ssao_blur.vert (100%) rename {qglview => libs/qglview}/shaders/ssao_merge.frag (100%) rename {qglview => libs/qglview}/shaders/ssao_merge.vert (100%) rename {qglview => libs/qglview}/shaders/ssr.frag (100%) rename {qglview => libs/qglview}/shaders/ssr.vert (100%) rename {qglview => libs/qglview}/shaders/ssr_blur.frag (100%) rename {qglview => libs/qglview}/shaders/ssr_blur.vert (100%) rename {qglview => libs/qglview}/shaders/ssr_merge.frag (100%) rename {qglview => libs/qglview}/shaders/ssr_merge.vert (100%) rename {qad/libs => libs}/sql_table/CMakeLists.txt (100%) rename {qad/libs => libs}/sql_table/lang/qad_sql_table_en.ts (100%) rename {qad/libs => libs}/sql_table/lang/qad_sql_table_ru.ts (100%) rename {qad/libs => libs}/sql_table/lang/update.bat (100%) rename {qad/libs => libs}/sql_table/plugin/CMakeLists.txt (100%) rename {qad/libs => libs}/sql_table/plugin/qad_sql_table.cpp (100%) rename {qad/libs => libs}/sql_table/plugin/qad_sql_table.h (100%) rename {qad/libs => libs}/sql_table/plugin/sql_record_plugin.cpp (100%) rename {qad/libs => libs}/sql_table/plugin/sql_record_plugin.h (100%) rename {qad/libs => libs}/sql_table/plugin/sql_table_plugin.cpp (100%) rename {qad/libs => libs}/sql_table/plugin/sql_table_plugin.h (100%) rename {qad/libs => libs}/sql_table/qad_sql_table.qrc (100%) rename {qad/libs => libs}/sql_table/sql_record_widget.cpp (100%) rename {qad/libs => libs}/sql_table/sql_record_widget.h (100%) rename {qad/libs => libs}/sql_table/sql_table_widget.cpp (100%) rename {qad/libs => libs}/sql_table/sql_table_widget.h (100%) rename {qad/libs => libs}/sql_table/sql_table_widget.ui (100%) rename {qad/libs => libs}/touch_widgets/CMakeLists.txt (100%) rename {qad/libs => libs}/touch_widgets/plugin/CMakeLists.txt (100%) rename {qad/libs => libs}/touch_widgets/plugin/qad_touch_widgets.cpp (100%) rename {qad/libs => libs}/touch_widgets/plugin/qad_touch_widgets.h (100%) rename {qad/libs => libs}/touch_widgets/plugin/touchbuttframeplugin.cpp (100%) rename {qad/libs => libs}/touch_widgets/plugin/touchbuttframeplugin.h (100%) rename {qad/libs => libs}/touch_widgets/plugin/touchbuttonplugin.cpp (100%) rename {qad/libs => libs}/touch_widgets/plugin/touchbuttonplugin.h (100%) rename {qad/libs => libs}/touch_widgets/plugin/touchsliderplugin.cpp (100%) rename {qad/libs => libs}/touch_widgets/plugin/touchsliderplugin.h (100%) rename {qad/libs => libs}/touch_widgets/touch_bar.h (100%) rename {qad/libs => libs}/touch_widgets/touch_widgets.qrc (100%) rename {qad/libs => libs}/touch_widgets/touchbuttframe.cpp (100%) rename {qad/libs => libs}/touch_widgets/touchbuttframe.h (100%) rename {qad/libs => libs}/touch_widgets/touchbutton.cpp (100%) rename {qad/libs => libs}/touch_widgets/touchbutton.h (100%) rename {qad/libs => libs}/touch_widgets/touchslider.cpp (100%) rename {qad/libs => libs}/touch_widgets/touchslider.h (100%) rename {qad/libs => libs}/touch_widgets/touchslider.ui (100%) rename {qad/libs => libs}/utils/CMakeLists.txt (100%) rename {qad/libs => libs}/utils/chunkstream.cpp (100%) rename {qad/libs => libs}/utils/chunkstream.h (100%) rename {qad/libs => libs}/utils/plugin/CMakeLists.txt (100%) rename {qad/libs => libs}/utils/plugin/qad_utils.cpp (100%) rename {qad/libs => libs}/utils/plugin/qad_utils.h (100%) rename {qad/libs => libs}/utils/propertystorage.cpp (100%) rename {qad/libs => libs}/utils/propertystorage.h (100%) rename {qad/libs => libs}/utils/qad_locations.cpp (100%) rename {qad/libs => libs}/utils/qad_locations.h (100%) rename {qad/libs => libs}/utils/qad_types.cpp (100%) rename {qad/libs => libs}/utils/qad_types.h (100%) rename {qad/libs => libs}/utils/qad_utils.qrc (100%) rename {qad/libs => libs}/utils/qpiconfig.cpp (100%) rename {qad/libs => libs}/utils/qpiconfig.h (100%) rename {qad/libs => libs}/utils/qpievaluator.cpp (100%) rename {qad/libs => libs}/utils/qpievaluator.h (100%) rename {qad/libs => libs}/widgets/CMakeLists.txt (100%) rename {qad/libs => libs}/widgets/chardialog.cpp (100%) rename {qad/libs => libs}/widgets/chardialog.h (100%) rename {qad/libs => libs}/widgets/chardialog.ui (100%) rename {qad/libs => libs}/widgets/clineedit.cpp (100%) rename {qad/libs => libs}/widgets/clineedit.h (100%) rename {qad/libs => libs}/widgets/colorbutton.cpp (100%) rename {qad/libs => libs}/widgets/colorbutton.h (100%) rename {qad/libs => libs}/widgets/ecombobox.cpp (100%) rename {qad/libs => libs}/widgets/ecombobox.h (100%) rename {qad/libs => libs}/widgets/evalspinbox.cpp (100%) rename {qad/libs => libs}/widgets/evalspinbox.h (100%) rename {qad/libs => libs}/widgets/iconedlabel.cpp (100%) rename {qad/libs => libs}/widgets/iconedlabel.h (100%) rename {qad/libs => libs}/widgets/image_view.cpp (100%) rename {qad/libs => libs}/widgets/image_view.h (100%) rename {qad/libs => libs}/widgets/lang/qad_widgets_en.ts (100%) rename {qad/libs => libs}/widgets/lang/qad_widgets_ru.ts (100%) rename {qad/libs => libs}/widgets/lang/update.bat (100%) rename {qad/libs => libs}/widgets/mathmatrixedit.cpp (100%) rename {qad/libs => libs}/widgets/mathmatrixedit.h (100%) rename {qad/libs => libs}/widgets/mathvectoredit.cpp (100%) rename {qad/libs => libs}/widgets/mathvectoredit.h (100%) rename {qad/libs => libs}/widgets/matrixedit.cpp (100%) rename {qad/libs => libs}/widgets/matrixedit.h (100%) rename {qad/libs => libs}/widgets/matrixedit.ui (100%) rename {qad/libs => libs}/widgets/plugin/CMakeLists.txt (100%) rename {qad/libs => libs}/widgets/plugin/chardialogplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/chardialogplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/clineeditplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/clineeditplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/colorbuttonplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/colorbuttonplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/ecomboboxplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/ecomboboxplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/evalspinboxplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/evalspinboxplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/iconedlabelplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/imageviewplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/imageviewplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/lconedlabelplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qad_widgets.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qad_widgets.h (100%) rename {qad/libs => libs}/widgets/plugin/qcodeeditplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qcodeeditplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/qipeditplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qipeditplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/qpiconfigplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qpiconfigplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/qpiconsoleplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qpiconsoleplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/qpointeditplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qpointeditplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/qrecteditplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qrecteditplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/qvarianteditplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/qvarianteditplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/scroll_spin_boxplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/scroll_spin_boxplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/shortcutsplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/shortcutsplugin.h (100%) rename {qad/libs => libs}/widgets/plugin/spinsliderplugin.cpp (100%) rename {qad/libs => libs}/widgets/plugin/spinsliderplugin.h (100%) rename {qad/libs => libs}/widgets/propertystorage_editor.cpp (100%) rename {qad/libs => libs}/widgets/propertystorage_editor.h (100%) rename {qad/libs => libs}/widgets/qad_widgets.qrc (100%) rename {qad/libs => libs}/widgets/qcodeedit.cpp (100%) rename {qad/libs => libs}/widgets/qcodeedit.h (100%) rename {qad/libs => libs}/widgets/qcodeedit.ui (100%) rename {qad/libs => libs}/widgets/qipedit.cpp (100%) rename {qad/libs => libs}/widgets/qipedit.h (100%) rename {qad/libs => libs}/widgets/qpiconfignewdialog.cpp (100%) rename {qad/libs => libs}/widgets/qpiconfignewdialog.h (100%) rename {qad/libs => libs}/widgets/qpiconfignewdialog.ui (100%) rename {qad/libs => libs}/widgets/qpiconfigvaluewidget.cpp (100%) rename {qad/libs => libs}/widgets/qpiconfigvaluewidget.h (100%) rename {qad/libs => libs}/widgets/qpiconfigwidget.cpp (100%) rename {qad/libs => libs}/widgets/qpiconfigwidget.h (100%) rename {qad/libs => libs}/widgets/qpiconsole.cpp (100%) rename {qad/libs => libs}/widgets/qpiconsole.h (100%) rename {qad/libs => libs}/widgets/qpointedit.cpp (100%) rename {qad/libs => libs}/widgets/qpointedit.h (100%) rename {qad/libs => libs}/widgets/qrectedit.cpp (100%) rename {qad/libs => libs}/widgets/qrectedit.h (100%) rename {qad/libs => libs}/widgets/qvariantedit.cpp (100%) rename {qad/libs => libs}/widgets/qvariantedit.h (100%) rename {qad/libs => libs}/widgets/qvariantedit_custom.cpp (100%) rename {qad/libs => libs}/widgets/qvariantedit_custom.h (100%) rename {qad/libs => libs}/widgets/scroll_spin_box.cpp (100%) rename {qad/libs => libs}/widgets/scroll_spin_box.h (100%) rename {qad/libs => libs}/widgets/scroll_spin_box.ui (100%) rename {qad/libs => libs}/widgets/session_manager.cpp (100%) rename {qad/libs => libs}/widgets/session_manager.h (100%) rename {qad/libs => libs}/widgets/shortcuts.cpp (100%) rename {qad/libs => libs}/widgets/shortcuts.h (100%) rename {qad/libs => libs}/widgets/spinslider.cpp (100%) rename {qad/libs => libs}/widgets/spinslider.h (100%) delete mode 100644 make_libs.bat delete mode 100755 make_libs.sh delete mode 100644 make_libs32.bat delete mode 100644 make_libs64.bat delete mode 100644 make_libs_all.bat delete mode 100644 make_libs_android.bat delete mode 100644 make_libs_android_all.bat delete mode 160000 pip delete mode 100644 piqt/CMakeLists.txt delete mode 100644 piqt/LICENSE.txt delete mode 100644 piqt/libs/CMakeLists.txt delete mode 100644 piqt/utils/CMakeLists.txt delete mode 100644 project_fs/ProjectFilesystemPlugin.json.in delete mode 100644 project_fs/filterdialog.cpp delete mode 100644 project_fs/filterdialog.h delete mode 100644 project_fs/filterdialog.ui delete mode 100644 project_fs/icons/utilities-terminal.png delete mode 100644 project_fs/projectfilesystem.qrc delete mode 100644 project_fs/projectfilesystemplugin.cpp delete mode 100644 project_fs/projectfilesystemplugin.h delete mode 100644 project_fs/projectfilesystemplugin.pro delete mode 100644 project_fs/projectfilesystemplugin_global.h delete mode 100644 project_fs/projectfilesystempluginconstants.h delete mode 100644 project_fs/projectfilesystemwidget.cpp delete mode 100644 project_fs/projectfilesystemwidget.h delete mode 100644 project_fs/projectfilesystemwidget.ui delete mode 100644 project_fs/projectfilesystemwidgetplugin.cpp delete mode 100644 project_fs/projectfilesystemwidgetplugin.h delete mode 100644 qad/CMakeLists.txt delete mode 100644 qad/LICENSE.txt delete mode 100644 qad/icons/edit-find.png delete mode 100644 qglengine/CMakeLists.txt delete mode 100644 qglengine/LICENSE.txt delete mode 100644 qglengine/coeffs_brdf.png delete mode 100644 qglengine/core/glbuffer.cpp delete mode 100644 qglengine/core/glbuffer.h delete mode 100644 qglengine/core/glcubemap.cpp delete mode 100644 qglengine/core/glcubemap.h delete mode 100644 qglengine/core/glframebuffer.cpp delete mode 100644 qglengine/core/glframebuffer.h delete mode 100644 qglengine/core/glframebuffer_mipmap.cpp delete mode 100644 qglengine/core/glframebuffer_mipmap.h delete mode 100644 qglengine/core/glmaterial.cpp delete mode 100644 qglengine/core/glmaterial.h delete mode 100644 qglengine/core/glmesh.cpp delete mode 100644 qglengine/core/glmesh.h delete mode 100644 qglengine/core/glprimitives.cpp delete mode 100644 qglengine/core/glprimitives.h delete mode 100644 qglengine/core/glshaders.cpp delete mode 100644 qglengine/core/glshaders.h delete mode 100644 qglengine/core/glshaders_headers.h delete mode 100644 qglengine/core/glshaders_types.cpp delete mode 100644 qglengine/core/glshaders_types.h delete mode 100644 qglengine/core/gltexturearray.cpp delete mode 100644 qglengine/core/gltexturearray.h delete mode 100644 qglengine/core/gltransform.cpp delete mode 100644 qglengine/core/gltransform.h delete mode 100644 qglengine/core/gltypes.cpp delete mode 100644 qglengine/core/gltypes.h delete mode 100644 qglengine/core/glvertexobject.cpp delete mode 100644 qglengine/core/glvertexobject.h delete mode 100644 qglengine/core/hdr.cpp delete mode 100644 qglengine/core/hdr_p.h delete mode 100644 qglengine/formats/loader_assimp.cpp delete mode 100644 qglengine/formats/loader_assimp.h delete mode 100644 qglengine/formats/loader_qgl.cpp delete mode 100644 qglengine/formats/loader_qgl.h delete mode 100644 qglengine/glcamera.cpp delete mode 100644 qglengine/glcamera.h delete mode 100644 qglengine/globject.cpp delete mode 100644 qglengine/globject.h delete mode 100644 qglengine/glrendererbase.cpp delete mode 100644 qglengine/glrendererbase.h delete mode 100644 qglengine/glscene.cpp delete mode 100644 qglengine/glscene.h delete mode 100644 qglengine/gltexture_manager.cpp delete mode 100644 qglengine/gltexture_manager.h delete mode 100644 qglengine/glwidget.cpp delete mode 100644 qglengine/glwidget.h delete mode 100644 qglengine/icons/add-type-camera.png delete mode 100644 qglengine/icons/add-type-empty.png delete mode 100644 qglengine/icons/add-type-geo.png delete mode 100644 qglengine/icons/add-type-light.png delete mode 100644 qglengine/icons/alpha.png delete mode 100644 qglengine/icons/application-exit.png delete mode 100644 qglengine/icons/collapse.png delete mode 100644 qglengine/icons/configure.png delete mode 100644 qglengine/icons/dialog-cancel.png delete mode 100644 qglengine/icons/dialog-close.png delete mode 100644 qglengine/icons/document-edit.png delete mode 100644 qglengine/icons/document-import.png delete mode 100644 qglengine/icons/document-new.png delete mode 100644 qglengine/icons/document-open.png delete mode 100644 qglengine/icons/document-save-all.png delete mode 100644 qglengine/icons/document-save.png delete mode 100644 qglengine/icons/edit-clear-locationbar-rtl.png delete mode 100644 qglengine/icons/edit-clear.png delete mode 100644 qglengine/icons/edit-copy.png delete mode 100644 qglengine/icons/edit-delete.png delete mode 100644 qglengine/icons/edit-find.png delete mode 100644 qglengine/icons/edit-paste.png delete mode 100644 qglengine/icons/edit-rename.png delete mode 100644 qglengine/icons/expand.png delete mode 100644 qglengine/icons/format-fill-color.png delete mode 100644 qglengine/icons/go-jump.png delete mode 100644 qglengine/icons/go-top.png delete mode 100644 qglengine/icons/group.png delete mode 100644 qglengine/icons/layer-visible-off.png delete mode 100644 qglengine/icons/layer-visible-on.png delete mode 100644 qglengine/icons/light-+.png delete mode 100644 qglengine/icons/list-add.png delete mode 100644 qglengine/icons/object-flip-horizontal.png delete mode 100644 qglengine/icons/object-flip-vertical.png delete mode 100644 qglengine/icons/picker.png delete mode 100644 qglengine/icons/transform-move.png delete mode 100644 qglengine/icons/transform-rotate.png delete mode 100644 qglengine/icons/transform-scale.png delete mode 100644 qglengine/icons/type-camera.png delete mode 100644 qglengine/icons/type-empty.png delete mode 100644 qglengine/icons/type-geo.png delete mode 100644 qglengine/icons/type-light.png delete mode 100644 qglengine/icons/view-refresh.png delete mode 100644 qglengine/mouse_controller.cpp delete mode 100644 qglengine/mouse_controller.h delete mode 100644 qglengine/openglwindow.cpp delete mode 100644 qglengine/openglwindow.h delete mode 100644 qglengine/plugin/CMakeLists.txt delete mode 100644 qglengine/plugin/qglviewplugin.cpp delete mode 100644 qglengine/qglview.cpp delete mode 100644 qglengine/qglview.h delete mode 100644 qglengine/qglview.qrc delete mode 100644 qglengine/qglview_test/main.cpp delete mode 100644 qglengine/qglview_test/qglview_window.cpp delete mode 100644 qglengine/qglview_test/qglview_window.h delete mode 100644 qglengine/qglview_test/qglview_window.ui delete mode 100644 qglengine/renderer.cpp delete mode 100644 qglengine/renderer.h delete mode 100644 qglengine/renderer_base.cpp delete mode 100644 qglengine/renderer_base.h delete mode 100644 qglengine/renderer_material.cpp delete mode 100644 qglengine/renderer_material.h delete mode 100644 qglengine/renderer_selection.cpp delete mode 100644 qglengine/renderer_selection.h delete mode 100644 qglengine/renderer_service.cpp delete mode 100644 qglengine/renderer_service.h delete mode 100644 qglengine/shaders.qrc delete mode 100644 qglengine/shaders/ds_final.glsl delete mode 100644 qglengine/shaders/ds_geom.glsl delete mode 100644 qglengine/shaders/ds_light.glsl delete mode 100644 qglengine/shaders/ds_tonemap.glsl delete mode 100644 qglengine/shaders/fxaa.frag delete mode 100644 qglengine/shaders/fxaa.vert delete mode 100644 qglengine/shaders/selection.glsl delete mode 100644 qglengine/shaders/selection_apply.glsl delete mode 100644 qglengine/shaders/selection_frame.glsl delete mode 100644 qglengine/shaders/selection_halo.glsl delete mode 100644 qglengine/shaders/service_fill.glsl delete mode 100644 qglengine/shaders/service_frame.glsl delete mode 100644 qglengine/shaders/service_line.glsl delete mode 100644 qglengine/shaders/sum.glsl delete mode 100644 qglengine/tonemapping_proc.cpp delete mode 100644 qglengine/tonemapping_proc.h delete mode 100644 qglengine/widgets/CMakeLists.txt delete mode 100644 qglengine/widgets/material_editor.cpp delete mode 100644 qglengine/widgets/material_editor.h delete mode 100644 qglengine/widgets/material_editor.ui delete mode 100644 qglengine/widgets/material_map_editor.cpp delete mode 100644 qglengine/widgets/material_map_editor.h delete mode 100644 qglengine/widgets/material_map_editor.ui delete mode 100644 qglengine/widgets/materials_editor.cpp delete mode 100644 qglengine/widgets/materials_editor.h delete mode 100644 qglengine/widgets/materials_editor.ui delete mode 100644 qglengine/widgets/object_editor.cpp delete mode 100644 qglengine/widgets/object_editor.h delete mode 100644 qglengine/widgets/object_editor.ui delete mode 100644 qglengine/widgets/primitiveeditor.cpp delete mode 100644 qglengine/widgets/primitiveeditor.h delete mode 100644 qglengine/widgets/primitiveeditor.ui delete mode 100644 qglengine/widgets/propertyeditor.cpp delete mode 100644 qglengine/widgets/propertyeditor.h delete mode 100644 qglengine/widgets/scene_tree.cpp delete mode 100644 qglengine/widgets/scene_tree.h delete mode 100644 qglengine/widgets/scene_tree.ui delete mode 100644 qglengine/widgets/treewidget_p.h delete mode 100644 qglengine/widgets/view_editor.cpp delete mode 100644 qglengine/widgets/view_editor.h delete mode 100644 qglengine/widgets/view_editor.ui delete mode 100644 qglengine/widgets/widgets.qrc delete mode 100644 qglview/LICENSE.txt delete mode 100644 qglview/icons/alpha.png delete mode 100644 qglview/icons/application-exit.png delete mode 100644 qglview/icons/configure.png delete mode 100644 qglview/icons/dialog-close.png delete mode 100644 qglview/icons/document-save.png delete mode 100644 qglview/icons/edit-clear-locationbar-rtl.png delete mode 100644 qglview/icons/edit-clear.png delete mode 100644 qglview/icons/edit-copy.png delete mode 100644 qglview/icons/edit-delete.png delete mode 100644 qglview/icons/edit-find.png delete mode 100644 qglview/icons/edit-guides.png delete mode 100644 qglview/icons/edit-paste.png delete mode 100644 qglview/icons/item-add.png delete mode 100644 qglview/icons/item.png delete mode 100644 qglview/icons/list-add.png delete mode 100644 qglview/icons/node-add.png delete mode 100644 qglview/icons/node.png delete mode 100644 qglview/icons/qglview.png delete mode 100644 qglview/icons/qglview.xcf delete mode 100644 qglview/icons/view-grid.png delete mode 100644 qglview/icons/zoom-fit-best.png delete mode 100644 qglview/plugin/qglview_designerplugin.cpp delete mode 100644 qglview/plugin/qglview_designerplugin.h delete mode 100644 qglview/plugin/qglviewplugin.h delete mode 100644 qglview/shaders/fxaa_v3.h rename {qad/utils => utils}/CMakeLists.txt (100%) rename {qad/utils => utils}/blockeditor/CMakeLists.txt (100%) rename {qad/utils => utils}/blockeditor/blockeditor_main.cpp (100%) rename {qad/utils => utils}/blockeditor/icons/blockview.ico (100%) rename {qad/utils => utils}/blockeditor/icons/blockview.png (100%) rename {piqt/utils => utils}/cd_pult/CMakeLists.txt (100%) rename {piqt/utils => utils}/cd_pult/cddirectk.cpp (100%) rename {piqt/utils => utils}/cd_pult/cddirectk.h (100%) rename {piqt/utils => utils}/cd_pult/cddirectk.ui (100%) rename {piqt/utils => utils}/cd_pult/cddirectk_type_dialog.cpp (100%) rename {piqt/utils => utils}/cd_pult/cddirectk_type_dialog.h (100%) rename {piqt/utils => utils}/cd_pult/cddirectk_type_dialog.ui (100%) rename {piqt/utils => utils}/cd_pult/cdgraphics.cpp (100%) rename {piqt/utils => utils}/cd_pult/cdgraphics.h (100%) rename {piqt/utils => utils}/cd_pult/cdgraphics.ui (100%) rename {piqt/utils => utils}/cd_pult/cdpult.qrc (100%) rename {piqt/utils => utils}/cd_pult/cdpultwindow.cpp (100%) rename {piqt/utils => utils}/cd_pult/cdpultwindow.h (100%) rename {piqt/utils => utils}/cd_pult/cdpultwindow.ui (100%) rename {piqt/utils => utils}/cd_pult/cdviewwidget.cpp (100%) rename {piqt/utils => utils}/cd_pult/cdviewwidget.h (100%) rename {piqt/utils => utils}/cd_pult/cdviewwidget.ui (100%) rename {piqt/utils => utils}/cd_pult/icons/Apps-accessories-calculator-icon.png (100%) rename {piqt/utils => utils}/cd_pult/icons/accessories-text-editor.png (100%) rename {piqt/utils => utils}/cd_pult/icons/db-export.png (100%) rename {piqt/utils => utils}/cd_pult/icons/db-import.png (100%) rename {piqt/utils => utils}/cd_pult/icons/flame.png (100%) rename {piqt/utils => utils}/cd_pult/icons/timer.png (100%) rename {piqt/utils => utils}/cd_pult/main.cpp (100%) rename {piqt/utils => utils}/piconnedit/CMakeLists.txt (100%) rename {piqt/utils => utils}/piconnedit/piconnedit.qrc (100%) rename {piqt/utils => utils}/piconnedit/piconnedit_main.cpp (100%) rename {piqt/utils => utils}/pidumper/CMakeLists.txt (100%) rename {piqt/utils => utils}/pidumper/pidumper.cpp (100%) rename {piqt/utils => utils}/pidumper/pidumper.h (100%) rename {piqt/utils => utils}/pidumper/pidumper.ui (100%) rename {piqt/utils => utils}/pidumper/pidumper_main.cpp (100%) rename {piqt/utils => utils}/piintrospector/CMakeLists.txt (100%) rename {piqt/utils => utils}/piintrospector/containers_view.cpp (100%) rename {piqt/utils => utils}/piintrospector/containers_view.h (100%) rename {piqt/utils => utils}/piintrospector/containers_view.ui (100%) rename {piqt/utils => utils}/piintrospector/objects_view.cpp (100%) rename {piqt/utils => utils}/piintrospector/objects_view.h (100%) rename {piqt/utils => utils}/piintrospector/objects_view.ui (100%) rename {piqt/utils => utils}/piintrospector/piintrospector.cpp (100%) rename {piqt/utils => utils}/piintrospector/piintrospector.h (100%) rename {piqt/utils => utils}/piintrospector/piintrospector.ui (100%) rename {piqt/utils => utils}/piintrospector/piintrospector_main.cpp (100%) rename {piqt/utils => utils}/piintrospector/threads_view.cpp (100%) rename {piqt/utils => utils}/piintrospector/threads_view.h (100%) rename {piqt/utils => utils}/piintrospector/threads_view.ui (100%) rename {qad/utils => utils}/qpicalculator/CMakeLists.txt (100%) rename {qad/utils => utils}/qpicalculator/icons/qpicalculator.ico (100%) rename {qad/utils => utils}/qpicalculator/icons/qpicalculator.png (100%) rename {qad/utils => utils}/qpicalculator/main.cpp (100%) rename {qad/utils => utils}/qpicalculator/mainwindow.cpp (100%) rename {qad/utils => utils}/qpicalculator/mainwindow.h (100%) rename {qad/utils => utils}/qpicalculator/mainwindow.ui (100%) rename {qad/utils => utils}/qpicalculator/qpicalculator.qrc (100%) diff --git a/.gitignore b/.gitignore index 539fedd..8a2cb3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ /.svn CMakeLists.txt.user* -/project_fs_build -/qad/qad_version.h -/qglengine/core/qglengine_version.h diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index bd49571..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "pip"] - path = pip - url = https://git.shs.tools/SHS/pip.git diff --git a/CMakeLists.txt b/CMakeLists.txt index b8390db..fa769fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,29 +1,12 @@ cmake_minimum_required(VERSION 3.0) -cmake_policy(SET CMP0011 NEW) # don`t affect includer policies cmake_policy(SET CMP0017 NEW) # need include() with .cmake -cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows -if (POLICY CMP0053) - cmake_policy(SET CMP0053 NEW) # simpler variable expansion and escape sequence evaluation rules -endif() -project(libs) -set(PIP_CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pip/cmake") -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${PIP_CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/qad/cmake") -set(LIBPROJECT 1) -set(_qt_libs ) -set(_qt_apps ) -set(_qt_plugs) -include(GenerateExportHeader) -include(SDKMacros) -include(QADMacros) -include(DeployMacros) +project(qad) -if(NOT DEFINED BUILD_NUMBER) - set(BUILD_NUMBER 9999) +find_package(MinGW REQUIRED) +if (NOT DEFINED ANDROID_PLATFORM) + find_package(OpenGL REQUIRED) endif() -if("x${BUILD_NUMBER}" STREQUAL "x") - set(BUILD_NUMBER 0) -endif() - +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) if(STATIC_LIB) set(QAD_LIB_TYPE STATIC) @@ -52,249 +35,29 @@ set_deploy_property(QAD ${QAD_LIB_TYPE} FULLNAME "${_QAD_DOMAIN}.*" COMPANY "${_QAD_COMPANY}") - -if(STATIC_LIB) - set(PIQt_LIB_TYPE STATIC) - add_definitions(-DPIQt_STATIC_DEFINE) - set(PIQt_LIB_TYPE_MSG "Static") -else() - set(PIQt_LIB_TYPE SHARED) - set(PIQt_LIB_TYPE_MSG "Shared") +# Version +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h") + file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h") endif() +#message(STATUS "Building QAD version ${QAD_VERSION} (${QAD_LIB_TYPE})") -set(_PIQt_MAJOR 1) -set(_PIQt_MINOR 0) -set(_PIQt_REVISION 0) -set(_PIQt_SUFFIX ) -set(_PIQt_COMPANY SHS) -set(_PIQt_DOMAIN org.SHS) -if(NOT DEFINED BUILD_NUMBER) - set(BUILD_NUMBER 9999) -endif() -set(PIQt_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/piqt/piqt_version.h") -set_version(PIQt - MAJOR "${_PIQt_MAJOR}" - MINOR "${_PIQt_MINOR}" - REVISION "${_PIQt_REVISION}" - BUILD "${BUILD_NUMBER}" - SUFFIX "${_PIQt_SUFFIX}" - OUTPUT "${PIQt_VERSION_FILE}") -set_deploy_property(PIQt ${_PIQt_LIB_TYPE} - FULLNAME "${_PIQt_DOMAIN}.*" - COMPANY "${_PIQt_COMPANY}") +file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in") - -include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/qad) -include_directories(${CMAKE_CURRENT_BINARY_DIR}/piqt) -if(MINGW) - find_package(MinGW REQUIRED) -else() - if(APPLE) - set(CMAKE_INSTALL_RPATH "@executable_path/../Frameworks;@executable_path/lib;@loader_path/../lib") - set(CMAKE_MACOSX_RPATH TRUE) - if(CMAKE_CROSSCOMPILING) - set(CMAKE_INSTALL_NAME_DIR "@rpath") - else() - include_directories(/usr/local/include) - link_directories(/usr/local/lib) - endif() - else() - set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib") - endif() -endif() -if (DEFINED ANDROID_PLATFORM) - include_directories(${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include) - #set(TARGET_INSTALL_PATH "${ANDROID_SYSTEM_LIBRARY_PATH}/usr/") - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${ANDROID_NDK}/sysroot/usr/include") - #message("${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include") - #message("${ANDROID_NDK}/sysroot/usr/include") -endif() -set(INSTALL_PREFIX "") -set(_plugins_default_ ON) -if(CMAKE_CROSSCOMPILING) - if (DEFINED ANDROID_PLATFORM) - set(_plugins_default_ OFF) - set(INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}/") - else() - set(INSTALL_PREFIX "${CMAKE_STAGING_PREFIX}") - endif() -endif() -option(CROSSTOOLS "Crosstools minimal build" OFF) -option(LIB "System install" ON) -option(QGLVIEW "Build QGLview library and utils" OFF) -option(QGLENGINE "Build QGLENGINE library and utils" OFF) -option(UTILS "Build various utils" ${_plugins_default_}) -option(DESIGNER_PLUGINS "Build qt designer plugins" ${_plugins_default_}) -option(STATIC_LIB OFF) -if (CROSSTOOLS) - set(LIB 1) - set(QGLVIEW 0) - set(QGLENGINE 0) - set(UTILS 0) - set(DESIGNER_PLUGINS 0) -endif() -if (CMAKE_BUILD_TYPE MATCHES Debug) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3 -Wall") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g3 -Wall") -else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wall") -endif() -set(CMAKE_CXX_STANDARD 11) - -set(PIP_LIBRARY pip) -set(PIP_INCLUDES) - -if(LIB) - if(WIN32) - if(MINGW) - set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) - endif() - else() - if (DEFINED ANDROID_PLATFORM) - set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr) - else() - if(CMAKE_CROSSCOMPILING) - set(CMAKE_INSTALL_PREFIX ${CMAKE_STAGING_PREFIX}) - else() - set(CMAKE_INSTALL_PREFIX ${INSTALL_PREFIX}/usr/local) - endif() - endif() - endif() - message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"") -else() - message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"") -endif() - -#message(${PIP_INCLUDES}) -if(CMAKE_CROSSCOMPILING OR (DEFINED ANDROID_PLATFORM)) - set(PIP_CMG "pip_cmg") - set(PIP_RC "pip_rc") - set(PIP_DEPLOY_TOOL "deploy_tool") -else() - set(PIP_CMG "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/code_model_generator/pip_cmg") - set(PIP_RC "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/resources_compiler/pip_rc") - set(PIP_DEPLOY_TOOL "${CMAKE_CURRENT_BINARY_DIR}/pip/utils/deploy_tool/deploy_tool") -endif() -if(WIN32) - set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}/pip") -endif() - -set(QAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/qad) -set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - -if (CROSSTOOLS) - - add_subdirectory(pip) - file(GLOB CMAKES "qad/cmake/*.cmake" "qad/cmake/*.in") +if (LIB) install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules) - -else() - - include(QtWraps) - find_qt(Core QUIET) - set(QtVersions) - set(SomeQtFound 0) - foreach(_v ${_QT_VERSIONS_}) - option(Qt${_v} "Build for Qt${_v}" 1) - if (Qt${_v}) - #message("Qt${_v} -> ${LOCAL_FOUND${_v}}") - if (LOCAL_FOUND${_v}) - list(APPEND QtVersions Qt${_v}) - set(SomeQtFound 1) - endif() - endif() - endforeach() - - #if(UTILS) - # message(STATUS "Building with utils") - #else() - # message(STATUS "Building only libraries") - #endif() - - add_subdirectory(pip) - foreach(F ${PIP_MAIN_FOLDERS}) - list(APPEND PIP_INCLUDES "${F}") - endforeach(F) - add_subdirectory(cd_utils) - include_directories("${CMAKE_CURRENT_SOURCE_DIR}/cd_utils" "${CMAKE_CURRENT_BINARY_DIR}/cd_utils") - set(_DIRS) - if (SomeQtFound) - #message(STATUS "Building Qt-derived targets for ${QtVersions}") - add_subdirectory(qad) - include_directories(${qad_includes}) - add_subdirectory(piqt) - include_directories(${piqt_includes}) - set(_DIRS) - if (Qt5) - if (QGLVIEW) - list(APPEND _DIRS qglview) - endif() - if (QGLENGINE) - list(APPEND _DIRS qglengine) - endif() - endif() - foreach(_D ${_DIRS}) - list(APPEND QT_MULTILIB_LIST ${_D}) - add_subdirectory(${_D}) - endforeach(_D) - - macro(align_list _list _out) - set(_max_len 0) - foreach(_m ${_list}) - string(LENGTH "${_m}" _clen) - if (_clen GREATER _max_len) - set(_max_len ${_clen}) - endif() - endforeach() - set(${_out}) - foreach(_m ${_list}) - set(_am "${_m}") - while(TRUE) - string(LENGTH "${_am}" _clen) - if (_clen GREATER_EQUAL ${_max_len}) - break() - endif() - string(APPEND _am " ") - endwhile() - list(APPEND ${_out} "${_am}") - endforeach() - endmacro() - - macro(print_list _list _name) - if (NOT "x${_list}" STREQUAL "x") - message("") - message(" ${_name}:") - #align_list("${_list}" _alist) - foreach(_m ${_list}) - message(" * ${_m}") - endforeach() - endif() - endmacro() - - message("----------QAD-----------") - message(" Build for ${QtVersions}") - message(" QAD Version: ${QAD_VERSION}") - message(" QAD Linkage: ${QAD_LIB_TYPE_MSG}") - message(" PIQt Version: ${PIQt_VERSION}") - message(" PIQt Linkage: ${PIQt_LIB_TYPE_MSG}") - print_list("${_qt_libs}" "Libraries") - print_list("${_qt_apps}" "Applications") - print_list("${_qt_plugs}" "Plugins") - message("-----------------------") - message("") - + if (WIN32) + install(FILES ${QAD_VERSION_FILE} DESTINATION ${MINGW_INCLUDE}/qad) else() - message(STATUS "None of Qt found, skip Qt-derived targets") + install(FILES ${QAD_VERSION_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qad) endif() - +else() + install(FILES ${QAD_VERSION_FILE} DESTINATION include/qad) endif() -if(WIN32) - foreach(PIP_LT ${PIP_MODULES}) - if (SomeQtFound) - qt_install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pip/lib${PIP_LT}.dll" DESTINATION QtBin) - endif() - endforeach() +add_subdirectory(libs) +if (UTILS) + add_subdirectory(utils) endif() + +copy_to_parent(qad_includes) + diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index aa1dfb8..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,62 +0,0 @@ -def build_docker(name) { - def image = "${name}-libs" - echo "Build image ${image}" - def pref = "" - if (env.DOCKER_PREFIX) { - pref = "--build-arg DOCKER_PREFIX=${env.DOCKER_PREFIX}/" - } - def jobs = 4 - if (env.JOBS_COUNT) { - jobs = "${env.JOBS_COUNT}" - } - def args = "${pref} --build-arg LIBS_BUILD_NUMBER=${env.BUILD_NUMBER} --build-arg JOBS_COUNT=${jobs}" - dir ("docker/${image}") { - sh "docker build ${args} --no-cache -t ${image} ." - } - return "\n - ${image}" -} -node { - stage("checkout") { - checkout scm - } - def _envmap = [:] - def _env = sh(script: "env", returnStdout: true).trim().split("\n") - _env.each{ l -> - def _ind = l.indexOf('='); - def _n = l.substring(0, _ind); - def _v = l.substring(_ind + 1); - _envmap["${_n}"] = "${_v}"; - } - def _msg = "Built images:" - def platforms = ['debian', 'osx', 'windows', 'android', 'pi'] - for (int i = 0; i < platforms.size(); ++i) { - if (_envmap["BUILD_${platforms[i]}"] == "1") { - stage("${platforms[i]}-libs") { - _msg += build_docker("${platforms[i]}") - } - } - } - sh "docker system prune -f" - echo "${_msg}" -} -pipeline { - agent { - label 'master' - } - stages { - stage("PIP doc") { - steps { - checkout scm - sh "rm -rf share" - sh "rm -vf *.zip" - sh "mkdir -p build" - sh "cd build && cmake -DLIB=0 -DCMAKE_INSTALL_PREFIX=`pwd` ../" - sh "cd build && make doc" - sh "cd share/doc && zip -r ../../pip_doc.zip pip" - sh "cp share/doc/pip/html/pip.qch ./" - archiveArtifacts 'pip_doc.zip' - archiveArtifacts 'pip.qch' - } - } - } -} diff --git a/README.md b/README.md index 9ac5e18..5c60939 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,10 @@ -# Main SHS SDK libraries repo +# Qt for ADvanced ## Introduction -This repo contains PIP, QAD and derived projects: -* cd_utils - PIP-based client/server library for read, transmit and use custom structures of coefficients +This repo contains QAD and PIQt projects: + * qcd_utils - Qt bindings to CDUtils and "CD Pult" executable - full-featured CD client * piqt - helpers to convert PIP <-> Qt types * piqt_utils - Gui libraries and executables to edit PIConnection configs and watch PIIntrospection * qglview - old Qt-base OpenGL engine -* qglengine - new Qt-base OpenGL engine - -## Compile -This repo can be compile with GCC/MinGW/Clang, for Qt 4/5. - -If there is no Qt found, builds only PIP and cd_utils. - -CMake options: -* **LIB** - if 1 then install to system directories: MinGW on Windows, /usr/local on Linux/MacOS, ${ANDROID_SYSTEM_LIBRARY_PATH} on Android. If 0 then install to ${CMAKE_INSTALL_PREFIX}. Enabled by default -* **UTILS** - build or not executable utilites, enabled by default -* **DESIGNER_PLUGINS** - build or not Qt Designer plugins, enabled by default -* **QGLVIEW** - build or not QGLView, disabled by default -* **QGLENGINE** - build or not QGLEngine, disabled by default - -## Windows scripts -Build steps for i686 architecture: -1. unzip mingw.7z to C:\mingw -2. unzip qt.7z to C:\qt -3. download and install cmake from https://cmake.org/download/ -4. Prepare environment - - set prefix for mingw e.g.: for C:\mingw\7_1_x32\ - set SDK_MINGW_DIR=C:\mingw\7_1_x - - set prefix for Qt5 e.g.: for C:\qt\qt5120_win32\ - set SDK_QT5_DIR=C:\qt\qt5120_win - - set SDK_CMAKE_DIR=C:\cmake -5. run make_libs32.bat - -Build steps for amd64 architecture: - -- follow previos steps, but replace '32' to '64' - -Build steps for both architectures: - -- follow previos steps, but on '4' state run make_libs_all.bat - -## Non-Windows scripts -Script "make_libs.sh" compile and install SDK for current environment, e.g. -`./make_libs.sh -j4` - -## Docker -This repo provide Dockerfile, so you can exec `docker build -t libs .` in this directory -and make docker image "libs" with installed SHS SDK for: -* Debian 10 -* Windows x64 -* MacOS -* Android ndk 21 armeabi-v71, arm64-v8a, x86, x86_64 diff --git a/SDKMacros.cmake b/SDKMacros.cmake deleted file mode 100644 index de07b6a..0000000 --- a/SDKMacros.cmake +++ /dev/null @@ -1,107 +0,0 @@ - -macro(sdk_install _DIR IS_APP _TARGET _H_FILES _QM_FILES) - #message("QM=${_QM_FILES}") - if((NOT ${IS_APP}) AND (NOT "${_H_FILES}" STREQUAL "")) - if(LIB) - if(WIN32) - install(FILES ${_H_FILES} DESTINATION ${MINGW_INCLUDE}/${_DIR}) - else() - install(FILES ${_H_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${_DIR}) - endif() - else() - install(FILES ${_H_FILES} DESTINATION include/${_DIR}) - endif() - endif() - if (NOT "${_TARGET}" STREQUAL "") - if(LIB) - if(WIN32) - if (${IS_APP}) - qt_install(TARGETS ${_TARGET} DESTINATION ${MINGW_BIN}) - qt_install(TARGETS ${_TARGET} DESTINATION QtBin) - else() - qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION ${MINGW_LIB}) - qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION ${MINGW_BIN}) - qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION QtBin) - endif() - else() - if (${IS_APP}) - qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) - else() - qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) - endif() - endif() - if(NOT "x${_QM_FILES}" STREQUAL "x") - qt_install(LANG ${_QM_FILES} DESTINATION QtLang) - endif() - else() - if(${IS_APP}) - qt_install(TARGETS ${_TARGET} DESTINATION bin) - else() - if(WIN32) - qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION bin) - qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION lib) - else() - qt_install(TARGETS ${_TARGET} DESTINATION lib) - endif() - endif() - if(NOT "x${_QM_FILES}" STREQUAL "x") - qt_install(LANG ${_QM_FILES} DESTINATION lang) - endif() - endif() - endif() -endmacro() - - -macro(copy_to_parent _inc_var) - set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE) - set(_qt_libs ${_qt_libs} PARENT_SCOPE) - set(_qt_apps ${_qt_apps} PARENT_SCOPE) - set(_qt_plugs ${_qt_plugs} PARENT_SCOPE) - if (NOT "x${_inc_var}" STREQUAL "x") - set(${_inc_var} ${${_inc_var}} PARENT_SCOPE) - endif() - if (LIB) - set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) - endif() -endmacro() - - -macro(add_directories_with_include multilib_prefix) - set(DIRS) - file(GLOB _dl "[^.]*") - foreach(_d ${_dl}) - if(IS_DIRECTORY ${_d}) - list(APPEND DIRS ${_d}) - endif() - endforeach() - - set(inc_var ${multilib_prefix}includes) - set(${inc_var}) - foreach(_d ${DIRS}) - get_filename_component(_dname "${_d}" NAME) - list(APPEND QT_MULTILIB_LIST ${multilib_prefix}${_dname}) - list(APPEND ${inc_var} "${_d}") - list(APPEND ${inc_var} "${CMAKE_CURRENT_BINARY_DIR}/${_dname}") - endforeach() - - include_directories(${${inc_var}}) - foreach(_d ${DIRS}) - add_subdirectory(${_d}) - endforeach() - - copy_to_parent(${inc_var}) -endmacro() - - -macro(add_directories multilib_prefix) - include_directories(${${multilib_prefix}includes}) - file(GLOB _dl "[^.]*") - foreach(_d ${_dl}) - if(IS_DIRECTORY ${_d}) - add_subdirectory(${_d}) - endif() - endforeach() - - copy_to_parent(${multilib_prefix}includes) -endmacro() - diff --git a/cd_utils/CMakeLists.txt b/cd_utils/CMakeLists.txt deleted file mode 100644 index f1c6a5d..0000000 --- a/cd_utils/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -project(cd_utils) -find_package(MinGW REQUIRED) -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES}) -file(GLOB CPPS_UTILS "cdutils_*.cpp") -file(GLOB HDRS_UTILS "cdutils_*.h") -add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS} ${HDRS_UTILS}) -target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY}) -generate_export_header(${PROJECT_NAME}) -list(APPEND HDRS_UTILS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h") - -add_executable(cdutilstest "cdutilstest.cpp" "cdtest.h") -target_link_libraries(cdutilstest ${PIP_LIBRARY} ${PROJECT_NAME}) -message(STATUS "Building ${PROJECT_NAME}") - -if(LIB) - list(APPEND _ALL_TARGETS ${PROJECT_NAME}) - set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) - if(WIN32) - install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE}) - install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${MINGW_LIB}) - install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN}) - else() - install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) - install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) - endif() - #message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"") -else() - if(WIN32) - install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) - install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib) - else() - install(TARGETS ${PROJECT_NAME} DESTINATION lib) - endif() - install(FILES ${HDRS_UTILS} DESTINATION include) - #message(STATUS "Install ${PROJECT_NAME} to local \"bin\"") -endif() diff --git a/cd_utils/cdtest.h b/cd_utils/cdtest.h deleted file mode 100644 index c2e45d6..0000000 --- a/cd_utils/cdtest.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CDTEST_H -#define CDTEST_H - - -enum KDescription { - First, //f Первый - Second, //b Второй -}; - -#endif // CDTEST_H diff --git a/cd_utils/cdutils_c.cpp b/cd_utils/cdutils_c.cpp deleted file mode 100644 index 30a5fae..0000000 --- a/cd_utils/cdutils_c.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "cdutils_c.h" -#include "cdutils_core.h" - -using namespace CDUtils; - -CInterface C; - - -CInterface::CInterface(): Interface(CDType::cdC) { -} - - -void CInterface::sendCommand(const CDType & c) { - core->sendCommand(c); -} - - -void CInterface::connect(const CDType & c, PIObject * o, Handler eh) { - core->registerCHandler(c, o, eh); -} - - -void CInterface::autoConnect(PIObject * o, const PIString & prefix) { - if (!o) return; - uint cid = o->classNameID(); - if (!PIObject::__meta_data().contains(cid)) return; - PIMap eh_map; - PIObject::__MetaData & md(PIObject::__meta_data()[cid]); - PIMap::const_iterator it; - for (it = md.eh_func.constBegin(); it != md.eh_func.constEnd(); ++it) { - eh_map[it.value().func_name] = (Handler)it.value().addr; - //piCout << "func" << it.value().func_name; - } - PIVector cl = C.root().children(); - piForeachC (CDType * c, cl) { - PIString cp = prefix + c->pathString().join("_"); - if (cp.isEmpty()) continue; - if (!eh_map.contains(cp)) continue; - connect(*c, o, eh_map[cp]); - } -} diff --git a/cd_utils/cdutils_c.h b/cd_utils/cdutils_c.h deleted file mode 100644 index a517e8c..0000000 --- a/cd_utils/cdutils_c.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_C_H -#define CDUTILS_C_H - -#include "cdutils_interface.h" -#include "cd_utils_export.h" - - -namespace CDUtils { - - -class CD_UTILS_EXPORT CInterface: public Interface -{ - PIOBJECT_SUBCLASS(CInterface, Interface) -public: - CInterface(); - - void sendCommand(const CDType & c); - void connect(const CDType & c, PIObject * o, Handler eh); - void autoConnect(PIObject * o, const PIString & prefix = PIStringAscii("c_")); - -}; - -} - -extern CD_UTILS_EXPORT CDUtils::CInterface C; - -#endif // CDUTILS_C_H diff --git a/cd_utils/cdutils_core.cpp b/cd_utils/cdutils_core.cpp deleted file mode 100644 index c03c327..0000000 --- a/cd_utils/cdutils_core.cpp +++ /dev/null @@ -1,606 +0,0 @@ -#include "cdutils_core.h" -#include "cdutils_parser.h" -#include "piconfig.h" -#include "piiobytearray.h" -#include "piiostring.h" -#include "pifile.h" - -using namespace CDUtils; - -const char CDCore::app_config[] = - "include = cd_ip.conf\n\ - port_rec = 2\n\ - port_send = 1\n\ - [connection]\n\ - device.cd = peer://cd_app:cd_pult #s\n\ - []\n\ - connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\ - "; - -const char CDCore::pult_config[] = - "include = cd_ip.conf\n\ - port_rec = 1\n\ - port_send = 2\n\ - [connection]\n\ - device.cd = peer://cd_pult:cd_app #s\n\ - []\n\ - connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\ - "; - - -int __Core_Initializer__::count_(0); -CDCore * __Core_Initializer__::__instance__(0); -const uchar header_direct = 0x80; -const uchar header_transfer = 0x81; - - -__Core_Initializer__::__Core_Initializer__() { - count_++; - if (count_ > 1) return; - __instance__ = new CDCore(); -} - - -__Core_Initializer__::~__Core_Initializer__() { - count_--; - if (count_ < 0) { - count_ = 0; - return; - } - if (count_ > 0) return; - if (__instance__) { - delete __instance__; - __instance__ = 0; - } -} - - - - -CDCore::CDCore() { - setName("CDCore"); - x_timer.setName("__S__.CDCore.x_timer"); - datatr.setPacketSize(960); - CONNECTU(&connection, dataReceivedEvent, this, dataReceived); - CONNECTU(PICout::Notifier::object(), finished, this, piCoutFinished); - /*PIString s(app_config); - connection.configureFromString(&s); - connection.start();*/ - need_rebuild_x = x_pult_side = false; - k_.cd_type_ = CDType::cdK; - x_.cd_type_ = CDType::cdX; - c_.cd_type_ = CDType::cdC; - m_.cd_type_ = CDType::cdM; - initRoot(&k_); - initRoot(&x_); - initRoot(&c_); - initRoot(&m_); - - CONNECTU(&sendt, started, this, sendThread) - CONNECTU(&datatr, sendRequest, this, dtSendRequest) - CONNECTU(&datatr, receiveFinished, this, dtReceiveFinished) - CONNECTU(&x_timer, tickEvent, this, xTimerTick) - - /*k_[1] = KType(1, "123", "120+3", "comment"); - k_[2] = KType(2, "1", "2", "comm"); - k_[4] = KType(4, "-0.6", "-6/10", "mment"); - k_.section(10)[5] = KType(5, "8", "2*2*2", "88"); - k_.section(10).section(50)[100] = KType(100, "8", "2*2*2", "88"); - k_.section(11)[3] = KType(3, "1", "1", "88"); - k_.section(11)[4] = KType(4, "0", "0", "88"); - k_.section(11)[6] = KType(6, "0", "0", "88");*/ - //piCout << s; -} - - -CDCore::~CDCore() { - x_timer.stop(true); - datatr.stop(); - sendt.stop(); - sendt.waitForFinish(10); - connection.stop(); -} - - -void CDCore::cd_write(CDSection * cd, PIIODevice * d) { - cd->write(d, PIString()); -} - - -void CDCore::cd_read(CDSection * cd, PIIODevice * d) { - PIConfig conf(d, PIIODevice::ReadOnly); - cd->read(&(conf.rootEntry())); - if (cd->cd_type_ == CDType::cdX) - x_selected = cd->collectX(); - initRoot(cd); - raiseChangedGlobal(cd->cd_type_); - /*PIVector ds = connection.allDevices(); - piForeach(PIIODevice * d, ds) { - if (d) - piCoutObj << d->constructFullPath() << d->isOpened(); - }*/ -} - - -void CDCore::cd_parse(CDSection * cd, PIIODevice * d) { - *cd = CDParser::parse(d, cd->cd_type_); - initRoot(cd); - raiseChangedGlobal(cd->cd_type_); -} - - -void CDCore::cd_update(CDSection * cd, PIIODevice * d, UpdateModeFlags mode) { - CDSection ucd = *cd; - cd_parse(cd, d); - /*bool kn = true; - if (!ucd.isEmpty()) - if (!ucd.isSameStructure(k_)) { - piCout << "ask for save names"; - K_KeepNamesRequest(&kn); - }*/ - ucd.update(*cd, mode); - //piCout << k_.count() << ucd.count(); - *cd = ucd; - initRoot(cd); - raiseChangedGlobal(cd->cd_type_); -} - - -void CDCore::cd_calculate(CDSection * cd) { - cd->calculate(); - raiseChangedGlobal(cd->cd_type_); -} - - -void CDCore::cd_send(CDSection * cd, CDPacketType pt, bool direct) { - if (!cd) return; - PIByteArray ba, sba; - PIIOByteArray iob(&ba, PIIODevice::ReadWrite); - cd_write(cd, &iob); - //piCoutObj << PIString(ba); - sba = makeHeader(pt, 0); - sba << ba; - if (direct) - sendDirect(sba); - else - sendThreaded(sba); -} - - -void CDCore::send(CDType::cdT cdt) { - CDPacketType pt = CD_Ping; - switch (cdt) { - case CDType::cdK: pt = CD_KSend; break; - case CDType::cdX: pt = CD_XSend; break; - case CDType::cdC: pt = CD_CSend; break; - case CDType::cdM: pt = CD_MSend; break; - default: break; - } - piCoutObj << "send" << typeLetter(cdt); - cd_send(root(cdt), pt); -} - - -void CDCore::request(CDType::cdT cdt) { - CDPacketType pt = CD_Ping; - switch (cdt) { - case CDType::cdK: pt = CD_KQuery; break; - case CDType::cdX: pt = CD_XQuery; break; - case CDType::cdC: pt = CD_CQuery; break; - case CDType::cdM: pt = CD_MQuery; break; - default: break; - } - piCoutObj << "request" << typeLetter(cdt); - PIByteArray sba = makeHeader(pt, 0); - sendThreaded(sba); -} - - -void CDCore::initApp() { - init(appConfig(), false); -} - - -void CDCore::initPult() { - init(pultConfig(), true); -} - - -void CDCore::init(const PIString & configuration, bool pult) { - PIString c = configuration; - //piCoutObj << "init" << c; - connection.stop(); - connection.removeAllDevices(); - connection.configureFromString(&c); - connection.start(); - x_pult_side = pult; -} - - -void CDCore::stop() { - x_timer.stop(); - x_timer.waitForFinish(1000); - connection.stop(); -} - - -void CDCore::release() { - stop(); - connection.removeAllDevices(); -} - - -void CDCore::startX(double freq) { - //piCout << "start x" << x_timer.isRunning() << freq; - if (!x_timer.isRunning()) - x_timer.start(1000. / piMaxd(freq, 0.01)); -} - - -void CDCore::stopX() { - x_timer.stop(); - x_timer.waitForFinish(1000); -} - - -void CDCore::sendCommand(const CDType & c) { - //piCoutObj << "C_sendCommand" << c; - PIByteArray sba = makeHeader(CD_Command, 0); - sba << c.path(); - sendDirect(sba); -} - - -void CDCore::registerCHandler(const CDType & c, PIObject * o, Handler h) { - PIString sp = pathToString(c.path()); - if (sp.isEmpty() || !h) return; - //piCout << "register" << sp; - c_handlers[sp] = OHPair(o, h); -} - - -void CDCore::sendMessage(const CDType & m, MessageType mt, const PIString & msg) { - if (msg.isEmpty() || (m.cd_type() != CDType::cdM)) return; - PIByteArray sba = makeHeader(CD_Message, 0); - sba << m.path() << int(mt) << msg; - sendDirect(sba); -} - - -CDSection * CDCore::root(CDType::cdT cdt) { - switch (cdt) { - case CDType::cdK: return &k_; break; - case CDType::cdX: return &x_; break; - case CDType::cdC: return &c_; break; - case CDType::cdM: return &m_; break; - default: break; - } - return 0; -} - - -PIString CDCore::typeLetter(CDType::cdT cdt) { - switch (cdt) { - case CDType::cdK: return PIStringAscii("k"); break; - case CDType::cdX: return PIStringAscii("x"); break; - case CDType::cdC: return PIStringAscii("c"); break; - case CDType::cdM: return PIStringAscii("m"); break; - default: break; - } - return PIString(); -} - - -CDCore * CDCore::instance() { - /*static CDCore * ret = new CDCore(); - return ret;*/ - return __Core_Initializer__::__instance__; -} - - -bool CDCore::destroy() { - if (!__Core_Initializer__::__instance__) return false; -// piCout << "delete Core ..."; - delete __Core_Initializer__::__instance__; -// piCout << "delete Core ok"; - __Core_Initializer__::__instance__ = 0; - __Core_Initializer__::count_ = 0; - return true; -} - - -void CDUtils::CDCore::K_DirectChange(PIDeque path, PIString value) { -// piCoutObj << "K_DirectChange"; - PacketKDirectChange p; - p.path = path; - p.value = value; - PIByteArray sba = makeHeader(CD_KDirectChange, 0); - sba << p; - sendDirect(sba); -} - - -void CDCore::sendThread() { - if (send_data.size_s() < 4) return; - PacketHeader h; - memcpy(&h, send_data.data(), sizeof(h)); - bool ok = datatr.send(send_data); - switch (h.type) { - case CD_KSend: - if (ok) K_Sended(); - else K_SendFail(); - break; - case CD_KQuery: - if (!ok) K_ReceiveFail(); - break; - case CD_XSend: - if (ok) X_Sended(); - else X_SendFail(); - break; - case CD_XQuery: - if (!ok) X_ReceiveFail(); - break; - case CD_CSend: - if (ok) C_Sended(); - else C_SendFail(); - break; - case CD_CQuery: - if (!ok) C_ReceiveFail(); - break; - case CD_MSend: - if (ok) M_Sended(); - else M_SendFail(); - break; - case CD_MQuery: - if (!ok) M_ReceiveFail(); - break; - default: break; - } -} - - -void CDCore::xTimerTick() { - //piCout << "x tick" << x_pult_side; - PIByteArray ba; - x_mutex.lock(); - if (x_pult_side) { - ba = makeHeader(CD_XRequest, 0); - if (need_rebuild_x) { - x_selected = x_.collectX(); - //piCout << "collectX" << x_selected.size(); - need_rebuild_x = false; - } - ba << x_selected; - //piCout << "x pult send" << x_selected.size(); - } else { - ba = makeHeader(CD_XValues, 0); - ba << x_selected; - piForeachC (PIDeque & p, x_selected) { - x_[p].writeX(ba); - } - //piCout << "x app" << x_selected.size(); - } - x_mutex.unlock(); - sendDirect(ba); -} - - -void CDCore::piCoutFinished(int id, PIString * buffer) { - if (!buffer || !(id == 1)) return; - PIString sp = buffer->takeRange("[", "]"); - PIDeque p = CDCore::stringToPath(sp); - sendMessage(m_[p], Log, *buffer); - delete buffer; -} - - -void CDCore::initRoot(CDSection * r) { - r->name = "__root__"; - r->alias = "root"; - r->makePath(); - r->calculate(); -} - - -PIByteArray CDCore::makeHeader(CDPacketType type, int session_id) const { - PacketHeader h; - h.type = type; - h.session_id = session_id; - PIByteArray ret; ret << h; - return ret; -} - - -void CDCore::sendDirect(PIByteArray & ba) { - ba.push_front(header_direct); - connection.writeByName("cd", ba); -} - - -void CDCore::sendThreaded(PIByteArray & ba) { - if (sendt.isRunning()) { - piCoutObj << "Send in process, abort"; - return; - } - send_data = ba; - sendt.startOnce(); -} - - -void CDCore::procReceivedPacket(PIByteArray & ba) { - PacketHeader h; - ba >> h; - switch(h.type) { - case CD_Ping: - //piCoutObj << "ping"; - break; - case CD_KQuery: - send(CDType::cdK); - break; - case CD_KSend: { - PIByteArray k; - ba >> k; - k << uchar(0); - PIString s = PIString::fromUTF8((const char *)k.data()); - PIIOString ios(&s); - cd_read(&k_, &ios); - K_Received(); - piCoutObj << "K received"; - } break; - case CD_KDirectChange: { - PacketKDirectChange p; - ba >> p; - k_[p.path].setValue(p.value); - } break; - case CD_XQuery: - send(CDType::cdX); - break; - case CD_XSend: { - PIByteArray x; - ba >> x; - x << uchar(0); - PIString s = PIString::fromUTF8((const char *)x.data()); - PIIOString ios(&s); - cd_read(&x_, &ios); - x_selected = x_.collectX(); - X_Received(); - piCoutObj << "X received"; - } break; - case CD_XRequest: { - if (x_pult_side) break; - //break; - x_mutex.lock(); - x_selected.clear(); - ba >> x_selected; - //piCout << "X req" << x_selected.size(); - x_.setSelectedX(false); - piForeachC (PIDeque & p, x_selected) { - x_[p].x_enabled = true; - } - x_mutex.unlock(); - } break; - case CD_XValues: { - if (!x_pult_side) break; - PIVector > x_vals; - ba >> x_vals; - x_mutex.lock(); - piForeachC (PIDeque & p, x_vals) { - x_[p].readX(ba); - } - x_mutex.unlock(); - X_ReceivedX(x_vals); - } break; - case CD_CQuery: - send(CDType::cdC); - break; - case CD_CSend: { - piCoutObj << "C received"; - PIByteArray c; - ba >> c; - c << uchar(0); - PIString s = PIString::fromUTF8((const char *)c.data()); - PIIOString ios(&s); - cd_read(&c_, &ios); - C_Received(); - } break; - case CD_Command: { - piCoutObj << "C command"; - PIDeque p; - ba >> p; - if (p.isEmpty()) return; - PIString sp = pathToString(p); - OHPair h = c_handlers.value(sp, OHPair(0, 0)); - //piCoutObj << "found" << sp << h.first; - if (h.first && h.second) h.second(h.first); - } break; - case CD_MQuery: - send(CDType::cdM); - break; - case CD_MSend: { - piCoutObj << "M received"; - PIByteArray c; - ba >> c; - c << uchar(0); - PIString s = PIString::fromUTF8((const char *)c.data()); - PIIOString ios(&s); - cd_read(&m_, &ios); - M_Received(); - } break; - case CD_Message: { - PIDeque p; - ba >> p; - piCoutObj << "M message" << p; - if (p.isEmpty()) return; - int t = 0; - PIString msg; - ba >> t >> msg; - //piCoutObj << "found" << sp << h.first; - //piCoutObj << "M message invoke"; - M_Message(p, t, msg); - } break; - default: break; - } -} - - -void CDCore::raiseChangedGlobal(CDType::cdT cdt) { - switch (cdt) { - case CDType::cdK: K_ChangedGlobal(); break; - case CDType::cdX: X_ChangedGlobal(); break; - case CDType::cdC: C_ChangedGlobal(); break; - case CDType::cdM: M_ChangedGlobal(); break; - default: break; - } -} - - -PIString CDCore::pathToString(const PIDeque & p) { - PIString ret; - for (int i = 0; i < p.size_s(); ++i) { - if (!ret.isEmpty()) ret += "."; - ret << p[i]; - } - return ret; -} - - -PIDeque CDCore::stringToPath(const PIString & p) { - PIDeque ret; - PIStringList sl = p.split("."); - piForeachC (PIString & s, sl) - ret << s.toInt(); - return ret; -} - - -void CDUtils::CDCore::dataReceived(const PIString & from, const PIByteArray & data) { - //piCoutObj << "dataReceived" << from << data.size(); - PIIODevice * d = connection.deviceByName("cd"); - if (d && d == connection.deviceByFullPath(from)) { - if (data.size() >= sizeof(4)) { - PIByteArray ba = data; - uchar header = ba.take_front(); - if (header == header_transfer) { - datatr.received(ba); - } - if (header == header_direct) { - procReceivedPacket(ba); - } - } - } -} - - -void CDCore::dtSendRequest(PIByteArray & data) { - data.push_front(header_transfer); - connection.writeByName("cd", data); - //piCoutObj << "send" << data.size() << ret; -} - - -void CDCore::dtReceiveFinished(bool ok) { - if (!ok) return; - PIByteArray ba = datatr.data(); - procReceivedPacket(ba); -} - diff --git a/cd_utils/cdutils_core.h b/cd_utils/cdutils_core.h deleted file mode 100644 index a0d4e79..0000000 --- a/cd_utils/cdutils_core.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_CORE_H -#define CDUTILS_CORE_H - -#include "cdutils_types.h" -#include "cdutils_protocol.h" -#include "piconnection.h" -#include "pidatatransfer.h" -#include "cd_utils_export.h" - - -namespace CDUtils { - -class CDCore; - - -class CD_UTILS_EXPORT __Core_Initializer__ { -public: - __Core_Initializer__(); - ~__Core_Initializer__(); - static int count_; - static CDCore * __instance__; -}; - - -class CD_UTILS_EXPORT CDCore: public PIObject -{ - PIOBJECT(CDUtils::CDCore) - friend class __Core_Initializer__; - friend class CDSection; - friend class Interface; - friend class XInterface; -public: - static CDCore * instance(); - static bool destroy(); - - EVENT(K_Sended) - EVENT(K_SendFail) - EVENT(K_Received) - EVENT(K_ReceiveFail) - EVENT(K_ChangedGlobal) - EVENT_HANDLER2(void, K_DirectChange, PIDeque, path, PIString, value); - - EVENT(X_Sended) - EVENT(X_SendFail) - EVENT(X_Received) - EVENT(X_ReceiveFail) - EVENT(X_ChangedGlobal) - EVENT1(X_ReceivedX, PIVector >, pathes) - - EVENT(C_Sended) - EVENT(C_SendFail) - EVENT(C_Received) - EVENT(C_ReceiveFail) - EVENT(C_ChangedGlobal) - - EVENT(M_Sended) - EVENT(M_SendFail) - EVENT(M_Received) - EVENT(M_ReceiveFail) - EVENT(M_ChangedGlobal) - EVENT3(M_Message, PIDeque, path, int, type, PIString, msg) - - void cd_write (CDSection * cd, PIIODevice * d); - void cd_read (CDSection * cd, PIIODevice * d); - void cd_parse (CDSection * cd, PIIODevice * d); - void cd_update (CDSection * cd, PIIODevice * d, UpdateModeFlags mode); - void cd_calculate(CDSection * cd); - void cd_send (CDSection * cd, CDPacketType pt, bool direct = false); - void send(CDType::cdT cdt); - void request(CDType::cdT cdt); - void initApp(); - void initPult(); - void init(const PIString & configuration, bool pult = false); - void stop(); - void release(); - void startX(double freq = 20.); - void stopX(); - void sendCommand(const CDType & c); - void registerCHandler(const CDType & c, PIObject * o, Handler h); - bool inProgress() {return sendt.isRunning();} - void sendMessage(const CDType & m, MessageType mt, const PIString & msg); - - CDSection * root(CDType::cdT cdt); - PIString typeLetter(CDType::cdT cdt); - static PIString pathToString(const PIDeque & p); - static PIDeque stringToPath(const PIString & p); - - static PIString pultConfig() {return PIString(pult_config);} - static PIString appConfig() {return PIString(app_config);} - -private: - CDCore(); - ~CDCore(); - EVENT_HANDLER2(void, dataReceived, const PIString &, from, const PIByteArray &, data); - EVENT_HANDLER1(void, dtSendRequest, PIByteArray &, data); - EVENT_HANDLER1(void, dtReceiveFinished, bool, ok); - EVENT_HANDLER(void, sendThread); - EVENT_HANDLER(void, xTimerTick); - EVENT_HANDLER2(void, piCoutFinished, int, id, PIString*, buffer); - void initRoot(CDSection * r); - PIByteArray makeHeader(CDPacketType type, int session_id = 0) const; - void sendDirect(PIByteArray & ba); - void sendThreaded(PIByteArray & ba); - void procReceivedPacket(PIByteArray & ba); - void raiseChangedGlobal(CDType::cdT cdt); - - typedef PIPair OHPair; - - static const char app_config[], pult_config[]; - PIConnection connection; - PIDataTransfer datatr; - PIByteArray send_data; - PIThread sendt; - PITimer x_timer; - CDSection k_, x_, c_, m_; - PIMutex x_mutex; - PIVector > x_selected; - PIMap c_handlers; - bool need_rebuild_x, x_pult_side; - -}; - - -static __Core_Initializer__ __Core_initializer__; - -} - -#endif // CDUTILS_CORE_H diff --git a/cd_utils/cdutils_interface.cpp b/cd_utils/cdutils_interface.cpp deleted file mode 100644 index a37d818..0000000 --- a/cd_utils/cdutils_interface.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "cdutils_interface.h" -#include "cdutils_core.h" -#include "piconfig.h" -#include "pifile.h" - -using namespace CDUtils; - - -Interface::Interface(CDType::cdT type_) { - core = CDCore::instance(); - s = core->root(type_); - type = type_; - //piCoutObj << (void*)this << core; - file_ = core->typeLetter(type_) + PIStringAscii(".dat"); - file_size = 0; - switch (type) { - case CDType::cdK: - CONNECTU(core, K_Sended, this, sended); - CONNECTU(core, K_SendFail, this, sendFailed); - CONNECTU(core, K_Received, this, received); - CONNECTU(core, K_ReceiveFail, this, receiveFailed); - CONNECTU(core, K_ChangedGlobal, this, changedGlobal); - break; - case CDType::cdX: - CONNECTU(core, X_Sended, this, sended); - CONNECTU(core, X_SendFail, this, sendFailed); - CONNECTU(core, X_Received, this, received); - CONNECTU(core, X_ReceiveFail, this, receiveFailed); - CONNECTU(core, X_ChangedGlobal, this, changedGlobal); - break; - case CDType::cdC: - CONNECTU(core, C_Sended, this, sended); - CONNECTU(core, C_SendFail, this, sendFailed); - CONNECTU(core, C_Received, this, received); - CONNECTU(core, C_ReceiveFail, this, receiveFailed); - CONNECTU(core, C_ChangedGlobal, this, changedGlobal); - break; - case CDType::cdM: - CONNECTU(core, M_Sended, this, sended); - CONNECTU(core, M_SendFail, this, sendFailed); - CONNECTU(core, M_Received, this, received); - CONNECTU(core, M_ReceiveFail, this, receiveFailed); - CONNECTU(core, M_ChangedGlobal, this, changedGlobal); - break; - default: break; - } -} - - -bool Interface::test(int v) { - return s->test(v); -} - - -CDType & Interface::operator [](const PIString & name_) { - return (*s)[name_]; -} - - -const CDType Interface::operator [](const PIString & name_) const { - return (*s)[name_]; -} - - -CDType & Interface::operator [](const PIDeque & path_) { - return (*s)[path_]; -} - - -const CDType Interface::operator [](const PIDeque & path_) const { - return (*s)[path_]; -} - - -CDType & Interface::operator [](int v) { - //piCout << (void*)this << "[]" << core; - return (*s)[v]; -} - - -const CDType Interface::operator [](int v) const { - //piCout << (void*)this << "[]" << core; - return (*s)[v]; -} - - -CDSection & Interface::section(int v) { -// CDSection & ret = s->section(v); -// piCout << "[get section]" << v << ret.name; - return s->section(v); -} - - -const CDSection Interface::section(int v) const { - return s->section(v); -} - - -CDSection & Interface::section(const PIDeque &path) { - PIDeque spath = path; - CDSection * rs = s; - while (!spath.isEmpty()) { - rs = &(rs->section(spath.take_front())); - } - return *rs; -} - - -CDSection & Interface::root() { - return *s; -} - - -const CDSection & Interface::root() const { - return *s; -} - - -int Interface::count(bool recursive) const { - return s->count(recursive); -} - - -bool Interface::exists(PIDeque path) const { - return s->exists(path); -} - - -void Interface::setFileName(const PIString & _file) { - file_ = _file; -} - - -bool Interface::configure(const PIString & config) { - PIConfig conf(config, PIIODevice::ReadOnly); - PIConfig::Entry & e(conf.getValue(core->typeLetter(s->cd_type_))); - bool ret = false; - setFileName(e.getValue("file", file(), &ret).toString()); - return ret; -} - - -void Interface::reinitConnection(const PIString & configuration) { - core->init(configuration); -} - - -void Interface::releaseConnection() { - core->release(); -} - - -void Interface::write(PIIODevice * d) { - core->cd_write(s, d); -} - - -void Interface::read(PIIODevice * d) { - core->cd_read(s, d); -} - - -void Interface::parse(PIIODevice * d) { - core->cd_parse(s, d); -} - - -void Interface::update(PIIODevice * d, UpdateModeFlags mode) { - core->cd_update(s, d, mode); -} - - -void Interface::calculate() { - core->cd_calculate(s); -} - - -PIString Interface::appConfig() { - return core->appConfig(); -} - - -PIString Interface::pultConfig() { - return core->pultConfig(); -} - - -void Interface::readFile() { - if (file_.isEmpty()) return; - PIFile f(file_, PIIODevice::ReadOnly); - read(&f); - file_size = f.size(); -} - - -void Interface::writeFile() { - if (file_.isEmpty()) return; - PIFile f(file_, PIIODevice::ReadWrite); - f.clear(); - write(&f); - file_size = f.size(); -} - - -bool Interface::inProgress() { - return core->inProgress(); -} - - -void Interface::send() { - core->send(type); -} - - -void Interface::request() { - core->request(type); -} diff --git a/cd_utils/cdutils_interface.h b/cd_utils/cdutils_interface.h deleted file mode 100644 index 635ed1d..0000000 --- a/cd_utils/cdutils_interface.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_INTERFACE_H -#define CDUTILS_INTERFACE_H - -#include "cdutils_types.h" -#include "piobject.h" -#include "cd_utils_export.h" - - -namespace CDUtils { - -class CDCore; - - -class CD_UTILS_EXPORT Interface: public PIObject -{ - PIOBJECT(CDUtils::Interface) -public: - Interface(CDType::cdT type_); - - bool test(int v); - CDType & operator [](int v); - const CDType operator [](int v) const; - CDType & operator [](const PIString & name_); - const CDType operator [](const PIString & name_) const; - CDType & operator [](const PIDeque & path_); - const CDType operator [](const PIDeque & path_) const; - CDSection & section(int v); - const CDSection section(int v) const; - CDSection & section(const PIDeque & path); - CDSection & root(); - const CDSection & root() const; - - int count(bool recursive = true) const; - const PIString file() const {return file_;} - int fileSize() const {return file_size;} - CDType::cdT cdType() const {return type;} - bool exists(PIDeque path) const; - - void setFileName(const PIString & _file); - bool configure(const PIString & config); - void reinitConnection(const PIString & configuration); - void releaseConnection(); - void write(PIIODevice * d); - void read(PIIODevice * d); - void parse(PIIODevice * d); - void update(PIIODevice * d, UpdateModeFlags mode = SaveByName); - void calculate(); - - PIString appConfig(); - PIString pultConfig(); - - void readFile(); - void writeFile(); - bool inProgress(); - - EVENT(sended) - EVENT(sendFailed) - EVENT(received) - EVENT(receiveFailed) - EVENT(changedGlobal) - EVENT_HANDLER(void, send); - EVENT_HANDLER(void, request); - -protected: - CDCore * core; - CDSection * s; - CDType::cdT type; - PIString file_; - int file_size; - -}; - - -} - - -#endif // CDUTILS_INTERFACE_H diff --git a/cd_utils/cdutils_k.cpp b/cd_utils/cdutils_k.cpp deleted file mode 100644 index 6ee850a..0000000 --- a/cd_utils/cdutils_k.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "cdutils_k.h" -#include "cdutils_core.h" - -using namespace CDUtils; - -KInterface K; - - -KInterface::KInterface(): Interface(CDType::cdK) { -} - - -void KInterface::directChange(const CDType & k) { - core->K_DirectChange(k.path(), k.value()); -} - - -void KInterface::directChange(const CDType & k, double v) { - core->K_DirectChange(k.path(), PIString::fromNumber(v)); -} diff --git a/cd_utils/cdutils_k.h b/cd_utils/cdutils_k.h deleted file mode 100644 index a3190f1..0000000 --- a/cd_utils/cdutils_k.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_K_H -#define CDUTILS_K_H - -#include "cdutils_interface.h" -#include "cd_utils_export.h" - - -namespace CDUtils { - - -class CD_UTILS_EXPORT KInterface: public Interface -{ - PIOBJECT_SUBCLASS(KInterface, Interface) -public: - KInterface(); - - EVENT1(keepNamesRequest, bool*, kn) - - void directChange(const CDType & k); - void directChange(const CDType & k, double v); - -}; - -} - -extern CD_UTILS_EXPORT CDUtils::KInterface K; - -#endif // CDUTILS_K_H diff --git a/cd_utils/cdutils_m.cpp b/cd_utils/cdutils_m.cpp deleted file mode 100644 index cd326cd..0000000 --- a/cd_utils/cdutils_m.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "cdutils_m.h" -#include "cdutils_core.h" - -using namespace CDUtils; - -MInterface M; - - -MInterface::MInterface(): Interface(CDType::cdM) { - CONNECTU(core, M_Message, this, messageReceived); -} - - -void MInterface::messageBox(const CDType & m, const PIString & msg) { - core->sendMessage(m, MessageBox, msg); -} - - -PICout MInterface::createPICout(const CDType & m) const { - PIString * buff = new PIString("[" + CDCore::pathToString(m.path()) + "]"); - return PICout(buff, 1); -} diff --git a/cd_utils/cdutils_m.h b/cd_utils/cdutils_m.h deleted file mode 100644 index 2585b66..0000000 --- a/cd_utils/cdutils_m.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_M_H -#define CDUTILS_M_H - -#include "cdutils_interface.h" -#include "cd_utils_export.h" - - -namespace CDUtils { - - -class CD_UTILS_EXPORT MInterface: public Interface -{ - PIOBJECT_SUBCLASS(MInterface, Interface) -public: - MInterface(); - - PICout operator [](int v) {return createPICout((*s)[v]);} - PICout operator [](int v) const {return createPICout((*s)[v]);} - PICout operator [](const PIString & name_) {return createPICout((*s)[name_]);} - PICout operator [](const PIString & name_) const {return createPICout((*s)[name_]);} - PICout operator [](const PIDeque & path_) {return createPICout((*s)[path_]);} - PICout operator [](const PIDeque & path_) const {return createPICout((*s)[path_]);} - - void messageBox(const CDType & m, const PIString & msg); - - EVENT3(messageReceived, PIDeque, path, int, type, PIString, msg) - -private: - PICout createPICout(const CDType & m) const; - -}; - -} - -extern CD_UTILS_EXPORT CDUtils::MInterface M; - -#endif // CDUTILS_M_H diff --git a/cd_utils/cdutils_parser.cpp b/cd_utils/cdutils_parser.cpp deleted file mode 100644 index 50e0600..0000000 --- a/cd_utils/cdutils_parser.cpp +++ /dev/null @@ -1,196 +0,0 @@ -#include "cdutils_parser.h" -#include "cdutils_types.h" -#include "piiostring.h" -#include "piiobytearray.h" -#include "pifile.h" - -using namespace CDUtils; - -enum Phase { - eName = 1, - eBracketOpen, - eBracketClose, - eMemberName, - eMemberEqual, - eMemberValue, - eMemberComma, - eComment, - eMultiComment -}; - - -void removeComment(PIString & line, PIString * type, PIString * comment) { - int ci = line.find("//"); - if (ci >= 0) { - if (comment) *comment = line.right(line.size_s() - ci - 2); - line.cutRight(line.size_s() - ci).trim(); - if (type && comment && !line.isEmpty()) { - *type = comment->takeLeft(1); - comment->trim(); - } - } -} - - -void parseEnumLine(PIString & line, int * value, PIString * type, PIString * comment) { - removeComment(line, type, comment); - int ci = line.find("="); - if (ci >= 0) { - if (value) *value = line.right(line.size_s() - ci - 1).trim().toInt(); - line.cutRight(line.size_s() - ci).trim(); - } - if (line.trim().endsWith(",")) line.cutRight(1); -} - - -void parseInsert(PIString line, PIString & alias, PIStringList & out) { - out.clear(); - int ci = line.find("="); - if (ci < 0) return; - alias = line.right(line.size_s() - ci - 1).trim(); - line.cutRight(line.size_s() - ci).trim(); - while (line.find("[") > 0) { - int is = line.find("["), ie = line.find("]"); - PIString arr = line.mid(is + 1, ie - is - 1); - out << arr; - line.cutMid(is, ie - is + 1); - } - if (!line.isEmpty()) out.insert(0, line); -} - - -PIVector enumValues(const PIString & e, const PIMap & sections, PIStringList & enames) { - PIVector ret; - enames.clear(); - if (sections.contains(e)) { - ret = sections[e].indexes(); - enames = sections[e].index_names(); - } else { - int v = e.toInt(); - if (v < 2) return ret; - for (int i = 0; i < v; ++i) { - ret << i; - enames << "";//PIString::fromNumber(i); - } - } - return ret; -} - - -CDSection CDParser::parse(PIIODevice * d, int cdsection_type) { - CDType::cdT et = (CDType::cdT)cdsection_type; - if (!d) return CDSection(et); - if (!d->canRead()) return CDSection(et); - //piCout << "[CDSection] parse start"; - CDSection cs(et); - CDType ck; - PIMap sections; - PIMap enum_values; - PIString content, line, alias, type, comment; - PIStringList iarr; - if (PIStringAscii(d->className()) == PIStringAscii("PIFile")) { - PIByteArray c = ((PIFile*)d)->readAll(); - c << uchar(0); - content = PIString::fromUTF8((const char *)c.data()); - } - if (PIStringAscii(d->className()) == PIStringAscii("PIIOString")) content = *(((PIIOString*)d)->string()); - if (PIStringAscii(d->className()) == PIStringAscii("PIIOByteArray")) content = PIString(*(((PIIOByteArray*)d)->byteArray())); - PIIOString ios(&content); - //int phase = 0; - int cind = -1; - while ((cind = content.find("enum", cind)) >= 0) { - ios.seek(cind); - line = ios.readLine().trim(); - type.clear(); - comment.clear(); - removeComment(line, &type, &comment); - if (line.find("{") < 0) { - cind += 4; - continue; - } - line.cutLeft(line.find("enum") + 4).trim(); - line.cutRight(line.size_s() - line.find("{")).trim(); - if (line.isEmpty()) { - cind += 4; - continue; - } - cs = CDSection(et); - cs.name = line; - //piCout << "enum" << cs.name; - int cev = 0; -// cevalues.clear(); - while (!ios.isEnd()) { - line = ios.readLine().trim(); - comment.clear(); - removeComment(line, &type, &comment); - if (line.find("}") >= 0) break; - if (line.isEmpty()) { - if (comment.find("=") >= 0) { - parseInsert(comment, alias, iarr); - if (!iarr.isEmpty()) { -// piCout << "#" << enum_values; - if (!enum_values.contains(alias)) { - piCout << "Parse error: can`t find section alias \"" << alias << "\"!"; - return CDSection(et); - } - if (!sections.contains(iarr.front())) { - piCout << "Parse error: can`t find section \"" << iarr.front() << "\"!"; - return CDSection(et); - } - //piCout << "insert" << alias << iarr; - int aval = enum_values.value(alias); - CDSection is = sections.value(iarr.take_front()), ts; - int ibpos = is.name.size_s(); - piForeachRC (PIString & a, iarr) { - PIStringList enames; - PIVector evals = enumValues(a, sections, enames); - //piCout << a << evals; - for (int i = 0; i < evals.size_s(); ++i) { - ts.section(evals[i]) = is; - ts.section(evals[i]).alias = enames[i]; - } - ts.name = is.name; - ts.name.insert(ibpos, PIString("[") << a << "]"); - is = ts; - ts = CDSection(et); - } - is.alias = alias; - cs.section(aval) = is; - } - } - } else { - parseEnumLine(line, &cev, &type, &comment); - //piCout << line << "=" << cev << "//" << type << comment; - ck = CDType(cev, line, type, "", "", comment, et); - if (type == "e") { - if (comment.startsWith("${")) { - comment.cutLeft(1); - PIString en = comment.inBrackets('{', '}'); - comment.cutLeft(en.size_s() + 2).trim(); - ck.setEnumValues(sections.value(en).enumValues()); - ck.setComment(comment); - //piCout << "enum" << en << ck.enumValues(); - } - } - cs[cev] = ck; - //cevalues[line] = cev; - enum_values[line] = cev; - ++cev; - } - } - //piCout << cs.name << cs.k; - sections[cs.name] = cs; -// piCout << "#" << cevalues; -// enum_values << cevalues; - cind += 4; - } -// piCout << "[CDSection] parse end"; - switch (et) { - case CDType::cdK: return sections.value("KDescription"); - case CDType::cdX: return sections.value("XDescription"); - case CDType::cdC: return sections.value("CDescription"); - case CDType::cdM: return sections.value("MDescription"); - default: return CDSection(et); - } - return CDSection(et); -} diff --git a/cd_utils/cdutils_parser.h b/cd_utils/cdutils_parser.h deleted file mode 100644 index 4b23fa3..0000000 --- a/cd_utils/cdutils_parser.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_PARSER_H -#define CDUTILS_PARSER_H - -#include "cd_utils_export.h" - -class PIIODevice; - -namespace CDUtils { - -class CDSection; - -namespace CDParser { - -CD_UTILS_EXPORT CDSection parse(PIIODevice * d, int cdsection_type); - -} - -} - -#endif // CDUTILS_PARSER_H diff --git a/cd_utils/cdutils_protocol.h b/cd_utils/cdutils_protocol.h deleted file mode 100644 index c9b541c..0000000 --- a/cd_utils/cdutils_protocol.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_PROTOCOL_H -#define CDUTILS_PROTOCOL_H - -#include "pistring.h" -#include "cd_utils_export.h" - -namespace CDUtils { - - enum CDPacketType { - CD_Ping, - CD_Pong, - - CD_KQuery, - CD_KSend, - CD_KDirectChange, - - CD_XQuery, - CD_XSend, - CD_XRequest, - CD_XValues, - - CD_CQuery, - CD_CSend, - CD_Command, - - CD_MQuery, - CD_MSend, - CD_Message, - }; - -# pragma pack(push,1) - - struct CD_UTILS_EXPORT PacketHeader { - int type; // CDPacketType - int session_id; - }; - - struct CD_UTILS_EXPORT PacketKDirectChange { - PIDeque path; - PIString value; - }; - -# pragma pack(pop) - - -inline PIByteArray & operator <<(PIByteArray & s, const PacketHeader & v) {s << v.type << v.session_id; return s;} -inline PIByteArray & operator >>(PIByteArray & s, PacketHeader & v) {s >> v.type >> v.session_id; return s;} - -inline PIByteArray & operator <<(PIByteArray & s, const PacketKDirectChange & v) {s << v.path << v.value; return s;} -inline PIByteArray & operator >>(PIByteArray & s, PacketKDirectChange & v) {s >> v.path >> v.value; return s;} - -} - -#endif // CDUTILS_PROTOCOL_H diff --git a/cd_utils/cdutils_types.cpp b/cd_utils/cdutils_types.cpp deleted file mode 100644 index 2000e1e..0000000 --- a/cd_utils/cdutils_types.cpp +++ /dev/null @@ -1,762 +0,0 @@ -#include "cdutils_types.h" -#include "piconfig.h" -#include "pifile.h" -#include "pievaluator.h" -#include "cdutils_core.h" - -using namespace CDUtils; - -//int cdtype_debug_cnt = 1; - -const int cd_x_history_max_size = 4000; - -CDType::CDType() { - index_ = -1; - value_d = 0.; - value_i = 0; - value_b = calculated = x_enabled = false; - cd_type_ = cdNull; - parent = 0; - avg_size = 1; - mode_ = rmode_ = X_Current; -// debug_cnt = cdtype_debug_cnt; -// cdtype_debug_cnt++; -// piCout << "[CDType]" << "create Null" << debug_cnt; -} - - - - -CDType::CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t) { - index_ = i; - name_ = n.trimmed(); - type_ = t.trimmed(); - value_s = v.trimmed(); - formula_ = f.trimmed(); - comment_ = c.trimmed(); - value_d = v.toDouble(); - value_i = v.toInt(); - value_b = v.toBool(); - cd_type_ = cd_t; - calculated = x_enabled = false; - parent = 0; - avg_size = 1; - mode_ = rmode_ = X_Current; - if (type_ == "e") { - enum_values = parseEnumComment(comment_); -// piCout << enum_values.size() << enum_values; - } -// piCout << type_.size() << type_.toUTF8(); -// piCout << formula_.size() << formula_.toUTF8(); -// piCout << comment_.size() << comment_.toUTF8(); -// debug_cnt = cdtype_debug_cnt; -// cdtype_debug_cnt++; -// piCout << "[CDType] create" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); -} - - -CDType & CDType::operator =(double x) { - value_d = x; - value_i = x; - value_b = x > 0.; - if (mode_ == X_All_Avg) { - avg_h << x; - double val = 0; - if (avg_h.size_s() >= avg_size) { - for (int i = 0; i < avg_h.size_s(); i++) - val += avg_h[i]; - val /= avg_h.size(); - avg_h.clear(); - if (history.size() < cd_x_history_max_size) - history << val; - } - } - return *this; -} - - -PIString CDType::type() const { - if (type_.trimmed().isEmpty()) return "f"; - // piCout << "type =" << type_.trimmed() << ";" << type_ << "#"; - return type_; -} - - -PIString CDType::value() const { - if (type_ == "b") return PIString::fromBool(value_b); - return value_s; -} - - -PIVariant CDType::variantValue() const { - if (type_.isEmpty()) return PIVariant(value()); - switch (type_[0].toAscii()) { - case 'b': return PIVariant(toBool()); break; - case 'n': return PIVariant(toInt()); break; - case 'f': return PIVariant(toDouble()); break; - case 'c': return PIVariant(PIVariantTypes::Color(toInt())); break; - case 'e': { - PIVariantTypes::Enum e = enum_values; - e.selectValue(toInt()); - return PIVariant(e); - break; - } - default: break; - } - return PIVariant(value()); -} - - -void CDType::setValue(const PIString & value_) { - formula_ = value_; - value_d = formula_.toDouble(); - value_i = formula_.toInt(); - value_b = formula_.toBool(); -} - - -void CDType::setVariantValue(const PIVariant & value_) { - setValue(PIString::fromNumber(value_.toDouble())); -} - - -void CDType::setFormula(const PIString & f) { - formula_ = f; - calculated = false; - //PIEvaluator e; - //calculate(&e); -} - - -PIStringList CDType::pathString() const { - PIStringList ret; - CDSection * ps = CDCore::instance()->root(cd_type_); - if (!ps) return ret; - for (int i = 0; i < path_.size_s() - 1; ++i) { - ps = &(ps->section(path_[i])); - if (!ps->alias.isEmpty()) ret << ps->alias; - else ret << PIString::fromNumber(path_[i]); - } - if (!name_.isEmpty()) ret << name_; - else ret << PIString::fromNumber(index_); - return ret; -} - - -void CDType::readX(PIByteArray & ba) { - if (ba.size() < 5) return; - uchar t(0); ba >> t; - rmode_ = (XMode)t; - switch (rmode_) { - case X_Current: - ba >> value_d; - break; - case X_All_Avg: { - PIVector ah; - ba >> ah; - history << ah; - if (!history.isEmpty()) - value_d = history.back(); - } break; - default: break; - } - value_i = value_d; - value_b = value_d > 0.; -} - - -void CDType::writeX(PIByteArray & ba) { - ba << uchar(mode_); - switch (mode_) { - case X_Current: - ba << value_d; - break; - case X_All_Avg: - ba << history; - history.clear(); - break; - default: break; - } -} - - -bool CDType::calculate(PIEvaluator * e, PIVector stack) { - if (stack.contains(this)) { - error_ = "Circular dependencies: "; - piForeachC (CDType * k, stack) - error_ << k->name() << " -> "; - error_ << name(); - //piCout << error_; - return false; - } - stack << this; - if (calculated) return true; - calculated = true; - error_.clear(); - if (!parent) return true; - //piCout << "calc" << name_ << (parent ? parent->alias : "root"); - value_s = formula_.trimmed(); - for (;;) { - int ki = value_s.find("K["); - if (ki < 0) break; - int ke = value_s.find("]", ki + 2); - if (ke < 0) break; - PIString kp = value_s.mid(ki + 2, ke - ki - 2); - //piCout << kp; - CDType & k((*parent)[kp]); - k.calculate(e, stack); - value_s.replace(ki, ke - ki + 1, PIString::fromNumber(k.value_d)); - } - value_d = formula_.toDouble(); - value_i = formula_.toInt(); - value_b = formula_.toBool(); - double ev = 0.; - if (!e->check(value_s) && value_d == 0. && value_i == 0 && !value_b) { - PIString f = formula_.trimmed().toLowerCase(); - if (f != "off" && f != "false" && f != "no" && !value_b) { - error_ = e->error(); - return false; - } - } else - if (e->isCorrect()) - ev = e->evaluate().real(); - //piCout << value_s << value_i << value_d << ev; - //if ((value_d == 0.) || (piAbsd(value_d) < piAbsd(ev))) value_d = ev; - //if ((value_i == 0) || (piAbsd(value_i) < piAbsd(ev))) value_i = int(ev); - if ((value_d == 0.) || (ev != 0.)) value_d = ev; - if ((value_i == 0) || (ev != 0.)) value_i = int(ev); - value_b = value_b || (ev > 0.); - if (value_i != 0) { - if (value_d == 0.) value_d = value_i; - value_b = value_i > 0; - } - if (value_d != 0.) { - if (value_i == 0) value_i = value_d; - value_b = value_d > 0.; - } - if (value_b) { - if (value_d == 0.) value_d = 1.; - if (value_i == 0) value_i = 1; - } - value_s = PIString::fromNumber(value_d); - return true; -} - - -PIVariantTypes::Enum CDType::parseEnumComment(PIString c) { - PIVariantTypes::Enum ret; - if (c.isEmpty()) return ret; - if (type_ == "e") { - PIStringList sl = c.inBrackets('{', '}').split(","); - int cval = 0; - piForeach (PIString & s, sl) { - s.trim(); - if (s.isEmpty()) continue; - if (s[0].isDigit()) { - int ind = s.find("-"); - if (ind > 0) { - cval = s.left(ind).toInt(); - s.cutLeft(ind + 1).trim(); - } - } - ret << PIVariantTypes::Enumerator(cval, s); - ++cval; - } - } - //piCout << c << "=" << ret; - return ret; -} - - -//CDType::CDType(const CDType &cdt) { -// index_ = cdt.index_; -// name_ = cdt.name_; -// type_ = cdt.type_; -// value_s = cdt.value_s; -// formula_ = cdt.formula_; -// comment_ = cdt.comment_; -// value_d = cdt.value_d; -// value_i = cdt.value_i; -// value_b = cdt.value_b; -// cd_type_ = cdt.cd_type_; -// debug_cnt = cdtype_debug_cnt; -// cdtype_debug_cnt++; -// piCout << "[CDType] copy" << debug_cnt << "->" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); -//} - - -//CDType &CDType::operator =(const CDType &cdt) { -// index_ = cdt.index_; -// name_ = cdt.name_; -// type_ = cdt.type_; -// value_s = cdt.value_s; -// formula_ = cdt.formula_; -// comment_ = cdt.comment_; -// value_d = cdt.value_d; -// value_i = cdt.value_i; -// value_b = cdt.value_b; -// cd_type_ = cdt.cd_type_; -// piCout << "[CDType] assign" << debug_cnt << "=" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); -// //debug_cnt = cdt.debug_cnt; -// return *this; -//} - - -//CDType::~CDType() { -// piCout << "[CDType] delete" << debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK); -//} - - - -CDSection::CDSection(CDType::cdT type_) { - cd_type_ = type_; - null.cd_type_ = type_; -} - - -CDSection & CDSection::section(int v) { - CDSection & ret(s[v]); - ret.cd_type_ = cd_type_; - return ret; -} - - -const CDSection CDSection::section(int v) const { - CDSection & ret(s[v]); - ret.cd_type_ = cd_type_; - return s[v]; -} - - -bool CDSection::exists(PIDeque path) const { - if (path.isEmpty()) return false; - if (path.size_s() == 1) return cd.contains(path[0]); - int si = path[0]; - if (!s.contains(si)) return false; - path.remove(0, 1); - return s[si].exists(path); -} - - -int CDSection::count(bool recursive) const { - int ret = cd.size_s(); - if (recursive) { - PIMap::const_iterator i; - for (i = s.constBegin(); i != s.constEnd(); ++i) - ret += i->second.count(recursive); - } - return ret; -} - - -int CDSection::sectionsCount() const { - return s.size(); -} - - -PIStringList CDSection::index_names() const { - PIStringList ret; - auto i = cd.makeIterator(); - while (i.next()) - ret << i.value().name(); - return ret; -} - - -void CDSection::calculate() { - prepareCalculate(); - if (cd_type_ != CDType::cdK) return; - PIEvaluator e; - calculateRecursive(&e); -} - - -CDType & CDSection::getByName(const PIString & name_) { - PIStringList np = name_.split("."); - if (np.isEmpty()) return null; - //piCout << np; - CDSection * cs = this, * ns = 0; - if (np.front().isEmpty()) { - if (np.size_s() < 2) return null; - cs = CDCore::instance()->root(cd_type_); - np.pop_front(); - } - for (int i = 0; i < np.size_s() - 1; ++i) { - if (np[i].isEmpty()) return null; - bool isd = np[i][0].isDigit() || (np[i][0] == '-'); - int dv = 0; - if (isd) dv = np[i].toInt(); - ns = 0; - auto it = cs->s.makeIterator(); - while (it.next()) { - bool f = false; - if (isd) f = (dv == it.key()); - else f = (np[i] == it.value().alias); - //piCout << "s..." << it.key() << it.value().alias << f; - if (f) { - ns = &(it.valueRef()); - break; - } - } - //piCout << ns; - if (!ns) return null; - cs = ns; - } - if (np.back().isEmpty()) return null; - bool isd = np.back()[0].isDigit() || (np.back()[0] == '-'); - int dv = 0; - if (isd) dv = np.back().toInt(); - //piCout << np.back() << isd << dv; - auto it = cs->cd.makeIterator(); - while (it.next()) { - bool f = false; - if (isd) f = (dv == it.key()); - else f = (np.back() == it.value().name()); - //piCout << "k..." << it.key() << it.value().name() << f; - if (f) - return cs->cd[it.key()]; - } - return null; -} - - -CDType & CDSection::getByPath(const PIDeque & path_) { - if (path_.isEmpty()) return null; - CDSection * s = this; - for (int i = 0; i < path_.size_s() - 1; ++i) - s = &(s->section(path_[i])); - if (!s) return null; - return (*s)[path_.back()]; -} - - -void CDSection::write(PIIODevice * d, const PIString & prefix) { - if (!d) return; - if (cd.isEmpty() && s.isEmpty()) return; -// piCout << "[CDSection] write start"; - PIString l; - PIStringList cdtl; - cdtl << "null" << "k" << "x" << "c" << "m"; - if (prefix.isEmpty()) l = "[" + cdtl[cd_type_] + "]"; - else l = "[" + prefix + "." + cdtl[cd_type_] + "]"; - l += "\n"; - d->write(l.toUTF8()); - l = "name = " + name + " \n"; - d->write(l.toUTF8()); - l = "alias = " + alias + " \n"; - d->write(l.toUTF8()); - auto i = cd.makeIterator(); - while (i.next()) { - const CDType & ck(i.value()); - if (ck.cd_type() != cd_type_) continue; - switch (cd_type_) { - case CDType::cdNull: break; - case CDType::cdK: - l.clear(); l << ck.index() << ".f = " << ck.formula() << " #s " << ck.comment() << " \n"; - d->write(l.toUTF8()); - l.clear(); l << ck.index() << ".v = " << ck.value() << " #" << ck.type() << " " << ck.name() << " \n"; - d->write(l.toUTF8()); - if (!ck.enumValues().enum_list.isEmpty()) { - l.clear(); l << ck.index() << ".ev = {"; - //PIVector el = ck.enumValues(); - piForeachC (PIVariantTypes::Enumerator & e, ck.enumValues().enum_list) - l << e.value << " - " << e.name << ", "; - l.cutRight(2); - l << "} \n"; - d->write(l.toUTF8()); - } - break; - case CDType::cdX: - l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n"; - d->write(l.toUTF8()); - l.clear(); l << ck.index() << ".mode = " << ck.xmode() << " #e (0 - cur, 1 - all_avg) " << "\n"; - d->write(l.toUTF8()); - l.clear(); l << ck.index() << ".avg = " << ck.avg() << " #n " << "\n"; - d->write(l.toUTF8()); - l.clear(); l << ck.index() << ".sel = " << (ck.isSelectedX() ? "1" : "0") << " #n " << "\n"; - d->write(l.toUTF8()); - break; - case CDType::cdC: - case CDType::cdM: - l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n"; - d->write(l.toUTF8()); - break; - } - } - if (!s.isEmpty()) { - if (prefix.isEmpty()) l = "s"; - else l = prefix + ".s"; - auto j = s.makeIterator(); - while (j.next()) { - j.valueRef().write(d, l + "." + PIString::fromNumber(j.key())); - } - } - if (prefix.isEmpty()) { - l = "[]\n"; - d->write(l.toUTF8()); - } -// piCout << "[CDSection] write end"; -} - - -void CDSection::read(const void * ep) { -// piCout << "[CDSection] read start"; - PIStringList cdtl; - cdtl << "null" << "k" << "x" << "c" << "m"; - cd.clear(); - s.clear(); - PIConfig::Entry & e(*(PIConfig::Entry*)ep); - name = e.getValue(cdtl[cd_type_] + ".name").value(); - alias = e.getValue(cdtl[cd_type_] + ".alias").value(); - PIConfig::Entry & cdl = e.getValue(cdtl[cd_type_]); - for (int i = 0; i < cdl.childCount(); ++i) { - const PIConfig::Entry * e(cdl.child(i)); - bool ok = false; - int id = e->name().toInt(-1, &ok); -// piCout << "[read]" << ke->name() << ke->value() << ok; -// PIString n = ke->getValue("v").comment(); -// PIString t = n.takeLeft(1); - if (ok) { - CDType c; - PIString ev; - switch (cd_type_) { - case CDType::cdNull: break; - case CDType::cdK: - c = CDType(id, e->getValue("v").comment(), e->getValue("v").type(), e->getValue("v").value(), e->getValue("f").value(), e->getValue("f").comment(), cd_type_); - ev = e->getValue("ev", "").value(); - if (!ev.isEmpty()) - c.enum_values = c.parseEnumComment(ev); - break; - case CDType::cdX: - c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_); - c.setXMode((CDType::XMode)e->getValue("mode", int(CDType::X_Current)).value().toInt()); - c.setAvg((CDType::XMode)e->getValue("avg", 1).value().toInt()); - c.x_enabled = e->getValue("sel", false).value().toBool(); - break; - case CDType::cdC: - case CDType::cdM: - c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_); - break; - } - cd[id] = c; - } - } - PIConfig::Entry & sl = e.getValue("s"); - for (int i = 0; i < sl.childCount(); ++i) { - const PIConfig::Entry * se(sl.child(i)); - int sid = se->name().toInt(); - CDSection & rs(s[sid]); - rs.cd_type_ = cd_type_; - rs.read(se); - } -// piCout << "[CDSection] read end"; -} - - -void CDSection::update(CDSection & v, UpdateModeFlags mode) { - if (mode[SaveByIndex] && mode[SaveByName]) { - piCout << "[CDSection] update error: SaveByIndex | SaveByName mode is denied!"; - return; - } - //piCout << "[CDSection] update start"; - //piCout << "before" << k.size() << v.k.size(); - - PIMap prev_cd_f_bi; - PIMap prev_cd_f_bn; - PIMap::iterator i; - if (mode[SaveByIndex]) { - for (i = cd.begin(); i != cd.end(); ++i) - prev_cd_f_bi[i.key()] = i.value().formula(); - } - if (mode[SaveByName]) { - for (i = cd.begin(); i != cd.end(); ++i) - prev_cd_f_bn[i.value().name_] = i.value().formula(); - } - if (!mode[Merge]) - cd.clear(); - for (i = v.cd.begin(); i != v.cd.end(); ++i) { - int id = i.key(); - PIString n = i.value().name(); - cd[id] = i.value(); - if (mode[SaveByIndex]) { - if (prev_cd_f_bi.contains(id)) - cd[id].setFormula(prev_cd_f_bi[id]); - } - if (mode[SaveByName]) { - if (prev_cd_f_bn.contains(n)) - cd[id].setFormula(prev_cd_f_bn[n]); - } - } - - PIMap prev_s_bi; - PIMap prev_s_bn; - PIMap::iterator j; - if (mode[SaveByIndex]) { - for (j = s.begin(); j != s.end(); ++j) - prev_s_bi[j.key()] = j.value(); - } - if (mode[SaveByName]) { - for (j = s.begin(); j != s.end(); ++j) - prev_s_bn[j.value().alias] = j.value(); - } - if (!mode[Merge]) - s.clear(); - for (j = v.s.begin(); j != v.s.end(); ++j) { - int id = j.key(); - PIString n = j.value().alias; - s[id] = j.value(); - if (mode[SaveByIndex]) { - if (prev_s_bi.contains(id)) - s[id] = prev_s_bi[id]; - } - if (mode[SaveByName]) { - if (prev_s_bn.contains(n)) - s[id] = prev_s_bn[n]; - } - s[id].update(j.value(), mode); - } - - /*PISet used; - for (i = k.begin(); i != k.end(); ++i) { - if (v.k.contains(i.key())) { - PIString f = k[i.key()].formula_; - CDType & cdt = v.k[i.key()]; - cdt.formula_ = f; - k[i.key()] = cdt; - used << i.key(); - } - if (mode) { - CDType & ck(k[i.key()]); - if (prev_k_f_bn.contains(ck.name_)) - ck.setFormula(prev_k_f_bn[ck.name_]); - } - } - //piCout << " after" << k.size(); - for (i = v.k.begin(); i != v.k.end(); ++i) { - if (!used.contains(i.key())) - k[i.key()] = i.value(); - CDType & ck(k[i.key()]); - ck.setFormula(prev_k_f_bn.value(ck.name_)); - } - used.clear(); - PIMap::iterator j; - for (j = s.begin(); j != s.end(); ++j) { - if (v.s.contains(j.key())) - j.value().update(v.s[j.key()], mode); - used << j.key(); - } - for (j = v.s.begin(); j != v.s.end(); ++j) { - if (!used.contains(j.key())) - s[j.key()] = j.value(); - }*/ -// piCout << "[CDSection] update end"; -} - - -bool CDSection::isSameStructure(CDSection & v) { - PIMap cd_ids; - PIMap::iterator i; - for (i = cd.begin(); i != cd.end(); ++i) - cd_ids[i.value().name()] = i.key(); - for (i = v.cd.begin(); i != v.cd.end(); ++i) { - if (!cd_ids.contains(i.value().name())) continue; - //piCout << i.key() << k[i.key()].name() << i.value().name(); - if (cd[cd_ids[i.value().name()]].index() != i.key()) - return false; - } - PIMap::iterator j; - for (j = v.s.begin(); j != v.s.end(); ++j) { - if (!s.contains(j.key())) continue; - if (!s[j.key()].isSameStructure(j.value())) - return false; - } - return true; -} - - -void CDSection::prepareCalculate() { - PIMap::iterator i; - for (i = cd.begin(); i != cd.end(); ++i) { - i.value().parent = this; - i.value().calculated = false; - } - PIMap::iterator j; - for (j = s.begin(); j != s.end(); ++j) - j.value().prepareCalculate(); -} - - -void CDSection::calculateRecursive(PIEvaluator * e) { - PIMap::iterator i; - for (i = cd.begin(); i != cd.end(); ++i) - i.value().calculate(e); - PIMap::iterator j; - for (j = s.begin(); j != s.end(); ++j) - j.value().calculateRecursive(e); -} - - -void CDSection::setSelectedX(bool yes) { - PIMap::iterator i; - for (i = cd.begin(); i != cd.end(); ++i) - i.value().x_enabled = yes; - PIMap::iterator j; - for (j = s.begin(); j != s.end(); ++j) - j.value().setSelectedX(yes); -} - - -PIVector > CDSection::collectX() const { - PIVector > ret; - PIMap::const_iterator i; - for (i = cd.begin(); i != cd.end(); ++i) { - if (i.value().x_enabled) - ret << i.value().path(); - } - PIMap::const_iterator j; - for (j = s.constBegin(); j != s.constEnd(); ++j) - ret << j.value().collectX(); - return ret; -} - - -void CDSection::makePath(PIDeque p) { - PIDeque tp; - PIMap::iterator i; - for (i = cd.begin(); i != cd.end(); ++i) { - tp = p; - tp << i.key(); - i.value().path_ = tp; - //piCout << "path for" << i.value().name() << tp; - } - PIMap::iterator j; - for (j = s.begin(); j != s.end(); ++j) { - tp = p; - tp << j.key(); - j.value().makePath(tp); - } -} - - -PIVector CDSection::children(bool recursive) const { - PIVector ret; - PIMap::const_iterator i; - for (i = cd.begin(); i != cd.end(); ++i) - ret << const_cast(&(i.value())); - if (!recursive) return ret; - PIMap::const_iterator j; - for (j = s.constBegin(); j != s.constEnd(); ++j) - ret << j.value().children(true); - return ret; -} - - -PIVariantTypes::Enum CDSection::enumValues() const { - PIVariantTypes::Enum ret; - PIMap::const_iterator i; - for (i = cd.constBegin(); i != cd.constEnd(); ++i) - ret << PIVariantTypes::Enumerator(i.key(), i.value().name()); - return ret; -} - - diff --git a/cd_utils/cdutils_types.h b/cd_utils/cdutils_types.h deleted file mode 100644 index 299e4a9..0000000 --- a/cd_utils/cdutils_types.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_TYPES_H -#define CDUTILS_TYPES_H - -#include "pistring.h" -#include "pimap.h" -#include "pivariant.h" -#include "cd_utils_export.h" - -class PIIODevice; -class PIEvaluator; -class CD_Pult; -class CDItem; -class CDItemModel; - -namespace CDUtils { - -class CDSection; - -enum UpdateMode { - SaveByIndex = 0x01, - SaveByName = 0x02, - Merge = 0x04 -}; - -enum MessageType { - Log = 1, - MessageBox, -}; - -typedef PIFlags UpdateModeFlags; - -class CD_UTILS_EXPORT CDType { - friend class CDSection; - friend class CDCore; - friend class Interface; - friend class XInterface; -public: - enum cdT {cdNull, cdK, cdX, cdC, cdM}; - enum XMode {X_Current, X_All_Avg}; - - CDType(); - CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t); - - CDType & operator =(double x); - int index() const {return index_;} - PIString name() const {return name_;} - PIString type() const; - PIString value() const; - PIVariant variantValue() const; - PIString formula() const {return formula_;} - PIString comment() const {return comment_;} - double toDouble() const {return value_d;} - int toInt() const {return value_i;} - bool toBool() const {return value_b;} - cdT cd_type() const {return cd_type_;} - void setValue(const PIString & value_); - void setVariantValue(const PIVariant & value_); - void setFormula(const PIString & formula); - void setComment(const PIString & comment) {comment_ = comment;} - operator double() const {return value_d;} - const PIVariantTypes::Enum & enumValues() const {return enum_values;} - void setEnumValues(const PIVariantTypes::Enum & ev) {enum_values = ev;} - const PIString & errorString() const {return error_;} - PIDeque path() const {return path_;} - PIStringList pathString() const; - - void setXMode(XMode mode) {mode_ = mode;} - void setAvg(int avg) {avg_size = avg;} - XMode xmode() const {return mode_;} - XMode xmode_rec() const {return rmode_;} - int avg() const {return avg_size;} - bool isSelectedX() const {return x_enabled;} - void readX(PIByteArray & ba); - void writeX(PIByteArray & ba); - - PIVector history; - -protected: - bool calculate(PIEvaluator * e, PIVector stack = PIVector()); - PIVariantTypes::Enum parseEnumComment(PIString c); - cdT cd_type_; - int index_; - PIString name_, type_; - PIString value_s, formula_, comment_, error_; - PIVariantTypes::Enum enum_values; - CDSection * parent; - PIDeque path_; - double value_d; - int value_i; - bool value_b, calculated, x_enabled; - PIVector avg_h; - int avg_size; - XMode mode_, rmode_; -}; - - -class CD_UTILS_EXPORT CDSection { - friend class CDCore; - friend class Interface; - friend class XInterface; - friend class ::CD_Pult; - friend class ::CDItem; - friend class ::CDItemModel; -public: - - CDSection(CDType::cdT type_ = CDType::cdNull); - - bool test(int v) {return cd.value(v).toBool();} -// CDType & operator [](int v) {if (!k.contains(v)) k[v].index_ = v; return k[v];} - CDType & operator [](int v) {return cd[v];} - const CDType operator [](int v) const {return cd[v];} - CDType & operator [](const PIString & name_) {return getByName(name_);} - const CDType operator [](const PIString & name_) const {return const_cast(this)->getByName(name_);} - CDType & operator [](const PIDeque & path_) {return getByPath(path_);} - const CDType operator [](const PIDeque & path_) const {return const_cast(this)->getByPath(path_);} - CDSection & section(int v); - const CDSection section(int v) const; - - bool isEmpty() const {return cd.isEmpty() && s.isEmpty();} - bool exists(PIDeque path) const; - int count(bool recursive = true) const; - int sectionsCount() const; - PIVector indexes() const {return cd.keys();} - PIStringList index_names() const; - void calculate(); - void makePath(PIDeque p = PIDeque()); - PIVector children(bool recursive = true) const; - PIVariantTypes::Enum enumValues() const; - - PIString name; - PIString alias; - -protected: - CDSection(PIMap k_, PIMap s_) { - cd = k_; - s = s_; - } - CDType & getByName(const PIString & name_); - CDType & getByPath(const PIDeque & path_); - void write(PIIODevice * d, const PIString & prefix = PIString()); - void read(const void * ep); - void update(CDSection & v, UpdateModeFlags mode = SaveByName); - bool isSameStructure(CDSection & v); - void prepareCalculate(); - void calculateRecursive(PIEvaluator * e); - void setSelectedX(bool yes); - PIVector > collectX() const; - - PIMap cd; - mutable PIMap s; - CDType null; - CDType::cdT cd_type_; -}; - -} - - -inline PICout operator <<(PICout s, const CDUtils::CDType & v) { - s.space(); - s.setControl(0, true); - switch (v.cd_type()) { - case CDUtils::CDType::cdK : s << "K["; break; - case CDUtils::CDType::cdX : s << "X["; break; - case CDUtils::CDType::cdC : s << "C["; break; - case CDUtils::CDType::cdM : s << "M["; break; - default : s << "Null["; break; - } - s << v.name() << "(" << v.index() << ")] = " << v.value(); - s.restoreControl(); - return s; -} - - -#endif // CDUTILS_TYPES_H diff --git a/cd_utils/cdutils_x.cpp b/cd_utils/cdutils_x.cpp deleted file mode 100644 index 2b2d24a..0000000 --- a/cd_utils/cdutils_x.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "cdutils_x.h" -#include "cdutils_core.h" - -using namespace CDUtils; - -XInterface X; - - -XInterface::XInterface(): Interface(CDType::cdX) { - CONNECTU(core, X_ReceivedX, this, receivedX); -} - - -void XInterface::setEnabled(const CDType & x, bool en) { - core->x_mutex.lock(); - CDType & t((*s)[x.path()]); - if (t.cd_type() != CDType::cdX) { - core->x_mutex.unlock(); - return; - } - t.x_enabled = en; - //piCout << t << "x_enabled" << en; - core->need_rebuild_x = true; - core->x_mutex.unlock(); -} - - -PIVector > XInterface::enabledList() const { - return CDCore::instance()->x_selected; -} - - -void XInterface::setEnabledList(const PIVector > & l) { - CDCore::instance()->x_selected = l; -} - - -void XInterface::lock() { - CDCore::instance()->x_mutex.lock(); -} - - -void XInterface::unlock() { - CDCore::instance()->x_mutex.unlock(); -} - - -void XInterface::start(double freq) { - core->startX(freq); -} - - -void XInterface::stop() { - core->stopX(); -} diff --git a/cd_utils/cdutils_x.h b/cd_utils/cdutils_x.h deleted file mode 100644 index b0a8e3c..0000000 --- a/cd_utils/cdutils_x.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - CD Utils - Control-Debug utilites - - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef CDUTILS_X_H -#define CDUTILS_X_H - -#include "cdutils_interface.h" -#include "cd_utils_export.h" - - -namespace CDUtils { - - -class CD_UTILS_EXPORT XInterface: public Interface -{ - PIOBJECT_SUBCLASS(XInterface, Interface) -public: - XInterface(); - - EVENT1(keepNamesRequest, bool*, xn) - EVENT1(receivedX, PIVector >, pathes) - - void enable(const CDType & x) {setEnabled(x, true);} - void disable(const CDType & x) {setEnabled(x, false);} - void setEnabled(const CDType & x, bool en); - void setDisabled(const CDType & x, bool dis) {setEnabled(x, !dis);} - PIVector > enabledList() const; - void setEnabledList(const PIVector > & l); - void lock(); - void unlock(); - - void start(double freq = 20.); - void stop(); - -}; - -} - -extern CD_UTILS_EXPORT CDUtils::XInterface X; - -#endif // CDUTILS_X_H diff --git a/cd_utils/cdutilstest.cpp b/cd_utils/cdutilstest.cpp deleted file mode 100644 index ff35970..0000000 --- a/cd_utils/cdutilstest.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "cdutils_k.h" -#include "cdutils_x.h" -#include "cdutils_c.h" -#include "cdutils_m.h" -#include "cdutils_core.h" -#include "cdtest.h" -#include "pip.h" -#include "k_description.h" - -using namespace CDUtils; - -class Core : public PIObject -{ - PIOBJECT(Core) - public: - Core() { - CDCore::instance()->initApp(); -// piCout << "testCore"; - CONNECTU(&timer, tickEvent, this, timerDone); - CONNECTU(&X, received, this, xrecv); - CONNECTU(&C, received, this, crecv); - t = 0.; - } - - void load() { - rf.open("k.dat", PIIODevice::ReadWrite); - K.read(&rf); - rf.close(); - } - - void save() { - rf.open("k_out.txt", PIIODevice::ReadWrite); - rf.resize(0); - K.write(&rf); - rf.close(); -// rf.open("k_out.txt", PIIODevice::ReadWrite); -// K.read(&rf); -// rf.close(); -// rf.open("k_out2.txt", PIIODevice::ReadWrite); -// rf.resize(0); -// K.write(&rf); -// rf.close(); -// rf.open("k_out2.txt", PIIODevice::ReadWrite); -// K.read(&rf); -// rf.close(); -// rf.open("k_out3.txt", PIIODevice::ReadWrite); -// rf.resize(0); -// K.write(&rf); -// rf.close(); - } - - void test() { - X.lock(); - X[KD::Frequency] = 100; - X.section(KD::Spectrometer)[KD::Temperature_default] = sin(t); - t += 0.01; - X.unlock(); - /*piCout << "count" << K.count(); - piCout << K[First]; - piCout << K[Second];*/ - } - - EVENT_HANDLER(void, ksend) {piCout << "sended k";} - EVENT_HANDLER(void, crecv) { - piCout << "received c"; - C.connect(C.section(KD::Logs).section(KD::Spec).section(KD::Formats)[KD::Binary], this, HANDLER(cmd)); - C.autoConnect(this); - } - EVENT_HANDLER(void, xrecv) { - piCout << "received x"; - if (!timer.isRunning()) timer.start(10); - X.start(); - } - EVENT_HANDLER(void, timerDone) {test();} - EVENT_HANDLER(void, cmd) {piCout << "command cmd";} - EVENT_HANDLER(void, c_Pause) { - piCout << "command pause"; - M[KD::Main] << "rec command" << C[KD::Pause]; - M.messageBox(M.root()[KD::Core], "init successfull"); - } - EVENT_HANDLER(void, c_Spectrometer_Connection) {piCout << "command spec_conn";} - -private: - PIFile rf; - PITimer timer; - double t; -}; - - -int main(int argc, char *argv[]) { - X.start(); - piSleep(1); - //CDCore::instance()->destroy(); - piCout << "DELETED"; - return 0; -} - diff --git a/cd_utils/k_description.h b/cd_utils/k_description.h deleted file mode 100644 index 09d53ce..0000000 --- a/cd_utils/k_description.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef K_DESCRIPTION_H -#define K_DESCRIPTION_H - -namespace KD { - -enum Sections { - Startup, - Spectrometer, - Switch, - Formats, - Logs, - Detector, - CoreOutput, -}; - -enum LogFormat { - Text, //b text - Binary, //b binary -}; - -enum LogType { - Data, //b write data logs - Spec, //b write spectrogram logs - ARINC, //b ARINC -}; - -enum KLogConfig { - // LogFormat = Formats - StartupWrite, //b - ApplyBinaryLogHeader, //b Apply settings under ID = 255 for binary log - MaximumWriteFrequency, //f Maximum frequency for log in Hz, or 0 for unlimited -}; - -enum SwitchType { - BaySpec, - DiCon, -}; - -enum SpectrometerConnection { - TCP, - USB, -}; - -enum PeakSearchMode { - Left, - Max, - Right, -}; - -enum CoreMode { - ModeSpectrometer, - ModePlayer, - ModePeaks, -}; - -enum KSpectrometer { - Connection, //e ${SpectrometerConnection} - Temperature_compensation, //b Use temperature sensor or default temperature witout compensation - Temperature_default, //f Default temperature using if compensation disabled -}; - -enum KSwitch { - Enabled, //b 0 or 1 Use optical switch or not - Wait, //n Delay after switching channel, ms - Autoscan, //e {0 - scan with our forces, 1 - SDK autoscan} - Autoscan_offset, //n Offset for SDK autoscan - Type, //e ${SwitchType} -}; - -enum KDetector { - Threshold_Min, //f - Threshold_Max, //f - SideSize, //f - SideOffset, //f - PeaksSearch, //e ${PeakSearchMode} -}; - -enum KCoreOutput { - SendSpectrum, //b Send spectrum data or empty vector - SendOnlyCurrentValue, //b Send current values or all stored in 20Hz -}; - -enum CoreOutputChannel { - GUI, - SecGUI, - ThirdGUI, -}; - -enum KDescription { - // KSpectrometer = Spectrometer - // KSwitch = Switch - // KDetector = Detector - // KCoreOutput[CoreOutputChannel] = CoreOutput - // KLogConfig[LogType] = Logs - Gratings_history, //n Gratings peak values history, count - Amplitude_history_size, //n Count of history values to calculate sensors amplitude - Fourier_enabled, //b Global fourier enable flag - Fourier_size, //n Size of fourier window, in counts - Fourier_YScale, //f scale for fourier amplitude - Fourier_Max_or_Density, //n 0 - Maximum in fourier window, 1 - Density of fourier window - Mode, //e ${CoreMode} Work mode - SynchronizationEnabled, //b When enabled, start logs and reset time when sync signal received - SynchronizationMode, //e {0 - disabled, 1 - new file, 2 - column in log} - LambdasAutoReset, //b Set lambdas_0 to grating values on first data receive - Gauss_size, //n - //Peak_max_offset, //f in pixels - //Peak_LF_coeff, //f 1. - no filtering - GratingOverloadMax, //n - GratingOverloadMin, //n - SendLED, //b Send to LED Arduino serial port current state - SynchronizationClearValues, //b clear gratings and sensors values and history on sync - PeaksModeFrequency, //f - PeaksModeAdditionNm_1, //f Addition nm to peaks in ModePeaks, channel 1 - PeaksModeAdditionNm_2, //f Addition nm to peaks in ModePeaks, channel 2 - PeaksModeAdditionNm_3, //f Addition nm to peaks in ModePeaks, channel 3 - PeaksModeAdditionNm_4, //f Addition nm to peaks in ModePeaks, channel 4 -}; - -enum XDescription { - // KSpectrometer = Spectrometer - // KSwitch = Switch - // KDetector = Detector - // KCoreOutput[CoreOutputChannel] = CoreOutput - // KLogConfig[LogType] = Logs - State, //b - Frequency, //n cur freq - //Fourier_enabled, //b Global fourier enable flag -}; - -enum CDescription { - // KSpectrometer = Spectrometer - // KCoreOutput[CoreOutputChannel] = CoreOutput - // KLogConfig[LogType] = Logs - Halt, //b - Reboot, //n cur freq - Pause, //b Global fourier enable flag -}; - -enum MDescription { - Main, //b - Core, //s - Warnings, //b Global fourier enable flag -}; - -} - -#endif // K_DESCRIPTION_H diff --git a/qad/cmake/FindQAD.cmake b/cmake/FindQAD.cmake similarity index 100% rename from qad/cmake/FindQAD.cmake rename to cmake/FindQAD.cmake diff --git a/qad/cmake/QADMacros.cmake b/cmake/QADMacros.cmake similarity index 100% rename from qad/cmake/QADMacros.cmake rename to cmake/QADMacros.cmake diff --git a/qad/cmake/QtWraps.cmake b/cmake/QtWraps.cmake similarity index 96% rename from qad/cmake/QtWraps.cmake rename to cmake/QtWraps.cmake index eac40ee..da1df24 100644 --- a/qad/cmake/QtWraps.cmake +++ b/cmake/QtWraps.cmake @@ -1,811 +1,811 @@ -#[[ - -find_qt([ ...] [Qt4] [Qt5]) - -Find Qt4 or/and Qt5 packages -If Qt4/5 found, set -* Qt<4/5>_ROOT var to Qt root dir -* Qt<4/5>_BIN var to Qt binary dir -* Qt<4/5>_PLUGINS_DIR var to Qt plugins dir -* Qt<4/5>_LANG_DIR var to Qt translations dir - - - - -qt_sources( [NO_DEFAULT] [DIR ] [ ...]) - -Collect all sources, optionally in directory and -Additional filters . By default filter files with regexps -"*.h", "*.hpp", "*.c", "*.cpp", "*.ui", "*.qrc", "*.rc", "*.ts" and "lang/*.ts". -Default filters disabled with option NO_DEFAULT - - - - -qt_wrap( ... [HDRS ] [CPPS ] [QMS ]) - -Prepare sources for compile -Store headers to , all wrapped Qt4 files to _Qt4 and Qt5 files to _Qt5 -version are automatic detected after find_qt() call - - - - -qt_add_executable( [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...]) - -Add executables for founded Qt versions, target names is -All needed Qt includes automatic added to corresponding targets - cant be CPPS variable passed to qt_wrap() or some list or filename - - - - -qt_add_library( [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...]) - -Add library for founded Qt versions, target names is -All needed Qt includes automatic added to corresponding targets - cant be CPPS variable passed to qt_wrap() or some list or filename - - - - -qt_target_link_libraries( ... ...) - -Link targets for founded Qt versions, target names is -All needed Qt libraries automatic added to corresponding targets -if QT_MULTILIB_LIST contains some linking library, to it name automatic -add or individual libname<_SUFFIX_Qt?> - - - - -qt_target_compile_definitions( ...) - -Syntax similar to original "target_compile_definitions()" -Specify compile definitions to use when compiling a given - - - - -qt_target_include_directories( ...) - -Syntax similar to original "target_include_directories()" -Add include directories to a target - - - - -qt_install(...) - -Syntax similar to original "install()" -Install targets for founded Qt versions - -if DESTINATION set to "QtBin" files will be installed -to corresponding Qt binary directory -if DESTINATION set to "QtLang" files will be installed -to corresponding Qt translation directory -if DESTINATION starts with "QtPlugins" files will be installed -to corresponding Qt plugins directory - -Add LANG type for first argument - in this case you should -specify variable name, not variable value! -e.g. "qt_install(LANG my_QM DESTINATION QtLang)" - - - - -qt_install_lang( DESTINATION [PATHS [] [...] ]) - -Search Qt translations for all dependencies -in Qt_LANG_DIR for _LANG languages -and install them to . PATH are additional search paths. -You should use "set_lang()" macro before this action - - - - -qt_get_target( [Qt4 | Qt5]) - -Write real Qt target name to -If Qt4 or Qt5 specified, search for this version, -otherwise returns greatest version - - - - -qt_get_targets( ) - -Write all real Qt target names to - - - - -qt_generate_export_header( ...) - -Call generate_export_header on Qt multitarget - - -]] - - -cmake_policy(SET CMP0011 NEW) # don`t affect includer policies -cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows -if (POLICY CMP0057) - cmake_policy(SET CMP0057 NEW) # Support if() IN_LIST -endif() -if (POLICY CMP0074) - cmake_policy(SET CMP0074 OLD) # ignore _ROOT variables -endif() -set(__qt_bug_modules "UiTools") - - -set(_QT_VERSIONS_ 4 5) -foreach(_v ${_QT_VERSIONS_}) - if (NOT DEFINED TARGET_SUFFIX_Qt${_v}) - set(TARGET_SUFFIX_Qt${_v} "${_v}") - set(MULTILIB_SUFFIX_Qt${_v} "${_v}") - endif() - set(MOC_INC_Qt${_v}) -endforeach() -if (NOT DEFINED QT_MULTILIB_LIST) - set(QT_MULTILIB_LIST) -endif() -#set(TARGET_SUFFIX_Qt4 "") - - -macro(find_qt) - set(_QCOMP) - foreach(_v ${_QT_VERSIONS_}) - set(_NEED${_v} 0) - set(LOCAL_FOUND${_v} 0) - set(MOC_INC_Qt${_v}) - set(Qt${_v}_INCLUDES) - set(Qt${_v}_LIBRARIES) - set(Qt${_v}_ROOT) - set(Qt${_v}_BIN) - set(Qt${_v}_PLUGINS_DIR) - set(Qt${_v}_LANG_DIR) - endforeach() - set(_NEED_SOME 0) - set(_QUIET) - foreach(_i ${ARGN}) - set(_FOUND_NEED 0) - foreach(_v ${_QT_VERSIONS_}) - if ("x${_i}" STREQUAL "xQt${_v}") - set(_NEED${_v} 1) - set(_NEED_SOME 1) - set(_FOUND_NEED 1) - endif() - if ("x${_i}" STREQUAL "xQUIET") - set(_QUIET QUIET) - endif() - endforeach() - if (NOT _FOUND_NEED) - list(APPEND _QCOMP "${_i}") - endif() - endforeach() - if (NOT _NEED_SOME) - foreach(_v ${_QT_VERSIONS_}) - set(_NEED${_v} 1) - endforeach() - endif() - list(REMOVE_DUPLICATES _QCOMP) - if (_NEED4) - find_package(Qt4 ${_QUIET}) - if (Qt4_FOUND) - set(LOCAL_FOUND4 1) - get_filename_component(Qt4_BIN ${QT_QMAKE_EXECUTABLE} PATH) - set(Qt4_INCLUDES ${QT_INCLUDES}) - foreach(m ${_QCOMP}) - string(TOUPPER "${m}" _um) - #message("${QT_QT${_um}_FOUND}") - if (${QT_QT${_um}_FOUND}) - list(APPEND Qt4_LIBRARIES ${QT_QT${_um}_LIBRARY}) - endif() - endforeach() - set(Qt4_PLUGINS_DIR ${QT_PLUGINS_DIR}) - set(Qt4_LANG_DIR ${Qt4_BIN}/../translations) - set(Qt4_ROOT "${Qt4_BIN}/../") - endif() - endif() - if (_NEED5) - #set(_MSG 1) - #if (Qt5_FOUND) - # set(_MSG 0) - #endif() - find_package(Qt5 COMPONENTS Core LinguistTools UiPlugin Widgets ${_QCOMP} ${_QUIET}) - if (DEFINED ANDROID_PLATFORM) - set(CMAKE_SHARED_MODULE_SUFFIX_CXX ".so") - set(CMAKE_SHARED_LIBRARY_SUFFIX_CXX ".so") - set(CMAKE_SHARED_MODULE_SUFFIX_C ".so") - set(CMAKE_SHARED_LIBRARY_SUFFIX_C ".so") - endif() - if (Qt5_FOUND) - set(LOCAL_FOUND5 1) - set(_Qt5Modules) - foreach(m ${_QCOMP}) - if (${Qt5${m}_FOUND}) - set(__lib ${Qt5${m}_LIBRARIES}) - if (DEFINED ANDROID_PLATFORM) - if (m IN_LIST __qt_bug_modules) - get_target_property(__lib Qt5::${m} LOCATION) - endif() - endif() - list(APPEND _Qt5Modules ${m}) - list(APPEND Qt5_INCLUDES ${Qt5${m}_INCLUDE_DIRS}) - list(APPEND Qt5_LIBRARIES ${__lib}) - endif() - endforeach() - #get_property(_up_dir TARGET Qt5::UiPlugin PROPERTY INTERFACE_INCLUDE_DIRECTORIES) - #message("${_up_dir}") - #if (NOT "x${_up_dir}" STREQUAL "x") - # list(APPEND Qt5_INCLUDES ${_up_dir}) - #endif() - get_target_property(_Qt5_qmake Qt5::qmake LOCATION) - get_filename_component(Qt5_BIN ${_Qt5_qmake} PATH) - foreach(_p ${Qt5Gui_PLUGINS}) - get_target_property(_l ${_p} LOCATION) - get_filename_component(_l ${_l} DIRECTORY) - string(FIND "${_l}" "/" _ind REVERSE) - string(SUBSTRING "${_l}" 0 ${_ind} _l) - set(Qt5_PLUGINS_DIR ${_l}) - #message("Qt5: plugins dir: ${Qt5_PLUGINS_DIR}") - break() - endforeach() - string(FIND "${Qt5_BIN}" "/" _ind REVERSE) - string(SUBSTRING "${Qt5_BIN}" 0 ${_ind} Qt5_ROOT) - if ("x${Qt5_PLUGINS_DIR}" STREQUAL "x") - set(Qt5_PLUGINS_DIR "${Qt5_ROOT}/plugins") - endif() - if (APPLE) - list(APPEND MOC_INC_Qt5 "-F${Qt5_ROOT}/lib") - endif() - set(Qt5_LANG_DIR ${Qt5_BIN}/../translations) - if (NOT _QT5_MSG) - message(STATUS "Found Qt5: ${_Qt5_qmake} (version \"${Qt5_VERSION}\")") - set(_QT5_MSG 1 CACHE BOOL "msg_qt5" FORCE) - #message(STATUS "Found Qt5 modules: ${_Qt5Modules}") - endif() - endif() - endif() - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - foreach(_p ${Qt${_v}_INCLUDES}) - list(APPEND MOC_INC_Qt${_v} "-I${_p}") - #message("${_p}") - endforeach() - endif() - #message("${MOC_INC_Qt${_v}}") - endforeach() - -endmacro() - - -macro(qt_sources OUT) - set(${OUT}) - set(_DIR "") - set(_IS_DIR 0) - set(_NO_DEFAULT 0) - set(_DEFAULT) - set(_REGEXP) - set(_REGEXP_WD) - foreach(_i ${ARGN}) - if (_IS_DIR) - set(_DIR "${_i}") - set(_IS_DIR 0) - elseif ("x${_i}" STREQUAL "xDIR") - set(_IS_DIR 1) - elseif ("x${_i}" STREQUAL "xNO_DEFAULT") - set(_NO_DEFAULT 1) - else() - list(APPEND _REGEXP ${_i}) - endif() - endforeach() - if (NOT "x${_DIR}" STREQUAL "x") - #file(TO_CMAKE_PATH "${_DIR}//" _DIR) - string(REPLACE "\\" "/" _DIR "${_DIR}/") - string(REPLACE "//" "/" _DIR "${_DIR}") - endif() - foreach(_i ${_REGEXP}) - list(APPEND _REGEXP_WD "${_DIR}${_i}") - endforeach() - if (NOT _NO_DEFAULT) - set(_DEFAULT "${_DIR}*.h" "${_DIR}*.hpp" "${_DIR}*.c" "${_DIR}*.cpp" "${_DIR}*.ui" "${_DIR}*.qrc" "${_DIR}*.rc" "${_DIR}*.ts" "${_DIR}lang/*.ts") - endif() - #message("${_DEFAULT}, ${_REGEXP_WD}") - file(GLOB ${OUT} ${_DEFAULT} ${_REGEXP_WD}) -endmacro() - - -macro(qt_wrap) - set(HDR_VAR) - set(CPP_VAR) - set(QM_VAR) - set(_HDR_ARG 0) - set(_CPP_ARG 0) - set(_QM_ARG 0) - set(WAS_HDR_ARG 0) - set(WAS_CPP_ARG 0) - set(WAS_QM_ARG 0) - set(FILE_LIST) - foreach(_i ${ARGN}) - if (_HDR_ARG) - set(HDR_VAR ${_i}) - set(WAS_HDR_ARG 1) - set(_HDR_ARG 0) - elseif (_CPP_ARG) - set(CPP_VAR ${_i}) - set(WAS_CPP_ARG 1) - set(_CPP_ARG 0) - elseif (_QM_ARG) - set(QM_VAR ${_i}) - set(WAS_QM_ARG 1) - set(_QM_ARG 0) - elseif ("x${_i}" STREQUAL "xHDRS") - set(_HDR_ARG 1) - elseif ("x${_i}" STREQUAL "xCPPS") - set(_CPP_ARG 1) - elseif ("x${_i}" STREQUAL "xQMS") - set(_QM_ARG 1) - else() - list(APPEND FILE_LIST "${_i}") - endif() - endforeach() - foreach(_v ${_QT_VERSIONS_}) - set(CPP${_v}_VAR) - set(QM${_v}_VAR) - if (LOCAL_FOUND${_v}) - if (WAS_CPP_ARG) - set(CPP${_v}_VAR ${CPP_VAR}_Qt${_v}) - endif() - if (WAS_QM_ARG) - set(QM${_v}_VAR ${QM_VAR}_Qt${_v}) - endif() - endif() - endforeach() - #message("found 4: ${LOCAL_FOUND4}, 5: ${LOCAL_FOUND5}") - #message("has HRDS: ${WAS_HDR_ARG}: ${HDR_VAR}") - #message("has CPPS4: ${WAS_CPP_ARG}: ${CPP4_VAR}") - #message("has CPPS5: ${WAS_CPP_ARG}: ${CPP5_VAR}") - #message("files: ${FILE_LIST}") - set(H_LIST) - set(CPP_LIST) - set(UI_LIST) - set(RES_LIST) - set(RC_LIST) - set(TS_LIST) - foreach(_i ${FILE_LIST}) - get_filename_component(_EXT "${_i}" EXT) - #message("${_EXT}") - if (NOT ("x${_EXT}" STREQUAL "x")) - if (("x${_EXT}" STREQUAL "x.h") OR ("x${_EXT}" STREQUAL "x.hpp")) - list(APPEND H_LIST "${_i}") - #message("header") - endif() - if (("x${_EXT}" STREQUAL "x.c") OR ("x${_EXT}" STREQUAL "x.cpp") OR ("x${_EXT}" STREQUAL "x.cxx")) - list(APPEND CPP_LIST "${_i}") - #message("source") - endif() - if ("x${_EXT}" STREQUAL "x.ui") - list(APPEND UI_LIST "${_i}") - endif() - if ("x${_EXT}" STREQUAL "x.qrc") - list(APPEND RES_LIST "${_i}") - endif() - if ("x${_EXT}" STREQUAL "x.rc") - list(APPEND RC_LIST "${_i}") - endif() - if ("x${_EXT}" STREQUAL "x.ts") - list(APPEND TS_LIST "${_i}") - endif() - endif() - endforeach() - if (WAS_HDR_ARG) - set(${HDR_VAR}) - list(APPEND ${HDR_VAR} ${H_LIST}) - endif() - set(SRC_CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v} AND WAS_CPP_ARG) - set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR}/qt${_v}) - set(${CPP${_v}_VAR}) - if (WAS_QM_ARG) - set(${QM${_v}_VAR}) - endif() - set(MOCS${_v}) - set(CUIS${_v}) - set(CRES${_v}) - if (${_v} EQUAL 4) - qt4_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt4}) - qt4_wrap_ui(CUIS${_v} ${UI_LIST}) - qt4_add_resources(CRES${_v} ${RES_LIST}) - if (WAS_QM_ARG) - set(${QM${_v}_VAR} "") - qt4_add_translation(${QM${_v}_VAR} ${TS_LIST}) - endif() - elseif (${_v} EQUAL 5) - qt5_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt5}) - qt5_wrap_ui(CUIS${_v} ${UI_LIST}) - qt5_add_resources(CRES${_v} ${RES_LIST}) - if (WAS_QM_ARG) - set(${QM${_v}_VAR} "") - qt5_add_translation(${QM${_v}_VAR} ${TS_LIST}) - endif() - else() - # Qt6 ... - endif() - #message("${${QM${_v}_VAR}}") - list(APPEND ${CPP${_v}_VAR} ${CPP_LIST}) - list(APPEND ${CPP${_v}_VAR} ${RC_LIST}) - list(APPEND ${CPP${_v}_VAR} ${MOCS${_v}}) - list(APPEND ${CPP${_v}_VAR} ${CUIS${_v}}) - list(APPEND ${CPP${_v}_VAR} ${CRES${_v}}) - if (WAS_QM_ARG) - list(APPEND ${CPP${_v}_VAR} ${${QM${_v}_VAR}}) - endif() - #message("${${QM${_v}_VAR}}") - endif() - endforeach() - set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR}) -endmacro() - - -macro(_qt_split_add_args _P _A) - set(${_P}) - set(${_A}) - foreach(_i ${ARGN}) - if (NOT ("x${${_i}_Qt${_v}}" STREQUAL "x")) - list(APPEND ${_A} ${${_i}_Qt${_v}}) - elseif (("x${_i}" STREQUAL "xWIN32") OR - ("x${_i}" STREQUAL "xMACOSX_BUNDLE") OR - ("x${_i}" STREQUAL "xSTATIC") OR - ("x${_i}" STREQUAL "xSHARED") OR - ("x${_i}" STREQUAL "xMODULE") OR - ("x${_i}" STREQUAL "xEXCLUDE_FROM_ALL")) - list(APPEND ${_P} ${_i}) - elseif ("x${${_i}}" STREQUAL "x") - list(APPEND ${_A} ${_i}) - else() - list(APPEND ${_A} ${${_i}}) - endif() - endforeach() -endmacro() - - -macro(__qt_set_defines _NAME _T) - target_compile_definitions(${_T} PRIVATE "__TARGET_NAME__=\"${_NAME}\"") - target_compile_definitions(${_T} PRIVATE "__TARGET_LABEL__=\"${${_NAME}_LABEL}\"") - target_compile_definitions(${_T} PRIVATE "__TARGET_COMPANY__=\"${${_NAME}_COMPANY}\"") - target_compile_definitions(${_T} PRIVATE "__TARGET_VERSION__=\"${${_NAME}_VERSION}\"") -endmacro() - - -macro(qt_add_executable _NAME) - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - _qt_split_add_args(_PREF _ARGS ${ARGN}) - if(APPLE) - set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}") - set(CMAKE_INSTALL_NAME_DIR "@rpath") - else() - if(NOT WIN32) - set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib") - endif() - endif() - set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - add_executable(${_TARGET} ${_PREF} ${_ARGS}) - set(_${_NAME}_is_qt 1) - target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES}) - __qt_set_defines(${_NAME} ${_TARGET}) - - if(APPLE) - set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}") - endif() - # # Apple crosscompiling rpath patch - # if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH) - # foreach(_RP ${CMAKE_INSTALL_RPATH}) - # add_custom_command(TARGET ${_TARGET} POST_BUILD - # COMMAND "${CMAKE_INSTALL_NAME_TOOL}" - # "-add_rpath" "${_RP}" - # "$/$" - # COMMENT "Add to ${_TARGET} rpath \"${_RP}\"") - # endforeach() - # endif() - - #list(APPEND _ALL_TARGETS "${_TARGET}") - #set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) - endif() - endforeach() -endmacro() - - -macro(qt_add_library _NAME) - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - _qt_split_add_args(_PREF _ARGS ${ARGN}) - if(APPLE) - set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}") - set(CMAKE_INSTALL_NAME_DIR "@rpath") - else() - if(NOT WIN32) - set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib") - endif() - endif() - set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - add_library(${_TARGET} ${_PREF} ${_ARGS}) - set(_${_NAME}_is_qt 1) - target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES}) - __qt_set_defines(${_NAME} ${_TARGET}) - #message("add lib: \"${_TARGET}\"") - - if(APPLE) - set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}") - endif() - # # Apple crosscompiling rpath patch - # if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH) - # foreach(_RP ${CMAKE_INSTALL_RPATH}) - # add_custom_command(TARGET ${_TARGET} POST_BUILD - # COMMAND "${CMAKE_INSTALL_NAME_TOOL}" - # "-add_rpath" "${_RP}" - # "$/$" - # COMMENT "Add to ${_TARGET} rpath \"${_RP}\"") - # endforeach() - # endif() - - list(APPEND _ALL_TARGETS "${_TARGET}") - set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) - endif() - endforeach() -endmacro() - - -macro(_qt_multitarget_suffix_ _OUT _IN _v) - string(REPLACE ":" "_" _in_str "${_IN}") - if (NOT "x${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}" STREQUAL "x") - set(${_OUT} "${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}") - else() - set(${_OUT} "${MULTILIB_SUFFIX_Qt${_v}}") - endif() -endmacro() - - -macro(qt_target_link_libraries _NAME) - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - set(_ARGS) - foreach(_i ${ARGN}) - set(_ind -1) - list(FIND QT_MULTILIB_LIST "${_i}" _ind) - if (_ind GREATER -1) - _qt_multitarget_suffix_(_TS ${_i} ${_v}) - #message(STATUS "${_i} in MULTILIB_LIST, suffix = ${_TS}") - list(APPEND _ARGS ${_i}${_TS}) - else() - list(APPEND _ARGS ${_i}) - endif() - endforeach() - target_link_libraries(${_TARGET} ${Qt${_v}_LIBRARIES} ${_ARGS}) - #message("link ${_TARGET}: ${Qt${_v}_LIBRARIES} ${_ARGS}") - endif() - endforeach() -endmacro() - - -macro(qt_target_compile_definitions _NAME) - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - target_compile_definitions(${_TARGET} ${ARGN}) - endif() - endforeach() -endmacro() - - -macro(qt_target_include_directories _NAME) - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - target_include_directories(${_TARGET} ${ARGN}) - endif() - endforeach() -endmacro() - - -macro(qt_install) - set(_prev_inst) - set(__add_args) - #message("command: ${ARGN}") - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - set(_INST_LIST) - set(_IS_TARGET 0) - set(_IS_FILES 0) - set(_IS_DEST 0) - set(_IS_LANG 0) - set(_INVALID 0) - foreach(_i ${ARGN}) - if ("x${_i}" STREQUAL "xQtLang") - set(_IS_LANG 1) - endif() - endforeach() - foreach(_i ${ARGN}) - if (_IS_TARGET) - set(_IS_TARGET 0) - set(__target ${_i}) - if (_${_i}_is_qt) - set(__target ${_i}${TARGET_SUFFIX_Qt${_v}}) - endif() - if (DEFINED ANDROID_PLATFORM) - get_target_property(_TT ${__target} TYPE) - if ("x${_TT}" STREQUAL "xEXECUTABLE") - list(APPEND __add_args EXCLUDE_FROM_ALL) - endif() - endif() - list(APPEND _INST_LIST ${__target}) - elseif (_IS_FILES) - set(_IS_FILES 0) - if (_IS_LANG) - if (("x${${_i}_Qt${_v}}" STREQUAL "x") OR ("x${_i}" STREQUAL "xDESTINATION")) - set(_INVALID 1) - else() - list(APPEND _INST_LIST ${${_i}_Qt${_v}}) - endif() - else() - list(APPEND _INST_LIST ${_i}) - endif() - else() - if (_IS_DEST) - set(_IS_DEST 0) - if ("x${_i}" STREQUAL "xQtBin") - list(APPEND _INST_LIST "${Qt${_v}_BIN}") - elseif ("x${_i}" STREQUAL "xQtLang") - list(APPEND _INST_LIST "${Qt${_v}_LANG_DIR}") - else() - set(_ind -1) - string(FIND "${_i}" "QtPlugins" _ind) - if (_ind GREATER -1) - string(REPLACE "QtPlugins" "${Qt${_v}_PLUGINS_DIR}" _o "${_i}") - list(APPEND _INST_LIST "${_o}") - else() - string(REPLACE "\\" "/" _o "${_i}") - list(APPEND _INST_LIST ${_o}) - endif() - endif() - else() - set(_ii ${_i}) - if ("x${_i}" STREQUAL "xTARGETS") - set(_IS_TARGET 1) - elseif ("x${_i}" STREQUAL "xFILES") - set(_IS_FILES 1) - elseif ("x${_i}" STREQUAL "xDESTINATION") - set(_IS_DEST 1) - elseif ("x${_i}" STREQUAL "xLANG") - set(_IS_FILES 1) - set(_IS_LANG 1) - set(_ii "FILES") - endif() - list(APPEND _INST_LIST ${_ii}) - endif() - endif() - endforeach() - if (NOT _INVALID) - if (NOT ("x${_prev_inst}" STREQUAL "x${_INST_LIST}")) - #message("install: ${_INST_LIST}") - install(${_INST_LIST} ${__add_args}) - set(_prev_inst "${_INST_LIST}") - endif() - endif() - endif() - endforeach() -endmacro() - - -macro(qt_install_lang _NAME) - set(_prev_inst) - #message("command: ${ARGN}") - set(_PATHS) - set(_DEST) - if(CMAKE_CROSSCOMPILING) - list(APPEND _PATHS "${CMAKE_PREFIX_PATH}/lang") - endif() - set(_cur_arg) - set(__args "DESTINATION;PATHS") - foreach(_i ${ARGN}) - if (_i IN_LIST __args) - set(_cur_arg "${_i}") - elseif("${_cur_arg}" STREQUAL "DESTINATION") - set(_DEST "${_i}") - elseif("${_cur_arg}" STREQUAL "PATHS") - list(APPEND _PATHS "${_i}") - endif() - endforeach() - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - set(_target) - if (_${_NAME}_is_qt) - set(_target ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - endif() - get_target_property(_LL ${_target} LINK_LIBRARIES) - foreach (_L ${_LL}) - get_filename_component(_libname "${_L}" NAME_WE) - #message("depend on ${_libname}") - if ("${_libname}" MATCHES "Qt${_v}::.*") - string(SUBSTRING "${_libname}" 5 -1 _libname) - string(TOLOWER "${_libname}" _libname) - #message("qt lib \"${_libname}\"") - list(APPEND _qt_libs qt${_libname}) - else() - if ("${_libname}" MATCHES "lib.*") - string(LENGTH ${_libname} _sl) - math(EXPR _sl ${_sl}-3) - string(SUBSTRING ${_libname} 3 ${_sl} _libname) - endif() - if ("${_libname}" MATCHES "qad_.*${_v}") - string(LENGTH ${_libname} _sl) - math(EXPR _sl ${_sl}-1) - string(SUBSTRING ${_libname} 0 ${_sl} _libname) - #message("qad lib \"${_libname}\"") - list(APPEND _qt_libs ${_libname}) - endif() - endif() - endforeach() - if (NOT "x${_qt_libs}" STREQUAL "x") - list(APPEND _qt_libs "qtbase") - foreach (_i ${${PROJECT_NAME}_LANG}) - foreach (_l ${_qt_libs}) - unset(_qm_path CACHE) - find_file(_qm_path "${_l}_${_i}.qm" PATHS "${Qt${_v}_LANG_DIR}" ${_PATHS} NO_DEFAULT_PATH) - if (EXISTS "${_qm_path}") - install(FILES ${_qm_path} DESTINATION "${_DEST}") - #message("qm = \"${_qm_path}\"") - endif() - endforeach() - endforeach() - endif() - endif() - endforeach() -endmacro() - - -macro(qt_get_target _NAME _OUT) - set(${_OUT}) - set(_ver) - foreach(_i ${ARGN}) - foreach(_v ${_QT_VERSIONS_}) - if ("x${_i}" STREQUAL "xQt${_v}") - set(_ver ${_v}) - break() - endif() - endforeach() - if (NOT "x${_ver}" STREQUAL "x") - break() - endif() - endforeach() - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v} AND (("x${_ver}" STREQUAL "x") OR ((NOT "x${_ver}" STREQUAL "x") AND ("x${_ver}" STREQUAL "x${_v}")))) - set(${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - endif() - endforeach() -endmacro() - - -macro(qt_get_targets _NAME _OUT) - set(${_OUT}) - foreach(_v ${_QT_VERSIONS_}) - if (LOCAL_FOUND${_v}) - list(APPEND ${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}}) - endif() - endforeach() -endmacro() - - -macro(qt_generate_export_header _NAME) - qt_get_target(${_NAME} _some_target) - qt_get_target(${_NAME} _targets) - foreach(_t ${_targets}) - set_target_properties(${_t} PROPERTIES DEFINE_SYMBOL ${_NAME}_EXPORTS) - endforeach() - set_target_properties(${_some_target} PROPERTIES DEFINE_SYMBOL ${_NAME}_EXPORTS) - generate_export_header(${_some_target} BASE_NAME "${_NAME}" ${ARGN}) -endmacro() +#[[ + +find_qt([ ...] [Qt4] [Qt5]) + +Find Qt4 or/and Qt5 packages +If Qt4/5 found, set +* Qt<4/5>_ROOT var to Qt root dir +* Qt<4/5>_BIN var to Qt binary dir +* Qt<4/5>_PLUGINS_DIR var to Qt plugins dir +* Qt<4/5>_LANG_DIR var to Qt translations dir + + + + +qt_sources( [NO_DEFAULT] [DIR ] [ ...]) + +Collect all sources, optionally in directory and +Additional filters . By default filter files with regexps +"*.h", "*.hpp", "*.c", "*.cpp", "*.ui", "*.qrc", "*.rc", "*.ts" and "lang/*.ts". +Default filters disabled with option NO_DEFAULT + + + + +qt_wrap( ... [HDRS ] [CPPS ] [QMS ]) + +Prepare sources for compile +Store headers to , all wrapped Qt4 files to _Qt4 and Qt5 files to _Qt5 +version are automatic detected after find_qt() call + + + + +qt_add_executable( [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...]) + +Add executables for founded Qt versions, target names is +All needed Qt includes automatic added to corresponding targets + cant be CPPS variable passed to qt_wrap() or some list or filename + + + + +qt_add_library( [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...]) + +Add library for founded Qt versions, target names is +All needed Qt includes automatic added to corresponding targets + cant be CPPS variable passed to qt_wrap() or some list or filename + + + + +qt_target_link_libraries( ... ...) + +Link targets for founded Qt versions, target names is +All needed Qt libraries automatic added to corresponding targets +if QT_MULTILIB_LIST contains some linking library, to it name automatic +add or individual libname<_SUFFIX_Qt?> + + + + +qt_target_compile_definitions( ...) + +Syntax similar to original "target_compile_definitions()" +Specify compile definitions to use when compiling a given + + + + +qt_target_include_directories( ...) + +Syntax similar to original "target_include_directories()" +Add include directories to a target + + + + +qt_install(...) + +Syntax similar to original "install()" +Install targets for founded Qt versions + +if DESTINATION set to "QtBin" files will be installed +to corresponding Qt binary directory +if DESTINATION set to "QtLang" files will be installed +to corresponding Qt translation directory +if DESTINATION starts with "QtPlugins" files will be installed +to corresponding Qt plugins directory + +Add LANG type for first argument - in this case you should +specify variable name, not variable value! +e.g. "qt_install(LANG my_QM DESTINATION QtLang)" + + + + +qt_install_lang( DESTINATION [PATHS [] [...] ]) + +Search Qt translations for all dependencies +in Qt_LANG_DIR for _LANG languages +and install them to . PATH are additional search paths. +You should use "set_lang()" macro before this action + + + + +qt_get_target( [Qt4 | Qt5]) + +Write real Qt target name to +If Qt4 or Qt5 specified, search for this version, +otherwise returns greatest version + + + + +qt_get_targets( ) + +Write all real Qt target names to + + + + +qt_generate_export_header( ...) + +Call generate_export_header on Qt multitarget + + +]] + + +cmake_policy(SET CMP0011 NEW) # don`t affect includer policies +cmake_policy(SET CMP0020 NEW) # Automatically link Qt executables to qtmain target on Windows +if (POLICY CMP0057) + cmake_policy(SET CMP0057 NEW) # Support if() IN_LIST +endif() +if (POLICY CMP0074) + cmake_policy(SET CMP0074 OLD) # ignore _ROOT variables +endif() +set(__qt_bug_modules "UiTools") + + +set(_QT_VERSIONS_ 4 5) +foreach(_v ${_QT_VERSIONS_}) + if (NOT DEFINED TARGET_SUFFIX_Qt${_v}) + set(TARGET_SUFFIX_Qt${_v} "${_v}") + set(MULTILIB_SUFFIX_Qt${_v} "${_v}") + endif() + set(MOC_INC_Qt${_v}) +endforeach() +if (NOT DEFINED QT_MULTILIB_LIST) + set(QT_MULTILIB_LIST) +endif() +#set(TARGET_SUFFIX_Qt4 "") + + +macro(find_qt) + set(_QCOMP) + foreach(_v ${_QT_VERSIONS_}) + set(_NEED${_v} 0) + set(LOCAL_FOUND${_v} 0) + set(MOC_INC_Qt${_v}) + set(Qt${_v}_INCLUDES) + set(Qt${_v}_LIBRARIES) + set(Qt${_v}_ROOT) + set(Qt${_v}_BIN) + set(Qt${_v}_PLUGINS_DIR) + set(Qt${_v}_LANG_DIR) + endforeach() + set(_NEED_SOME 0) + set(_QUIET) + foreach(_i ${ARGN}) + set(_FOUND_NEED 0) + foreach(_v ${_QT_VERSIONS_}) + if ("x${_i}" STREQUAL "xQt${_v}") + set(_NEED${_v} 1) + set(_NEED_SOME 1) + set(_FOUND_NEED 1) + endif() + if ("x${_i}" STREQUAL "xQUIET") + set(_QUIET QUIET) + endif() + endforeach() + if (NOT _FOUND_NEED) + list(APPEND _QCOMP "${_i}") + endif() + endforeach() + if (NOT _NEED_SOME) + foreach(_v ${_QT_VERSIONS_}) + set(_NEED${_v} 1) + endforeach() + endif() + list(REMOVE_DUPLICATES _QCOMP) + if (_NEED4) + find_package(Qt4 ${_QUIET}) + if (Qt4_FOUND) + set(LOCAL_FOUND4 1) + get_filename_component(Qt4_BIN ${QT_QMAKE_EXECUTABLE} PATH) + set(Qt4_INCLUDES ${QT_INCLUDES}) + foreach(m ${_QCOMP}) + string(TOUPPER "${m}" _um) + #message("${QT_QT${_um}_FOUND}") + if (${QT_QT${_um}_FOUND}) + list(APPEND Qt4_LIBRARIES ${QT_QT${_um}_LIBRARY}) + endif() + endforeach() + set(Qt4_PLUGINS_DIR ${QT_PLUGINS_DIR}) + set(Qt4_LANG_DIR ${Qt4_BIN}/../translations) + set(Qt4_ROOT "${Qt4_BIN}/../") + endif() + endif() + if (_NEED5) + #set(_MSG 1) + #if (Qt5_FOUND) + # set(_MSG 0) + #endif() + find_package(Qt5 COMPONENTS Core LinguistTools UiPlugin Widgets ${_QCOMP} ${_QUIET}) + if (DEFINED ANDROID_PLATFORM) + set(CMAKE_SHARED_MODULE_SUFFIX_CXX ".so") + set(CMAKE_SHARED_LIBRARY_SUFFIX_CXX ".so") + set(CMAKE_SHARED_MODULE_SUFFIX_C ".so") + set(CMAKE_SHARED_LIBRARY_SUFFIX_C ".so") + endif() + if (Qt5_FOUND) + set(LOCAL_FOUND5 1) + set(_Qt5Modules) + foreach(m ${_QCOMP}) + if (${Qt5${m}_FOUND}) + set(__lib ${Qt5${m}_LIBRARIES}) + if (DEFINED ANDROID_PLATFORM) + if (m IN_LIST __qt_bug_modules) + get_target_property(__lib Qt5::${m} LOCATION) + endif() + endif() + list(APPEND _Qt5Modules ${m}) + list(APPEND Qt5_INCLUDES ${Qt5${m}_INCLUDE_DIRS}) + list(APPEND Qt5_LIBRARIES ${__lib}) + endif() + endforeach() + #get_property(_up_dir TARGET Qt5::UiPlugin PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + #message("${_up_dir}") + #if (NOT "x${_up_dir}" STREQUAL "x") + # list(APPEND Qt5_INCLUDES ${_up_dir}) + #endif() + get_target_property(_Qt5_qmake Qt5::qmake LOCATION) + get_filename_component(Qt5_BIN ${_Qt5_qmake} PATH) + foreach(_p ${Qt5Gui_PLUGINS}) + get_target_property(_l ${_p} LOCATION) + get_filename_component(_l ${_l} DIRECTORY) + string(FIND "${_l}" "/" _ind REVERSE) + string(SUBSTRING "${_l}" 0 ${_ind} _l) + set(Qt5_PLUGINS_DIR ${_l}) + #message("Qt5: plugins dir: ${Qt5_PLUGINS_DIR}") + break() + endforeach() + string(FIND "${Qt5_BIN}" "/" _ind REVERSE) + string(SUBSTRING "${Qt5_BIN}" 0 ${_ind} Qt5_ROOT) + if ("x${Qt5_PLUGINS_DIR}" STREQUAL "x") + set(Qt5_PLUGINS_DIR "${Qt5_ROOT}/plugins") + endif() + if (APPLE) + list(APPEND MOC_INC_Qt5 "-F${Qt5_ROOT}/lib") + endif() + set(Qt5_LANG_DIR ${Qt5_BIN}/../translations) + if (NOT _QT5_MSG) + message(STATUS "Found Qt5: ${_Qt5_qmake} (version \"${Qt5_VERSION}\")") + set(_QT5_MSG 1 CACHE BOOL "msg_qt5" FORCE) + #message(STATUS "Found Qt5 modules: ${_Qt5Modules}") + endif() + endif() + endif() + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + foreach(_p ${Qt${_v}_INCLUDES}) + list(APPEND MOC_INC_Qt${_v} "-I${_p}") + #message("${_p}") + endforeach() + endif() + #message("${MOC_INC_Qt${_v}}") + endforeach() + +endmacro() + + +macro(qt_sources OUT) + set(${OUT}) + set(_DIR "") + set(_IS_DIR 0) + set(_NO_DEFAULT 0) + set(_DEFAULT) + set(_REGEXP) + set(_REGEXP_WD) + foreach(_i ${ARGN}) + if (_IS_DIR) + set(_DIR "${_i}") + set(_IS_DIR 0) + elseif ("x${_i}" STREQUAL "xDIR") + set(_IS_DIR 1) + elseif ("x${_i}" STREQUAL "xNO_DEFAULT") + set(_NO_DEFAULT 1) + else() + list(APPEND _REGEXP ${_i}) + endif() + endforeach() + if (NOT "x${_DIR}" STREQUAL "x") + #file(TO_CMAKE_PATH "${_DIR}//" _DIR) + string(REPLACE "\\" "/" _DIR "${_DIR}/") + string(REPLACE "//" "/" _DIR "${_DIR}") + endif() + foreach(_i ${_REGEXP}) + list(APPEND _REGEXP_WD "${_DIR}${_i}") + endforeach() + if (NOT _NO_DEFAULT) + set(_DEFAULT "${_DIR}*.h" "${_DIR}*.hpp" "${_DIR}*.c" "${_DIR}*.cpp" "${_DIR}*.ui" "${_DIR}*.qrc" "${_DIR}*.rc" "${_DIR}*.ts" "${_DIR}lang/*.ts") + endif() + #message("${_DEFAULT}, ${_REGEXP_WD}") + file(GLOB ${OUT} ${_DEFAULT} ${_REGEXP_WD}) +endmacro() + + +macro(qt_wrap) + set(HDR_VAR) + set(CPP_VAR) + set(QM_VAR) + set(_HDR_ARG 0) + set(_CPP_ARG 0) + set(_QM_ARG 0) + set(WAS_HDR_ARG 0) + set(WAS_CPP_ARG 0) + set(WAS_QM_ARG 0) + set(FILE_LIST) + foreach(_i ${ARGN}) + if (_HDR_ARG) + set(HDR_VAR ${_i}) + set(WAS_HDR_ARG 1) + set(_HDR_ARG 0) + elseif (_CPP_ARG) + set(CPP_VAR ${_i}) + set(WAS_CPP_ARG 1) + set(_CPP_ARG 0) + elseif (_QM_ARG) + set(QM_VAR ${_i}) + set(WAS_QM_ARG 1) + set(_QM_ARG 0) + elseif ("x${_i}" STREQUAL "xHDRS") + set(_HDR_ARG 1) + elseif ("x${_i}" STREQUAL "xCPPS") + set(_CPP_ARG 1) + elseif ("x${_i}" STREQUAL "xQMS") + set(_QM_ARG 1) + else() + list(APPEND FILE_LIST "${_i}") + endif() + endforeach() + foreach(_v ${_QT_VERSIONS_}) + set(CPP${_v}_VAR) + set(QM${_v}_VAR) + if (LOCAL_FOUND${_v}) + if (WAS_CPP_ARG) + set(CPP${_v}_VAR ${CPP_VAR}_Qt${_v}) + endif() + if (WAS_QM_ARG) + set(QM${_v}_VAR ${QM_VAR}_Qt${_v}) + endif() + endif() + endforeach() + #message("found 4: ${LOCAL_FOUND4}, 5: ${LOCAL_FOUND5}") + #message("has HRDS: ${WAS_HDR_ARG}: ${HDR_VAR}") + #message("has CPPS4: ${WAS_CPP_ARG}: ${CPP4_VAR}") + #message("has CPPS5: ${WAS_CPP_ARG}: ${CPP5_VAR}") + #message("files: ${FILE_LIST}") + set(H_LIST) + set(CPP_LIST) + set(UI_LIST) + set(RES_LIST) + set(RC_LIST) + set(TS_LIST) + foreach(_i ${FILE_LIST}) + get_filename_component(_EXT "${_i}" EXT) + #message("${_EXT}") + if (NOT ("x${_EXT}" STREQUAL "x")) + if (("x${_EXT}" STREQUAL "x.h") OR ("x${_EXT}" STREQUAL "x.hpp")) + list(APPEND H_LIST "${_i}") + #message("header") + endif() + if (("x${_EXT}" STREQUAL "x.c") OR ("x${_EXT}" STREQUAL "x.cpp") OR ("x${_EXT}" STREQUAL "x.cxx")) + list(APPEND CPP_LIST "${_i}") + #message("source") + endif() + if ("x${_EXT}" STREQUAL "x.ui") + list(APPEND UI_LIST "${_i}") + endif() + if ("x${_EXT}" STREQUAL "x.qrc") + list(APPEND RES_LIST "${_i}") + endif() + if ("x${_EXT}" STREQUAL "x.rc") + list(APPEND RC_LIST "${_i}") + endif() + if ("x${_EXT}" STREQUAL "x.ts") + list(APPEND TS_LIST "${_i}") + endif() + endif() + endforeach() + if (WAS_HDR_ARG) + set(${HDR_VAR}) + list(APPEND ${HDR_VAR} ${H_LIST}) + endif() + set(SRC_CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v} AND WAS_CPP_ARG) + set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR}/qt${_v}) + set(${CPP${_v}_VAR}) + if (WAS_QM_ARG) + set(${QM${_v}_VAR}) + endif() + set(MOCS${_v}) + set(CUIS${_v}) + set(CRES${_v}) + if (${_v} EQUAL 4) + qt4_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt4}) + qt4_wrap_ui(CUIS${_v} ${UI_LIST}) + qt4_add_resources(CRES${_v} ${RES_LIST}) + if (WAS_QM_ARG) + set(${QM${_v}_VAR} "") + qt4_add_translation(${QM${_v}_VAR} ${TS_LIST}) + endif() + elseif (${_v} EQUAL 5) + qt5_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt5}) + qt5_wrap_ui(CUIS${_v} ${UI_LIST}) + qt5_add_resources(CRES${_v} ${RES_LIST}) + if (WAS_QM_ARG) + set(${QM${_v}_VAR} "") + qt5_add_translation(${QM${_v}_VAR} ${TS_LIST}) + endif() + else() + # Qt6 ... + endif() + #message("${${QM${_v}_VAR}}") + list(APPEND ${CPP${_v}_VAR} ${CPP_LIST}) + list(APPEND ${CPP${_v}_VAR} ${RC_LIST}) + list(APPEND ${CPP${_v}_VAR} ${MOCS${_v}}) + list(APPEND ${CPP${_v}_VAR} ${CUIS${_v}}) + list(APPEND ${CPP${_v}_VAR} ${CRES${_v}}) + if (WAS_QM_ARG) + list(APPEND ${CPP${_v}_VAR} ${${QM${_v}_VAR}}) + endif() + #message("${${QM${_v}_VAR}}") + endif() + endforeach() + set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR}) +endmacro() + + +macro(_qt_split_add_args _P _A) + set(${_P}) + set(${_A}) + foreach(_i ${ARGN}) + if (NOT ("x${${_i}_Qt${_v}}" STREQUAL "x")) + list(APPEND ${_A} ${${_i}_Qt${_v}}) + elseif (("x${_i}" STREQUAL "xWIN32") OR + ("x${_i}" STREQUAL "xMACOSX_BUNDLE") OR + ("x${_i}" STREQUAL "xSTATIC") OR + ("x${_i}" STREQUAL "xSHARED") OR + ("x${_i}" STREQUAL "xMODULE") OR + ("x${_i}" STREQUAL "xEXCLUDE_FROM_ALL")) + list(APPEND ${_P} ${_i}) + elseif ("x${${_i}}" STREQUAL "x") + list(APPEND ${_A} ${_i}) + else() + list(APPEND ${_A} ${${_i}}) + endif() + endforeach() +endmacro() + + +macro(__qt_set_defines _NAME _T) + target_compile_definitions(${_T} PRIVATE "__TARGET_NAME__=\"${_NAME}\"") + target_compile_definitions(${_T} PRIVATE "__TARGET_LABEL__=\"${${_NAME}_LABEL}\"") + target_compile_definitions(${_T} PRIVATE "__TARGET_COMPANY__=\"${${_NAME}_COMPANY}\"") + target_compile_definitions(${_T} PRIVATE "__TARGET_VERSION__=\"${${_NAME}_VERSION}\"") +endmacro() + + +macro(qt_add_executable _NAME) + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + _qt_split_add_args(_PREF _ARGS ${ARGN}) + if(APPLE) + set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}") + set(CMAKE_INSTALL_NAME_DIR "@rpath") + else() + if(NOT WIN32) + set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib") + endif() + endif() + set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + add_executable(${_TARGET} ${_PREF} ${_ARGS}) + set(_${_NAME}_is_qt 1) + target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES}) + __qt_set_defines(${_NAME} ${_TARGET}) + + if(APPLE) + set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}") + endif() + # # Apple crosscompiling rpath patch + # if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH) + # foreach(_RP ${CMAKE_INSTALL_RPATH}) + # add_custom_command(TARGET ${_TARGET} POST_BUILD + # COMMAND "${CMAKE_INSTALL_NAME_TOOL}" + # "-add_rpath" "${_RP}" + # "$/$" + # COMMENT "Add to ${_TARGET} rpath \"${_RP}\"") + # endforeach() + # endif() + + #list(APPEND _ALL_TARGETS "${_TARGET}") + #set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) + endif() + endforeach() +endmacro() + + +macro(qt_add_library _NAME) + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + _qt_split_add_args(_PREF _ARGS ${ARGN}) + if(APPLE) + set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}") + set(CMAKE_INSTALL_NAME_DIR "@rpath") + else() + if(NOT WIN32) + set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib") + endif() + endif() + set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + add_library(${_TARGET} ${_PREF} ${_ARGS}) + set(_${_NAME}_is_qt 1) + target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES}) + __qt_set_defines(${_NAME} ${_TARGET}) + #message("add lib: \"${_TARGET}\"") + + if(APPLE) + set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}") + endif() + # # Apple crosscompiling rpath patch + # if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH) + # foreach(_RP ${CMAKE_INSTALL_RPATH}) + # add_custom_command(TARGET ${_TARGET} POST_BUILD + # COMMAND "${CMAKE_INSTALL_NAME_TOOL}" + # "-add_rpath" "${_RP}" + # "$/$" + # COMMENT "Add to ${_TARGET} rpath \"${_RP}\"") + # endforeach() + # endif() + + list(APPEND _ALL_TARGETS "${_TARGET}") + set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) + endif() + endforeach() +endmacro() + + +macro(_qt_multitarget_suffix_ _OUT _IN _v) + string(REPLACE ":" "_" _in_str "${_IN}") + if (NOT "x${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}" STREQUAL "x") + set(${_OUT} "${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}") + else() + set(${_OUT} "${MULTILIB_SUFFIX_Qt${_v}}") + endif() +endmacro() + + +macro(qt_target_link_libraries _NAME) + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + set(_ARGS) + foreach(_i ${ARGN}) + set(_ind -1) + list(FIND QT_MULTILIB_LIST "${_i}" _ind) + if (_ind GREATER -1) + _qt_multitarget_suffix_(_TS ${_i} ${_v}) + #message(STATUS "${_i} in MULTILIB_LIST, suffix = ${_TS}") + list(APPEND _ARGS ${_i}${_TS}) + else() + list(APPEND _ARGS ${_i}) + endif() + endforeach() + target_link_libraries(${_TARGET} ${Qt${_v}_LIBRARIES} ${_ARGS}) + #message("link ${_TARGET}: ${Qt${_v}_LIBRARIES} ${_ARGS}") + endif() + endforeach() +endmacro() + + +macro(qt_target_compile_definitions _NAME) + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + target_compile_definitions(${_TARGET} ${ARGN}) + endif() + endforeach() +endmacro() + + +macro(qt_target_include_directories _NAME) + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + target_include_directories(${_TARGET} ${ARGN}) + endif() + endforeach() +endmacro() + + +macro(qt_install) + set(_prev_inst) + set(__add_args) + #message("command: ${ARGN}") + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + set(_INST_LIST) + set(_IS_TARGET 0) + set(_IS_FILES 0) + set(_IS_DEST 0) + set(_IS_LANG 0) + set(_INVALID 0) + foreach(_i ${ARGN}) + if ("x${_i}" STREQUAL "xQtLang") + set(_IS_LANG 1) + endif() + endforeach() + foreach(_i ${ARGN}) + if (_IS_TARGET) + set(_IS_TARGET 0) + set(__target ${_i}) + if (_${_i}_is_qt) + set(__target ${_i}${TARGET_SUFFIX_Qt${_v}}) + endif() + if (DEFINED ANDROID_PLATFORM) + get_target_property(_TT ${__target} TYPE) + if ("x${_TT}" STREQUAL "xEXECUTABLE") + list(APPEND __add_args EXCLUDE_FROM_ALL) + endif() + endif() + list(APPEND _INST_LIST ${__target}) + elseif (_IS_FILES) + set(_IS_FILES 0) + if (_IS_LANG) + if (("x${${_i}_Qt${_v}}" STREQUAL "x") OR ("x${_i}" STREQUAL "xDESTINATION")) + set(_INVALID 1) + else() + list(APPEND _INST_LIST ${${_i}_Qt${_v}}) + endif() + else() + list(APPEND _INST_LIST ${_i}) + endif() + else() + if (_IS_DEST) + set(_IS_DEST 0) + if ("x${_i}" STREQUAL "xQtBin") + list(APPEND _INST_LIST "${Qt${_v}_BIN}") + elseif ("x${_i}" STREQUAL "xQtLang") + list(APPEND _INST_LIST "${Qt${_v}_LANG_DIR}") + else() + set(_ind -1) + string(FIND "${_i}" "QtPlugins" _ind) + if (_ind GREATER -1) + string(REPLACE "QtPlugins" "${Qt${_v}_PLUGINS_DIR}" _o "${_i}") + list(APPEND _INST_LIST "${_o}") + else() + string(REPLACE "\\" "/" _o "${_i}") + list(APPEND _INST_LIST ${_o}) + endif() + endif() + else() + set(_ii ${_i}) + if ("x${_i}" STREQUAL "xTARGETS") + set(_IS_TARGET 1) + elseif ("x${_i}" STREQUAL "xFILES") + set(_IS_FILES 1) + elseif ("x${_i}" STREQUAL "xDESTINATION") + set(_IS_DEST 1) + elseif ("x${_i}" STREQUAL "xLANG") + set(_IS_FILES 1) + set(_IS_LANG 1) + set(_ii "FILES") + endif() + list(APPEND _INST_LIST ${_ii}) + endif() + endif() + endforeach() + if (NOT _INVALID) + if (NOT ("x${_prev_inst}" STREQUAL "x${_INST_LIST}")) + #message("install: ${_INST_LIST}") + install(${_INST_LIST} ${__add_args}) + set(_prev_inst "${_INST_LIST}") + endif() + endif() + endif() + endforeach() +endmacro() + + +macro(qt_install_lang _NAME) + set(_prev_inst) + #message("command: ${ARGN}") + set(_PATHS) + set(_DEST) + if(CMAKE_CROSSCOMPILING) + list(APPEND _PATHS "${CMAKE_PREFIX_PATH}/lang") + endif() + set(_cur_arg) + set(__args "DESTINATION;PATHS") + foreach(_i ${ARGN}) + if (_i IN_LIST __args) + set(_cur_arg "${_i}") + elseif("${_cur_arg}" STREQUAL "DESTINATION") + set(_DEST "${_i}") + elseif("${_cur_arg}" STREQUAL "PATHS") + list(APPEND _PATHS "${_i}") + endif() + endforeach() + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + set(_target) + if (_${_NAME}_is_qt) + set(_target ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + endif() + get_target_property(_LL ${_target} LINK_LIBRARIES) + foreach (_L ${_LL}) + get_filename_component(_libname "${_L}" NAME_WE) + #message("depend on ${_libname}") + if ("${_libname}" MATCHES "Qt${_v}::.*") + string(SUBSTRING "${_libname}" 5 -1 _libname) + string(TOLOWER "${_libname}" _libname) + #message("qt lib \"${_libname}\"") + list(APPEND _qt_libs qt${_libname}) + else() + if ("${_libname}" MATCHES "lib.*") + string(LENGTH ${_libname} _sl) + math(EXPR _sl ${_sl}-3) + string(SUBSTRING ${_libname} 3 ${_sl} _libname) + endif() + if ("${_libname}" MATCHES "qad_.*${_v}") + string(LENGTH ${_libname} _sl) + math(EXPR _sl ${_sl}-1) + string(SUBSTRING ${_libname} 0 ${_sl} _libname) + #message("qad lib \"${_libname}\"") + list(APPEND _qt_libs ${_libname}) + endif() + endif() + endforeach() + if (NOT "x${_qt_libs}" STREQUAL "x") + list(APPEND _qt_libs "qtbase") + foreach (_i ${${PROJECT_NAME}_LANG}) + foreach (_l ${_qt_libs}) + unset(_qm_path CACHE) + find_file(_qm_path "${_l}_${_i}.qm" PATHS "${Qt${_v}_LANG_DIR}" ${_PATHS} NO_DEFAULT_PATH) + if (EXISTS "${_qm_path}") + install(FILES ${_qm_path} DESTINATION "${_DEST}") + #message("qm = \"${_qm_path}\"") + endif() + endforeach() + endforeach() + endif() + endif() + endforeach() +endmacro() + + +macro(qt_get_target _NAME _OUT) + set(${_OUT}) + set(_ver) + foreach(_i ${ARGN}) + foreach(_v ${_QT_VERSIONS_}) + if ("x${_i}" STREQUAL "xQt${_v}") + set(_ver ${_v}) + break() + endif() + endforeach() + if (NOT "x${_ver}" STREQUAL "x") + break() + endif() + endforeach() + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v} AND (("x${_ver}" STREQUAL "x") OR ((NOT "x${_ver}" STREQUAL "x") AND ("x${_ver}" STREQUAL "x${_v}")))) + set(${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + endif() + endforeach() +endmacro() + + +macro(qt_get_targets _NAME _OUT) + set(${_OUT}) + foreach(_v ${_QT_VERSIONS_}) + if (LOCAL_FOUND${_v}) + list(APPEND ${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}}) + endif() + endforeach() +endmacro() + + +macro(qt_generate_export_header _NAME) + qt_get_target(${_NAME} _some_target) + qt_get_target(${_NAME} _targets) + foreach(_t ${_targets}) + set_target_properties(${_t} PROPERTIES DEFINE_SYMBOL ${_NAME}_EXPORTS) + endforeach() + set_target_properties(${_some_target} PROPERTIES DEFINE_SYMBOL ${_NAME}_EXPORTS) + generate_export_header(${_some_target} BASE_NAME "${_NAME}" ${ARGN}) +endmacro() diff --git a/cmake_android.bat b/cmake_android.bat deleted file mode 100644 index 94d9290..0000000 --- a/cmake_android.bat +++ /dev/null @@ -1,50 +0,0 @@ -@echo off -rem Please add to environment ANDROID_QT5_DIR (path to Qt directory) and ANDROID_NDK_HOME (path to android ndk directory) -rem Execute with Android API version and arch e. g. : #cmake_android.bat 24 arm ../libs -rem Arches: arm, arm64, x86, x86_64 -set _usage_=0 -if [%~1]==[] set _usage_=1 -if [%~2]==[] set _usage_=1 -if [%~3]==[] set _usage_=1 -if %_usage_%==1 ( - echo Usage: cmake_android.bat ^ ^ ^ - echo ^ ^ ^ - number of API ^(e.g. 19^) - echo ^ ^ ^ - architecture ^(arm, arm64, x86, x86_64^) - echo ^ ^ ^ - path to sources - echo. - echo You also have to set next env variables^: - echo ^ ^ ANDROID_QT5_DIR - path to Qt dir, contains subdirs for arch - echo ^ ^ ANDROID_NDK_HOME - path to android ndk directory - exit /b -) -set QARCH= -set AARCH= -set _PLATFORM_=%~1 -if %~2==arm ( - set QARCH=armv7 - set AARCH=armeabi-v7a -) -if %~2==arm64 ( - set QARCH=arm64_v8a - set AARCH=arm64-v8a - if /i %_PLATFORM_% LSS 21 set _PLATFORM_=21 -) -if %~2==x86 ( - set QARCH=x86 - set AARCH=x86 -) -if %~2==x86_64 ( - set QARCH=x86_64 - set AARCH=x86_64 - if /i %_PLATFORM_% LSS 21 set _PLATFORM_=21 -) -rem set Qt5_ROOT=%ANDROID_QT5_DIR%\android_%QARCH%\lib\cmake -set Qt5_ROOT=%ANDROID_QT5_DIR%\lib\cmake -rem set Qt5_DIR=%Qt5_ROOT%\Qt5 -if NOT [%QARCH%]==[] ( - @echo on - cmake_mgw -Wno-dev -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK_HOME%\build\cmake\android.toolchain.cmake -DANDROID_STL=c++_shared -DANDROID_PLATFORM=android-%_PLATFORM_% -DANDROID_ABI=%AARCH% -DICU=0 -DQt4=0 -DQt5=1 -DQGLVIEW=0 -DQGLENGINE=0 -DQt5_DIR=%Qt5_ROOT%\Qt5 -DQt5LinguistTools_DIR=%Qt5_ROOT%\Qt5LinguistTools -DQt5UiPlugin_DIR=%Qt5_ROOT%\Qt5UiPlugin -DQt5UiTools_DIR=%Qt5_ROOT%\Qt5UiTools -DQt5Widgets_DIR=%Qt5_ROOT%\Qt5Widgets -DQt5Core_DIR=%Qt5_ROOT%\Qt5Core -DQt5Gui_DIR=%Qt5_ROOT%\Qt5Gui -DQt5Sql_DIR=%Qt5_ROOT%\Qt5Sql -DQt5OpenGL_DIR=%Qt5_ROOT%\Qt5OpenGL -DQt5PrintSupport_DIR=%Qt5_ROOT%\Qt5PrintSupport -DQt5Script_DIR=%Qt5_ROOT%\Qt5Script -DQt5Positioning_DIR=%Qt5_ROOT%\Qt5Positioning -DQt5Network_DIR=%Qt5_ROOT%\Qt5Network -DQt5Qml_DIR=%Qt5_ROOT%\Qt5Qml -DQt5Quick_DIR=%Qt5_ROOT%\Qt5Quick -DQt5QuickWidgets_DIR=%Qt5_ROOT%\Qt5QuickWidgets -DQt5QmlModels_DIR=%Qt5_ROOT%\Qt5QmlModels -DQt5AndroidExtras_DIR=%Qt5_ROOT%\Qt5AndroidExtras %~3 %~4 %~5 %~6 -) else ( - @echo on - cmake_mgw -Wno-dev -DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK_HOME%\build\cmake\android.toolchain.cmake -DANDROID_STL=c++_shared -DANDROID_PLATFORM=android-%_PLATFORM_% -DANDROID_ABI=%AARCH% -DICU=0 -DQt4=0 -DQt5=0 -DQGLVIEW=0 %~3 %~4 %~5 %~6 -) diff --git a/cmake_android.sh b/cmake_android.sh deleted file mode 100755 index 9b7e609..0000000 --- a/cmake_android.sh +++ /dev/null @@ -1,3 +0,0 @@ -export SDK_DIR=/usr/lib/android-sdk -export PREFIX=/soft/android -rm -rf * && cmake -DCMAKE_TOOLCHAIN_FILE=${SDK_DIR}/ndk-bundle/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=android-21 -DQt4=0 -DQt5=1 -DQt5_DIR=${PREFIX}/qt/lib/cmake/Qt5 ../libs diff --git a/docker/android-libs/Dockerfile b/docker/android-libs/Dockerfile deleted file mode 100644 index e94bc3f..0000000 --- a/docker/android-libs/Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -ARG DOCKER_PREFIX=wapmobil/ -FROM ${DOCKER_PREFIX}android - -ARG LIBS_BUILD_NUMBER=9999 -ARG JOBS_COUNT=4 -ENV PATH=/opt/cmake/bin:$PATH -ENV ANDROID_HOME=/usr/lib/android-sdk -ENV ANDROID_NDK_HOME=${ANDROID_HOME}/ndk-bundle -ENV ANDROID_TOOLCHAIN=${ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake -ENV NDK_PLATFORM="android-21" - -WORKDIR /soft -RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git - -WORKDIR /soft/libs_build_host -RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ - && make install -j${JOBS_COUNT} \ - && rm -rf * \ - && ldconfig - -WORKDIR /soft/libs_build_anroid -ENV _ANDROID_TOOLCHAIN=/usr/lib/android-sdk/ndk-bundle/build/cmake/android.toolchain.cmake - -ENV _CUR_ABI=armeabi-v7a -RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ - && make install -j${JOBS_COUNT} && rm -rf * - -ENV _CUR_ABI=arm64-v8a -WORKDIR /soft/libs_build_android_${_CUR_ABI} -RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ - && make install -j${JOBS_COUNT} && rm -rf * - -ENV _CUR_ABI=x86 -WORKDIR /soft/libs_build_android_${_CUR_ABI} -RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ - && make install -j${JOBS_COUNT} && rm -rf * - -ENV _CUR_ABI=x86_64 -WORKDIR /soft/libs_build_android_${_CUR_ABI} -RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/android/${_CUR_ABI} -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=${_ANDROID_TOOLCHAIN} -DQt5_DIR=/soft/android/qt/lib/cmake/Qt5 -DANDROID_PLATFORM=${NDK_PLATFORM} -DANDROID_ABI=${_CUR_ABI} ../libs/ \ - && make install -j${JOBS_COUNT} && rm -rf * - -WORKDIR /soft/src diff --git a/docker/debian-libs/Dockerfile b/docker/debian-libs/Dockerfile deleted file mode 100644 index 0a85c7f..0000000 --- a/docker/debian-libs/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -ARG DOCKER_PREFIX=wapmobil/ -FROM ${DOCKER_PREFIX}debian - -ARG LIBS_BUILD_NUMBER=9999 -ARG JOBS_COUNT=4 -ENV PATH=/opt/cmake/bin:$PATH - -WORKDIR /soft -RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git - -WORKDIR /soft/libs_build_debian -RUN cmake -DICU=0 -DLIB=1 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ - && make install -j${JOBS_COUNT} \ - && rm -rf * \ - && ldconfig - -WORKDIR /soft/src diff --git a/docker/osx-libs/Dockerfile b/docker/osx-libs/Dockerfile deleted file mode 100644 index 5a496e4..0000000 --- a/docker/osx-libs/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -ARG DOCKER_PREFIX=wapmobil/ -FROM ${DOCKER_PREFIX}osx - -ARG LIBS_BUILD_NUMBER=9999 -ARG JOBS_COUNT=4 -ENV PATH=/soft/osxcross/target/bin:/opt/cmake/bin:$PATH - -WORKDIR /soft -RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git - -WORKDIR /soft/libs_build_host -RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ - && make install -j${JOBS_COUNT} \ - && rm -rf * \ - && ldconfig - -WORKDIR /soft/libs_build_osx -RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/osx -DICU=0 -DLIB=0 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-Darwin.cmake ../libs/ \ - && make install -j${JOBS_COUNT} && rm -rf * - -WORKDIR /soft/src diff --git a/docker/pi-libs/Dockerfile b/docker/pi-libs/Dockerfile deleted file mode 100644 index 666e20c..0000000 --- a/docker/pi-libs/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -ARG DOCKER_PREFIX=wapmobil/ -FROM ${DOCKER_PREFIX}pi - -ARG LIBS_BUILD_NUMBER=9999 -ARG JOBS_COUNT=4 -ENV PATH=/opt/cmake/bin:$PATH - -WORKDIR /soft -RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git - -WORKDIR /soft/libs_build_host -RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ - && make install -j${JOBS_COUNT} \ - && rm -rf * \ - && ldconfig - -WORKDIR /soft/libs_build_pi -RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/pi/usr -DICU=0 -DLIB=0 -DQGLENGINE=0 -DQGLVIEW=0 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-RPi.cmake ../libs/ \ - && make install -j${JOBS_COUNT} && rm -rf * - -WORKDIR /soft/src diff --git a/docker/windows-libs/Dockerfile b/docker/windows-libs/Dockerfile deleted file mode 100644 index 82be301..0000000 --- a/docker/windows-libs/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -ARG DOCKER_PREFIX=wapmobil/ -FROM ${DOCKER_PREFIX}windows - -ARG LIBS_BUILD_NUMBER=9999 -ARG JOBS_COUNT=4 -ENV PATH=/opt/cmake/bin:$PATH - -WORKDIR /soft -RUN git clone -b release --single-branch --depth 1 --recursive https://git.shs.tools/SHS/libs.git - -WORKDIR /soft/libs_build_host -RUN cmake -DICU=0 -DCROSSTOOLS=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} ../libs \ - && make install -j${JOBS_COUNT} \ - && rm -rf * \ - && ldconfig - -WORKDIR /soft/libs_build_windows -RUN cmake -DCMAKE_INSTALL_PREFIX=/soft/windows -DICU=0 -DLIB=0 -DQGLENGINE=1 -DQGLVIEW=1 -DBUILD_NUMBER=${LIBS_BUILD_NUMBER} -DCMAKE_TOOLCHAIN_FILE=/soft/toolchain-Windows.cmake ../libs/ \ - && make install -j${JOBS_COUNT} && rm -rf * - -WORKDIR /soft/src diff --git a/qad/icons/align-bottom-center.png b/icons/align-bottom-center.png similarity index 100% rename from qad/icons/align-bottom-center.png rename to icons/align-bottom-center.png diff --git a/qad/icons/align-bottom-left.png b/icons/align-bottom-left.png similarity index 100% rename from qad/icons/align-bottom-left.png rename to icons/align-bottom-left.png diff --git a/qad/icons/align-bottom-right.png b/icons/align-bottom-right.png similarity index 100% rename from qad/icons/align-bottom-right.png rename to icons/align-bottom-right.png diff --git a/qad/icons/align-center-center.png b/icons/align-center-center.png similarity index 100% rename from qad/icons/align-center-center.png rename to icons/align-center-center.png diff --git a/qad/icons/align-center-left.png b/icons/align-center-left.png similarity index 100% rename from qad/icons/align-center-left.png rename to icons/align-center-left.png diff --git a/qad/icons/align-center-right.png b/icons/align-center-right.png similarity index 100% rename from qad/icons/align-center-right.png rename to icons/align-center-right.png diff --git a/qad/icons/align-hor.png b/icons/align-hor.png similarity index 100% rename from qad/icons/align-hor.png rename to icons/align-hor.png diff --git a/qad/icons/align-top-center.png b/icons/align-top-center.png similarity index 100% rename from qad/icons/align-top-center.png rename to icons/align-top-center.png diff --git a/qad/icons/align-top-left.png b/icons/align-top-left.png similarity index 100% rename from qad/icons/align-top-left.png rename to icons/align-top-left.png diff --git a/qad/icons/align-top-right.png b/icons/align-top-right.png similarity index 100% rename from qad/icons/align-top-right.png rename to icons/align-top-right.png diff --git a/qad/icons/align-ver.png b/icons/align-ver.png similarity index 100% rename from qad/icons/align-ver.png rename to icons/align-ver.png diff --git a/kx_utils/icons/alpha.png b/icons/alpha.png similarity index 100% rename from kx_utils/icons/alpha.png rename to icons/alpha.png diff --git a/qad/icons/application-exit.png b/icons/application-exit.png similarity index 100% rename from qad/icons/application-exit.png rename to icons/application-exit.png diff --git a/qad/icons/archive-extract.png b/icons/archive-extract.png similarity index 100% rename from qad/icons/archive-extract.png rename to icons/archive-extract.png diff --git a/qad/icons/archive-insert-directory.png b/icons/archive-insert-directory.png similarity index 100% rename from qad/icons/archive-insert-directory.png rename to icons/archive-insert-directory.png diff --git a/qad/icons/archive-insert.png b/icons/archive-insert.png similarity index 100% rename from qad/icons/archive-insert.png rename to icons/archive-insert.png diff --git a/qad/icons/arrow-down.png b/icons/arrow-down.png similarity index 100% rename from qad/icons/arrow-down.png rename to icons/arrow-down.png diff --git a/qad/icons/arrow-up.png b/icons/arrow-up.png similarity index 100% rename from qad/icons/arrow-up.png rename to icons/arrow-up.png diff --git a/qad/icons/axis_x.png b/icons/axis_x.png similarity index 100% rename from qad/icons/axis_x.png rename to icons/axis_x.png diff --git a/qad/icons/axis_y.png b/icons/axis_y.png similarity index 100% rename from qad/icons/axis_y.png rename to icons/axis_y.png diff --git a/qad/icons/blockview.png b/icons/blockview.png similarity index 100% rename from qad/icons/blockview.png rename to icons/blockview.png diff --git a/qad/icons/blockview.xcf b/icons/blockview.xcf similarity index 100% rename from qad/icons/blockview.xcf rename to icons/blockview.xcf diff --git a/qad/icons/border-line.png b/icons/border-line.png similarity index 100% rename from qad/icons/border-line.png rename to icons/border-line.png diff --git a/qad/icons/button.png b/icons/button.png similarity index 100% rename from qad/icons/button.png rename to icons/button.png diff --git a/qad/icons/case-sensitive.png b/icons/case-sensitive.png similarity index 100% rename from qad/icons/case-sensitive.png rename to icons/case-sensitive.png diff --git a/qad/icons/chardialog.png b/icons/chardialog.png similarity index 100% rename from qad/icons/chardialog.png rename to icons/chardialog.png diff --git a/qad/icons/checkbox-unchecked.png b/icons/checkbox-unchecked.png similarity index 100% rename from qad/icons/checkbox-unchecked.png rename to icons/checkbox-unchecked.png diff --git a/qad/icons/checkbox.png b/icons/checkbox.png similarity index 100% rename from qad/icons/checkbox.png rename to icons/checkbox.png diff --git a/qad/icons/clear-history.png b/icons/clear-history.png similarity index 100% rename from qad/icons/clear-history.png rename to icons/clear-history.png diff --git a/qad/icons/clineedit.png b/icons/clineedit.png similarity index 100% rename from qad/icons/clineedit.png rename to icons/clineedit.png diff --git a/qad/icons/code-error.png b/icons/code-error.png similarity index 100% rename from qad/icons/code-error.png rename to icons/code-error.png diff --git a/qad/icons/code-parents.png b/icons/code-parents.png similarity index 100% rename from qad/icons/code-parents.png rename to icons/code-parents.png diff --git a/qad/icons/code-struct.png b/icons/code-struct.png similarity index 100% rename from qad/icons/code-struct.png rename to icons/code-struct.png diff --git a/qad/icons/code-union.png b/icons/code-union.png similarity index 100% rename from qad/icons/code-union.png rename to icons/code-union.png diff --git a/qad/icons/code-variable.png b/icons/code-variable.png similarity index 100% rename from qad/icons/code-variable.png rename to icons/code-variable.png diff --git a/qad/icons/code-word.png b/icons/code-word.png similarity index 100% rename from qad/icons/code-word.png rename to icons/code-word.png diff --git a/qad/icons/colorbutton.png b/icons/colorbutton.png similarity index 100% rename from qad/icons/colorbutton.png rename to icons/colorbutton.png diff --git a/qad/icons/configure.png b/icons/configure.png similarity index 100% rename from qad/icons/configure.png rename to icons/configure.png diff --git a/qad/icons/configure_16.png b/icons/configure_16.png similarity index 100% rename from qad/icons/configure_16.png rename to icons/configure_16.png diff --git a/qad/icons/database.png b/icons/database.png similarity index 100% rename from qad/icons/database.png rename to icons/database.png diff --git a/qad/icons/dialog-cancel.png b/icons/dialog-cancel.png similarity index 100% rename from qad/icons/dialog-cancel.png rename to icons/dialog-cancel.png diff --git a/qad/icons/dialog-close.png b/icons/dialog-close.png similarity index 100% rename from qad/icons/dialog-close.png rename to icons/dialog-close.png diff --git a/qad/icons/dialog-information.png b/icons/dialog-information.png similarity index 100% rename from qad/icons/dialog-information.png rename to icons/dialog-information.png diff --git a/qad/icons/dialog-ok-apply.png b/icons/dialog-ok-apply.png similarity index 100% rename from qad/icons/dialog-ok-apply.png rename to icons/dialog-ok-apply.png diff --git a/qad/icons/dialog-warning.png b/icons/dialog-warning.png similarity index 100% rename from qad/icons/dialog-warning.png rename to icons/dialog-warning.png diff --git a/qad/icons/document-close.png b/icons/document-close.png similarity index 100% rename from qad/icons/document-close.png rename to icons/document-close.png diff --git a/qad/icons/document-edit.png b/icons/document-edit.png similarity index 100% rename from qad/icons/document-edit.png rename to icons/document-edit.png diff --git a/qad/icons/document-new.png b/icons/document-new.png similarity index 100% rename from qad/icons/document-new.png rename to icons/document-new.png diff --git a/qad/icons/document-open-recent.png b/icons/document-open-recent.png similarity index 100% rename from qad/icons/document-open-recent.png rename to icons/document-open-recent.png diff --git a/qad/icons/document-open.png b/icons/document-open.png similarity index 100% rename from qad/icons/document-open.png rename to icons/document-open.png diff --git a/qad/icons/document-open_16.png b/icons/document-open_16.png similarity index 100% rename from qad/icons/document-open_16.png rename to icons/document-open_16.png diff --git a/qad/icons/document-print.png b/icons/document-print.png similarity index 100% rename from qad/icons/document-print.png rename to icons/document-print.png diff --git a/qad/icons/document-revert.png b/icons/document-revert.png similarity index 100% rename from qad/icons/document-revert.png rename to icons/document-revert.png diff --git a/qad/icons/document-save-all.png b/icons/document-save-all.png similarity index 100% rename from qad/icons/document-save-all.png rename to icons/document-save-all.png diff --git a/qad/icons/document-save-as.png b/icons/document-save-as.png similarity index 100% rename from qad/icons/document-save-as.png rename to icons/document-save-as.png diff --git a/qad/icons/document-save.png b/icons/document-save.png similarity index 100% rename from qad/icons/document-save.png rename to icons/document-save.png diff --git a/qad/icons/draw-ellipse.png b/icons/draw-ellipse.png similarity index 100% rename from qad/icons/draw-ellipse.png rename to icons/draw-ellipse.png diff --git a/qad/icons/draw-line.png b/icons/draw-line.png similarity index 100% rename from qad/icons/draw-line.png rename to icons/draw-line.png diff --git a/qad/icons/draw-rectangle.png b/icons/draw-rectangle.png similarity index 100% rename from qad/icons/draw-rectangle.png rename to icons/draw-rectangle.png diff --git a/qad/icons/draw-text.png b/icons/draw-text.png similarity index 100% rename from qad/icons/draw-text.png rename to icons/draw-text.png diff --git a/qad/icons/ecombobox.png b/icons/ecombobox.png similarity index 100% rename from qad/icons/ecombobox.png rename to icons/ecombobox.png diff --git a/qad/icons/edit-clear-locationbar-rtl.png b/icons/edit-clear-locationbar-rtl.png similarity index 100% rename from qad/icons/edit-clear-locationbar-rtl.png rename to icons/edit-clear-locationbar-rtl.png diff --git a/qad/icons/edit-clear.png b/icons/edit-clear.png similarity index 100% rename from qad/icons/edit-clear.png rename to icons/edit-clear.png diff --git a/qad/icons/edit-copy.png b/icons/edit-copy.png similarity index 100% rename from qad/icons/edit-copy.png rename to icons/edit-copy.png diff --git a/qad/icons/edit-delete.png b/icons/edit-delete.png similarity index 100% rename from qad/icons/edit-delete.png rename to icons/edit-delete.png diff --git a/project_fs/icons/edit-find.png b/icons/edit-find.png similarity index 100% rename from project_fs/icons/edit-find.png rename to icons/edit-find.png diff --git a/qad/icons/edit-find_16.png b/icons/edit-find_16.png similarity index 100% rename from qad/icons/edit-find_16.png rename to icons/edit-find_16.png diff --git a/qad/icons/edit-guides.png b/icons/edit-guides.png similarity index 100% rename from qad/icons/edit-guides.png rename to icons/edit-guides.png diff --git a/qad/icons/edit-paste.png b/icons/edit-paste.png similarity index 100% rename from qad/icons/edit-paste.png rename to icons/edit-paste.png diff --git a/qad/icons/edit-redo.png b/icons/edit-redo.png similarity index 100% rename from qad/icons/edit-redo.png rename to icons/edit-redo.png diff --git a/qad/icons/edit-table-insert-row-below.png b/icons/edit-table-insert-row-below.png similarity index 100% rename from qad/icons/edit-table-insert-row-below.png rename to icons/edit-table-insert-row-below.png diff --git a/qad/icons/edit-undo.png b/icons/edit-undo.png similarity index 100% rename from qad/icons/edit-undo.png rename to icons/edit-undo.png diff --git a/qad/icons/edockwidget.png b/icons/edockwidget.png similarity index 100% rename from qad/icons/edockwidget.png rename to icons/edockwidget.png diff --git a/qad/icons/etabwidget.png b/icons/etabwidget.png similarity index 100% rename from qad/icons/etabwidget.png rename to icons/etabwidget.png diff --git a/qad/icons/evalspinbox.png b/icons/evalspinbox.png similarity index 100% rename from qad/icons/evalspinbox.png rename to icons/evalspinbox.png diff --git a/qad/icons/expand_s_x.png b/icons/expand_s_x.png similarity index 100% rename from qad/icons/expand_s_x.png rename to icons/expand_s_x.png diff --git a/qad/icons/expand_s_y.png b/icons/expand_s_y.png similarity index 100% rename from qad/icons/expand_s_y.png rename to icons/expand_s_y.png diff --git a/qad/icons/expand_x.png b/icons/expand_x.png similarity index 100% rename from qad/icons/expand_x.png rename to icons/expand_x.png diff --git a/qad/icons/expand_y.png b/icons/expand_y.png similarity index 100% rename from qad/icons/expand_y.png rename to icons/expand_y.png diff --git a/qad/icons/f1.png b/icons/f1.png similarity index 100% rename from qad/icons/f1.png rename to icons/f1.png diff --git a/qad/icons/format-fill-color.png b/icons/format-fill-color.png similarity index 100% rename from qad/icons/format-fill-color.png rename to icons/format-fill-color.png diff --git a/qad/icons/format-stroke-color.png b/icons/format-stroke-color.png similarity index 100% rename from qad/icons/format-stroke-color.png rename to icons/format-stroke-color.png diff --git a/qad/icons/format-text-subscript.png b/icons/format-text-subscript.png similarity index 100% rename from qad/icons/format-text-subscript.png rename to icons/format-text-subscript.png diff --git a/qad/icons/games-solve.png b/icons/games-solve.png similarity index 100% rename from qad/icons/games-solve.png rename to icons/games-solve.png diff --git a/qad/icons/go-next.png b/icons/go-next.png similarity index 100% rename from qad/icons/go-next.png rename to icons/go-next.png diff --git a/qad/icons/go-previous.png b/icons/go-previous.png similarity index 100% rename from qad/icons/go-previous.png rename to icons/go-previous.png diff --git a/qad/icons/graphic.png b/icons/graphic.png similarity index 100% rename from qad/icons/graphic.png rename to icons/graphic.png diff --git a/qad/icons/graphics.png b/icons/graphics.png similarity index 100% rename from qad/icons/graphics.png rename to icons/graphics.png diff --git a/qad/icons/historyview.png b/icons/historyview.png similarity index 100% rename from qad/icons/historyview.png rename to icons/historyview.png diff --git a/qad/icons/icons.xcf b/icons/icons.xcf similarity index 100% rename from qad/icons/icons.xcf rename to icons/icons.xcf diff --git a/kx_utils/icons/item-add.png b/icons/item-add.png similarity index 100% rename from kx_utils/icons/item-add.png rename to icons/item-add.png diff --git a/kx_utils/icons/item.png b/icons/item.png similarity index 100% rename from kx_utils/icons/item.png rename to icons/item.png diff --git a/qad/icons/lastmoves.png b/icons/lastmoves.png similarity index 100% rename from qad/icons/lastmoves.png rename to icons/lastmoves.png diff --git a/qad/icons/layer-visible-off.png b/icons/layer-visible-off.png similarity index 100% rename from qad/icons/layer-visible-off.png rename to icons/layer-visible-off.png diff --git a/qad/icons/layer-visible-on.png b/icons/layer-visible-on.png similarity index 100% rename from qad/icons/layer-visible-on.png rename to icons/layer-visible-on.png diff --git a/qad/icons/led_3.png b/icons/led_3.png similarity index 100% rename from qad/icons/led_3.png rename to icons/led_3.png diff --git a/qad/icons/led_gray.png b/icons/led_gray.png similarity index 100% rename from qad/icons/led_gray.png rename to icons/led_gray.png diff --git a/qad/icons/led_off.png b/icons/led_off.png similarity index 100% rename from qad/icons/led_off.png rename to icons/led_off.png diff --git a/qad/icons/led_on.png b/icons/led_on.png similarity index 100% rename from qad/icons/led_on.png rename to icons/led_on.png diff --git a/qad/icons/legend.png b/icons/legend.png similarity index 100% rename from qad/icons/legend.png rename to icons/legend.png diff --git a/qad/icons/list-add.png b/icons/list-add.png similarity index 100% rename from qad/icons/list-add.png rename to icons/list-add.png diff --git a/qad/icons/list-remove.png b/icons/list-remove.png similarity index 100% rename from qad/icons/list-remove.png rename to icons/list-remove.png diff --git a/qad/icons/log_parser.png b/icons/log_parser.png similarity index 100% rename from qad/icons/log_parser.png rename to icons/log_parser.png diff --git a/qad/icons/logview.png b/icons/logview.png similarity index 100% rename from qad/icons/logview.png rename to icons/logview.png diff --git a/qad/icons/mail.png b/icons/mail.png similarity index 100% rename from qad/icons/mail.png rename to icons/mail.png diff --git a/qad/icons/media-playback-pause.png b/icons/media-playback-pause.png similarity index 100% rename from qad/icons/media-playback-pause.png rename to icons/media-playback-pause.png diff --git a/qad/icons/media-playback-start.png b/icons/media-playback-start.png similarity index 100% rename from qad/icons/media-playback-start.png rename to icons/media-playback-start.png diff --git a/qad/icons/media-playback-stop.png b/icons/media-playback-stop.png similarity index 100% rename from qad/icons/media-playback-stop.png rename to icons/media-playback-stop.png diff --git a/qad/icons/media-record.png b/icons/media-record.png similarity index 100% rename from qad/icons/media-record.png rename to icons/media-record.png diff --git a/qad/icons/media-skip-forward.png b/icons/media-skip-forward.png similarity index 100% rename from qad/icons/media-skip-forward.png rename to icons/media-skip-forward.png diff --git a/kx_utils/icons/node-add.png b/icons/node-add.png similarity index 100% rename from kx_utils/icons/node-add.png rename to icons/node-add.png diff --git a/kx_utils/icons/node.png b/icons/node.png similarity index 100% rename from kx_utils/icons/node.png rename to icons/node.png diff --git a/qad/icons/pause-back.png b/icons/pause-back.png similarity index 100% rename from qad/icons/pause-back.png rename to icons/pause-back.png diff --git a/qad/icons/pause-front.png b/icons/pause-front.png similarity index 100% rename from qad/icons/pause-front.png rename to icons/pause-front.png diff --git a/qad/icons/qcodeedit.png b/icons/qcodeedit.png similarity index 100% rename from qad/icons/qcodeedit.png rename to icons/qcodeedit.png diff --git a/qad/icons/qpiconsole.png b/icons/qpiconsole.png similarity index 100% rename from qad/icons/qpiconsole.png rename to icons/qpiconsole.png diff --git a/qad/icons/qt.png b/icons/qt.png similarity index 100% rename from qad/icons/qt.png rename to icons/qt.png diff --git a/qad/icons/quickopen.png b/icons/quickopen.png similarity index 100% rename from qad/icons/quickopen.png rename to icons/quickopen.png diff --git a/qad/icons/qvariantedit.png b/icons/qvariantedit.png similarity index 100% rename from qad/icons/qvariantedit.png rename to icons/qvariantedit.png diff --git a/qad/icons/scroll_spin.png b/icons/scroll_spin.png similarity index 100% rename from qad/icons/scroll_spin.png rename to icons/scroll_spin.png diff --git a/qad/icons/select-all.png b/icons/select-all.png similarity index 100% rename from qad/icons/select-all.png rename to icons/select-all.png diff --git a/qad/icons/select-none.png b/icons/select-none.png similarity index 100% rename from qad/icons/select-none.png rename to icons/select-none.png diff --git a/qad/icons/spinslider.png b/icons/spinslider.png similarity index 100% rename from qad/icons/spinslider.png rename to icons/spinslider.png diff --git a/qad/icons/sql_table.png b/icons/sql_table.png similarity index 100% rename from qad/icons/sql_table.png rename to icons/sql_table.png diff --git a/qad/icons/tools-wizard.png b/icons/tools-wizard.png similarity index 100% rename from qad/icons/tools-wizard.png rename to icons/tools-wizard.png diff --git a/qad/icons/touchbuttframe.png b/icons/touchbuttframe.png similarity index 100% rename from qad/icons/touchbuttframe.png rename to icons/touchbuttframe.png diff --git a/qad/icons/touchbutton.png b/icons/touchbutton.png similarity index 100% rename from qad/icons/touchbutton.png rename to icons/touchbutton.png diff --git a/qad/icons/touchslider.png b/icons/touchslider.png similarity index 100% rename from qad/icons/touchslider.png rename to icons/touchslider.png diff --git a/qad/icons/transform-move.png b/icons/transform-move.png similarity index 100% rename from qad/icons/transform-move.png rename to icons/transform-move.png diff --git a/qad/icons/variable-add.png b/icons/variable-add.png similarity index 100% rename from qad/icons/variable-add.png rename to icons/variable-add.png diff --git a/qad/icons/variable-copy.png b/icons/variable-copy.png similarity index 100% rename from qad/icons/variable-copy.png rename to icons/variable-copy.png diff --git a/qad/icons/variable-edit.png b/icons/variable-edit.png similarity index 100% rename from qad/icons/variable-edit.png rename to icons/variable-edit.png diff --git a/qad/icons/variable-remove.png b/icons/variable-remove.png similarity index 100% rename from qad/icons/variable-remove.png rename to icons/variable-remove.png diff --git a/qad/icons/view-autofit.png b/icons/view-autofit.png similarity index 100% rename from qad/icons/view-autofit.png rename to icons/view-autofit.png diff --git a/qad/icons/view-fullscreen.png b/icons/view-fullscreen.png similarity index 100% rename from qad/icons/view-fullscreen.png rename to icons/view-fullscreen.png diff --git a/qad/icons/view-grid.png b/icons/view-grid.png similarity index 100% rename from qad/icons/view-grid.png rename to icons/view-grid.png diff --git a/qad/icons/view-preview.png b/icons/view-preview.png similarity index 100% rename from qad/icons/view-preview.png rename to icons/view-preview.png diff --git a/qad/icons/view-refresh.png b/icons/view-refresh.png similarity index 100% rename from qad/icons/view-refresh.png rename to icons/view-refresh.png diff --git a/qad/icons/z-bottom.png b/icons/z-bottom.png similarity index 100% rename from qad/icons/z-bottom.png rename to icons/z-bottom.png diff --git a/qad/icons/z-down.png b/icons/z-down.png similarity index 100% rename from qad/icons/z-down.png rename to icons/z-down.png diff --git a/qad/icons/z-top.png b/icons/z-top.png similarity index 100% rename from qad/icons/z-top.png rename to icons/z-top.png diff --git a/qad/icons/z-up.png b/icons/z-up.png similarity index 100% rename from qad/icons/z-up.png rename to icons/z-up.png diff --git a/qad/icons/zoom-draw.png b/icons/zoom-draw.png similarity index 100% rename from qad/icons/zoom-draw.png rename to icons/zoom-draw.png diff --git a/qad/icons/zoom-fit-best.png b/icons/zoom-fit-best.png similarity index 100% rename from qad/icons/zoom-fit-best.png rename to icons/zoom-fit-best.png diff --git a/qad/icons/zoom-in.png b/icons/zoom-in.png similarity index 100% rename from qad/icons/zoom-in.png rename to icons/zoom-in.png diff --git a/qad/icons/zoom-original.png b/icons/zoom-original.png similarity index 100% rename from qad/icons/zoom-original.png rename to icons/zoom-original.png diff --git a/qad/icons/zoom-out.png b/icons/zoom-out.png similarity index 100% rename from qad/icons/zoom-out.png rename to icons/zoom-out.png diff --git a/qad/icons/zoom-range.png b/icons/zoom-range.png similarity index 100% rename from qad/icons/zoom-range.png rename to icons/zoom-range.png diff --git a/qad/icons/zoom-rect.png b/icons/zoom-rect.png similarity index 100% rename from qad/icons/zoom-rect.png rename to icons/zoom-rect.png diff --git a/qad/icons/zoom-select.png b/icons/zoom-select.png similarity index 100% rename from qad/icons/zoom-select.png rename to icons/zoom-select.png diff --git a/kx_utils/CMakeLists.txt b/kx_utils/CMakeLists.txt deleted file mode 100644 index 80da37a..0000000 --- a/kx_utils/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -project(kx_utils) -if (POLICY CMP0017) - cmake_policy(SET CMP0017 NEW) -endif() -if (NOT LIBPROJECT) - find_package(PIP REQUIRED) -endif () -if (MINGW) - find_package(MinGW REQUIRED) -endif() -include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES}) -set(KX_PULT_NAME "kx_pult") -option(KX_PULT "Build ${KX_PULT_NAME}" 1) -option(LIB "System install" 1) -option(DEBUG "Build with -g3" 0) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall") -if (DEBUG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") -endif() -set(CPPS_UTILS "kx_coeffs.cpp" "piprotocol.cpp") -set(HDRS_UTILS "kx_coeffs.h" "kx_protocol_x.h" "kx_protocol_c.h" "piprotocol.h") -if (DEFINED ENV{QNX_HOST}) - add_library(${PROJECT_NAME} STATIC ${CPPS_UTILS}) -else() - add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS}) -endif() -target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY}) -message(STATUS "Building ${PROJECT_NAME}") -if (NOT DEFINED ENV{QNX_HOST}) - if (KX_PULT) - find_package(Qt4 REQUIRED) - find_package(QAD REQUIRED) - find_package(OpenGL REQUIRED) - include_directories(${QT_INCLUDES} ${QAD_INCLUDES}) - set(CPPS "kx_pult.cpp" "kx_pult.h" "kx_pult.ui" "main_kx_pult.cpp") - set(MOCS "kx_pult.h") - file(GLOB UIS "*.ui") - file(GLOB RES "*.qrc") - qt4_wrap_cpp(CMOCS ${MOCS} OPTIONS -nw) - qt4_wrap_ui(CUIS ${UIS}) - qt4_add_resources(RESS ${RES}) - add_executable(${KX_PULT_NAME} WIN32 ${CPPS} ${CMOCS} ${CUIS} ${RESS} ${MOCS}) - set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} ${PIP_LIBRARY} qad_graphic4 qad_utils4 qad_widgets4) - target_link_libraries(${KX_PULT_NAME} ${LIBS} ${PROJECT_NAME}) - endif() -endif() -if (LIB) - list(APPEND _ALL_TARGETS ${PROJECT_NAME}) - set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE) - if (WIN32) - set(CMAKE_INSTALL_PREFIX ${MINGW_DIR}) - install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE}) - install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB}) - install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN}) - else() - if (DEFINED ANDROID_PLATFORM) - set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr) - else() - set(CMAKE_INSTALL_PREFIX /usr/local) - endif() - install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include) - install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) - endif() - message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"") -else() - install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) - install(TARGETS ${PROJECT_NAME} DESTINATION lib) - install(FILES ${HDRS_UTILS} DESTINATION include) - message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"") -endif() -if (NOT DEFINED ENV{QNX_HOST}) - if (KX_PULT) - install(TARGETS ${KX_PULT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) - endif() -endif() diff --git a/kx_utils/clean b/kx_utils/clean deleted file mode 100644 index e1d5feb..0000000 --- a/kx_utils/clean +++ /dev/null @@ -1,4 +0,0 @@ -#! /bin/bash -VERBOSE=1 make clean -rm -rvf CMakeFiles -rm -vf CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *.user* *~ *cxx moc_* ui_* qrc_* *.o diff --git a/kx_utils/clean.bat b/kx_utils/clean.bat deleted file mode 100644 index 3a657d9..0000000 --- a/kx_utils/clean.bat +++ /dev/null @@ -1,4 +0,0 @@ -#make clean -del /q /f /s CMakeFiles -rmdir /q /s CMakeFiles -del /q /f CMakeCache.txt Makefile cmake_install.cmake install_manifest.txt *.user* *~ *cxx moc_* ui_* qrc_* *.o *.exe *.a *.dll *.lib core *.qrc.depends diff --git a/kx_utils/icons/accessories-calculator.png b/kx_utils/icons/accessories-calculator.png deleted file mode 100644 index 1b1dd1e44dbf286667d71b20d0eb1a42b29a23ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1525 zcmYk6c~DbV7{yaE%2KRAt*F>)X?5I+3rrA@fEt7#U?4#VW#0r8AtnkVA_WY%v5G(@ zVG#%fOaj>m1TicjVF`pK?8q)_!ai!%La*)A>6v%mz4v?XkMExId+!m-!Fq?rJ`D&2 zvIA*@a02teFGCFq?ueqtVlYAR7mye=HMQZ1E8}3R9&UrhgX*0xF^BD|Ad3ia9!vV$8(o#B|{^G@pqM{-ymHPbo^Q^3_?Cfk3i9{xo zDHKX>Zf;sy+S8{`{rvo5Vq&_xyAu);Qc_Zql9G-bIdb~+=`&}}7#SJCU@&828X6i#xQ@f&ZsBowJf1)x+y=Ufi;O1RyLT@dC^j?M#OAJ_{FXVexlnM`1NMMVXR#bN^q zOW5_r?1mB$1gDY46_s*DWjvrpI!{yzV&aRKd{KE7kce3Y7ER!)s1nnwfy5QnVwON4 z0Lj)!xUYbkxv!cl0Ry!yd=P6LkhHqKz8-|$*x2|l6@U{!1z-kH0pI~F0YU&O|KbFa z?dj=}%jE#SzP`Tx{{Df1fx*GSp`oGS;o*^ykvDJNjE;_ujg5_uk55cYOioTtO-)Tt zPrrTpc4lT~c6N4dZf<^leqmu@adAi%?mDSbNwY9bN_4SR74W-8^ zUw|^4;N*aYs6f>;H23J~8yLb&&CaD2l+Xd2z#=xA!{Ksyynk8+2uuHK7W6CY?C$Md z`TTkF%6;8*@EM&zBF5(xI>F(P2ih z--}m+8hSiTh(6E0+ooz3#Z-1>2om{hjXkTH_0`W}#3%|nypRz-<#yb?nzSpobdeEG z!XIXwVsX4Bs1ut0kOL=Gl6EXs+_5Xy+b^K2*pp{^KH=6|%q_|~gR(IgIe)-crqXRq#Khf#;N-DQsWz-g@9p$5eA=I5N;A^qe@%0&ZJ6XD59E;MT5NA350 zY1`D=S_K-~$BfkJM>l7st4kk84bPwl;JEWMnL%`gTlq8&M53J0jTyPB%um%D Q`|?*sS~(z?7rf*C28+}ws{jB1 diff --git a/kx_utils/icons/archive-extract.png b/kx_utils/icons/archive-extract.png deleted file mode 100644 index f6f2a5db96aa099fac1ead1cf2472dfc999a6c40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1005 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabRA=0V4ND@6XFWw5)YV|n3$QFL&HKt zLV{<_nw6KImy?@QTUXQ3*}iAbp8fmxpSyVJ@QG75Z{ECp=k}eucj_A&8X6mS@7@iO z-G2ZK4jw#s=+L3VhYueCful!{9y@mI_z4g=4FqQ(;4BE7gMjnr&tCw7ix)3mx^(IC z<;z#DT)B4b+I1kf0Yo4GwDHz0Ai8zu&Yin=f#~l2`}ZF_c<}Jy!$*%EJ$VWO&p_Zg z2)ual;^oU1FJHX`f>&Vh`t_^VZ(hB5^BM?%e;s-|%XY&(r4?7hUI(^vEK0iGCUi(hX!_KS+oi5OKgxHz zA69$ZW4tf^{_XSTlU;gzZ-0M(W6qE6i5CrBi@r}hc+vLcMqW2}v!;*_J1>9yoA>)% zEL-F^Gqp+Y`a>j2;zWCbZq7Jc#>i0j?orm>xb3;Kd6?(_-hOOnYnf+*n10B@hF1?t zcP9DRyS^8B@iXV_(-#lCcLvRfabvg>!T3OmA@1LvR)M6$4Iy5}uIEkG&tX|ssg*nH z-fwTdW45vkkBbgR&E97hx^>OUGd@?Fiun{LCS0v4v#L+yT(;Itxi@}}u8)}J(puS& z>}#K5Ha<;F*gRA5%Bi{(8QC@0b)?N=uhd;Ax?3qG#KU}Q?_;Gm`bs_X4Xy>dH0}EI zWU0SL+$lSCA(L5`f_M07J_$3FV7s4iT6msd-ON+RnPd$L7kKX!4SHE|!KtX>Wa ztAg8eSIBGBy>{SfiF@S`^GlNR5aZKkIY+({yO$0;8T-Fw{HxR3zM&*1T%zW9UCM(0 z0dk6ue{Xx~5Ieyx;ro*L78-lGYMj0@oa3s0G~tWZ3s?Kbo7;EP*F^lzP`I})=IQ&^ z>x|v3`FWE#_x-&SMGn4WLZx M>FVdQ&MBb@0Gy;gf&c&j diff --git a/kx_utils/icons/document-export.png b/kx_utils/icons/document-export.png deleted file mode 100644 index 9e1b6a620cf19c87ece3788fc8bdd77378f38d74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1106 zcmZA0c}$aM90zcY4k#^cCy+%3Z11KLmq9rlV3?FqkgI75-4Meu$244-WT4|v4H&-uLJ3BkKgyXRcuzqa2T^vEi-mMqf+1ZcNlhdf+H7Y8qxVRWR1Ox<-$>fNL zh!h$vJ3AXx{^jB6NhA`Tot-fl%zw52uXsG(6^9E83k?YkVlvYR1OkafVx%(i3-j{| z@+vCJW@ct!7~TdDLI zUtd4)_%V;i8yFZ62n2(JgHHwrhlYlRhlfW-o&lqyqtAhH8=+7*F)=YYIXN};5&)-6 zi(i4$XJ%1zb0U#QEE2r}=I0lHl{bJy@>VL9NCBBlwk};?m#x1;ZJ;(cH#asm<#PF^ zE#zBUav0tMKq?e4tbi3LB}#=tR4N2f+1f=AkZQH9cQs0*(WuoRG@x@dw6=-ZW@4j9 z?V=2*y*-23x(67IMuP!_30x+V*=)90EMRE&T-MgW2MH`;&{Dx_k8*ItV4S=U1O^2k z2|pS`jf*cjTUJ?F$zrz&w|DeLBiL#~Ts#8yI^YvxDQQ0~wlwQ2MA63|Le<0*l4p(z~?&nT5DT?HiBt$z16@z{{+d?v{PT_`BOOZH&! z;u-zOsZ;8rUW9Tz*U)gMb?QdBrSP^8>n^C-J<;rWFYRG|Smq52Hc?jHe40C z(|Axe{%OV6vslbQ=^qkkwmtY}IkRQ_X*x}nwa+DgEORW9A5zR>{^&>%f9Rtu>$U7n zb{M~Svp+ZYNSM1bG$1E1bmX$)6GZQ*`Z9!a^zw;MiQJ?F-*HLabu zC+K_q$XLhwndJ2Y*7WXXyxu>fFnS^g8awvugZ)kJ>5lWzY8$=2H!C#AkN4aO@*64` z`IeKjKvx-DLTWEgpH?jk%*dR$^zzlvOSy-W_GGP|{iNg^r)M4=?ZUaiY< zD2TpR*02w5Qe}Krf}OzKx=I=dPOjF^x`*3efw`9s7k`;`zgA+#(lDp#g?|cKeP3g% zYJGkB%*xg7o<>c~Hy4+e@y6{F?edvL*{D@Y&iNp*`N0#S!S<6UP-(HfF*!B=0F}aQ A^#A|> diff --git a/kx_utils/icons/document-import.png b/kx_utils/icons/document-import.png deleted file mode 100644 index 97e683ae5523e3f377a6a73be7f66d480f029ea3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1017 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 diff --git a/kx_utils/icons/document-save-.png b/kx_utils/icons/document-save-.png deleted file mode 100644 index 7fa489c0fe615ddfa1d1f8dae1de37c8ed858dcd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1263 zcmVM8$}SF`)$W|Vz+h^3K1d&siN<^An_F5_&0!O z)Rzj0@&v6^_10 zg~*Nh4_Qv0^%;Z#{w#!k|1X#ZQ;;@Dp6+HDfFwzvR;z(y+w7a5d4<3CPl}Rf7-tVSvZMG^9)A0BAQf8V&LJ zVG9{>Z3|Y_U^M`ViOHx#!ZB013K_`6*9ZV_uqB#YC@zDZ2d0D?f6(P|tQ3#a@s(2L z01}P3@xh-TA45^onUU7wF%q&o*g97OmE=lL4uFOcKDoWQ{=CRE|L5o=qZ!D84eqm0 z(TY!}fpk-G0x@+f4Xgl&tX`6`UHUODLTUZqH4rBXBHE6TT3rHJy|_6BfHj~JeTEX? z(^0ITcRZGj$IvMk;Sv)L>kUjP&dLt6R- zyYa=Bbgatf8{D{glU698=svQ`7Y~CniEsL{qWLobmqjQA_hgE!!xHWaYvFXB9A-fFUE*Y87hrIt&Mc0u2-(v~0T& zKomz11c4+VD@>5(9wI1v4m741bguyr;G&{9J{<$#x*U9p55;jL|g$=_H zfzf=j5U4rdp6zxU`u#o_*fcf*z=O+|E`3m`*1o|~wbT1m=)U#UEdfQHwk8G7iBS9~ z3|T7zz%osq?{>Q^UTjrN8wdl&ql1G#H#RoD-hSocXL!RJi!cf~kv-Q!YQ;po(4Rhx zD7a`UT{6*-j6*c%v3CUk-TC)uH2Mye-|{@~A`$TRl`GZ{4<78euIssuZ~ diff --git a/kx_utils/icons/edit-clear-.png b/kx_utils/icons/edit-clear-.png deleted file mode 100644 index 631ed4457342d9e6f224012c842463ef09bfb8c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2066 zcmV+t2<`WYP)x*e)JWac-SH#wQ-nR8CQ z??V9a&birHyP>V2D6Oi1xANEi_WvUA?O=O#N1Yt{FO}b!bpZ~OI%n`&{aCwN2zNS9 z<;}Xl^-CIRSECYcHRXZsglPS&3*5WjSf$N705{Jm`}F5o6%ZbYHS29I`~HkF7JAMW z9h!B4-ixPvn@;edOOyWUnB?HHSr-`S)M$I}4mtW`5AwSp2HFJOx?;+$L~N8m^(Bff|Ht{ui9&=7Wp`+_rHI)*!@x7XeD= zg~}9-Dj8ZUgp)(O_~DmAA;#H!Tty@*5nA)#^~VwVxSGK4al`P7qet=I3Kh7;_ETI< zB;HCO%6|(-!i#t%PmY*8D?9w+No*|EXCf&P-%sP>910ptM#xTIn~somDMGgf#@e37#LwL%m)+;BfE*HhU`HL`UPBN&7IH zg6{4`C^QS9zW%5{{3vSQbj`!CP&}f_#V1V+AD%?We#Y=5wo7uolKVr0G9HxaQBab3 z0OanQ{(ghzgunFh!TnU~RBp2vxHE={1r&sDgi`Tf5OexFeeU!2;}Zm~LTKlVM-b22 zw!bbv?p3!o4Vp_6K`ROdb#??Kc-o&XHZ-``>-`zNzI{9Hb#}%*B-cGX@YmcB+~@77 z|7Z@}RYn4;mp0bn;M;a;fJP2ssoG ziJo0{xZCbexXae|O~}~}-w6uBePm4i@xfS0;Q7<=83>RUMf%0={<8(KaJf7QE|eya z90W}U6Lcav$Pf9p>FZ=fB3IuDuTA)>g9E<0Wee_dalu_X-EhOaxwy@71{#^bp8BM12vn=r`+xhI4vboUDhwTr_v+mZ|YjpPBLS4Rh1s zc9(U-H_ge}aL!P_0R<138sp2Kufyp?BArP5qJSW5o1#oW1O2V`d*M|Y<+xh z;oR@;n;H&1FfhR1n3>=!uA6Zxkq{7xpA|?B+7ezZ^m~>OxdU2?BS9@q|v_3JGcuf()^)G z9t@gvI@F1opi1_$fOX49 zMb2w@HL~D8W;m=4-SOUnp$?kI@DHX&L(ho7GlcNOMq8|Q-GQ?#EErSpcEMId`2ja4 z1=qFzQV|C-BAuZvKO8RRv!VWIAk<{hq3Y-!(5BI#DK`kTS%FXxEOyFAZ|kN;vCvQu;@{m4DddIe+e>emV{RWNwbfY^-qQI%}MY zP$?OM5mLv}%ue!sw|hESb)U+hy_6i-0hi<)&`BAS4e5bX5@mcJXe$f>ozM@|nR}qK zBpeD7sIA2Tn|mr4&QCjH111t3t)Jw1+l%TXtk3ImLN+vrLzdUcg669QG-I))B{gB0 z<->lK{~LIj9zL}LIuUzGd758v5@%~~ZI(Zr6EonPoIP1DrcX9zFyMR+lg!-@+7wJs z6M^p1Fz7tKcQQAASBX|c7pQ#fJ7tbmqXoX7iECxS+Zv=S>sm3xLM^44snxVO`imI| z1V%Yam+n4dZ2Ywzo{Nz2o6%2ophgzo%gv^!w-4V@Z#_QvJ+GxFmd8k&x zVrryx$1|Bs%l7=p-?j?`hI;T@Jrk;Fv^i7uQqIB}8U6hRF=M$}#I(zfbx%%WZ&OwA zcRxKL@P1hq?=>QfcJHf~F`XL}jO7)%f%D!1Je{At0f9cGD^0o4CKZCfdHOw3C3tK~ w4tEYMH2CfEFY~e(IA|La%m4rY07*qoM6N<$f+Lgg_5c6? diff --git a/kx_utils/icons/edit-find-.png b/kx_utils/icons/edit-find-.png deleted file mode 100644 index 64a1e28d3afe98367cfe6e0dc06e617fd3045772..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1631 zcmV-l2B7(gP)MNw`U7%Rx2bK8Bi(|P{(xd5FTJ76}M;B+{UX?H*-l_BDd$m@K* z;M=q`5flm)BogV($cTt9+2j_Jne%fHIyY=Yds`af4F3(o!_k*TbFVhQ(|~VO{~eZVwoZ78xQj3UAZcnMB6)-8nqf0 zs=dQz<5Z}eRl$)-O-Y5xXn@ORfj@T!@_b%;u0<|2X>H9sR)v(1h=_=74BhlP9mrCP zu&~I3b&CV&ZD~MndlRb5ixE2|7CH(@yBwNUHlks9Jyb*>DKYUTZA{;>E8V;M9W+xp zJXvneCp9?*W&;B^BgLZ9Y^+~aLow^ov$_H0g}E@(WW639ekg?MbX%iT!X`>YZbmFh zB|N<85TmKkigmSq)R*`m7YZO2iMcW?U9uGW_wIw1nsMydvHqy2sHLpr-J82{{QZ7z z&oCQ}&?@9`O8M{zqfxFEV3|*Yb+digzM=+=vvZJ^B4Aa!N86|Nv0f#IE0r8GqS0(g zM5{ds9lms|^NLU@n+%sU8N8Snw!T5RO!kP%aVI)Ddi8IeOxNvFvE;5&p?v6ZdxC7! zDyQ?|PM(NG#%XA@@zLrMVuLpgOAJ#{rH+R&BZcdm5UOQRClR4IeG=*!9@g3u(U&hq zZ%#UzjIl&09wlZOSN{p)$5%b?aEXbDaq(h!Fp87m7e!&AE)MJ6LiEm@j?HcXHaVwa z`)md|W(_yuA$FVXd$v(3lnLl@C*wqg0+;LbxLCvBNQoG$iNO4_0&W6mS|+@}aXdzt znu;8kl@y(X&MX0rl*%wzt-)YGj-y4Sgl9Ttda~GZ4TX@iS*1{-wyGT6C3>9n3vsPh zjgKlsI8vO3zLsUk%gbXAqOXQc{_LrEot3w_t`gneR2(asjw^H3_#`04sYO}nT+;~h zp(ak6$-TfZjFa~J;JiQ;j&0k3&yMWCwSj#&+_wdDD#~H8SZ=Tf)r%4!8%Gh1u4^P)Guu8^Mp^E`ked2vSpt|61su;L2ij z<;PH$U8o=m7C~3tWcNTG)J7{b*F~FWqfP8t%?xJ_=iHei07;UR(=|yPDj=vjL>=voHq|p#I-L?Qk>AmS zzPxvY0Nbw1lMihQArOM+`NlI`aTj%p_iiAI9|$Hw>+3_T2;aNL;`?_!mV=+Kn@kKz5^$Yl9iaBspAwx;pX{S z#-xlBhlq@bpn{6fn5pNER231WR;dAk=m>$JMxhWW_&>=E-TxetbB4~q4s4q*7xMMe z`tqTiLx#AA`>z)1x*vO%1$<bC>TR zB179YWoA}u9idFEyi8O1+r)8vEX%UVenCc{Z$RQW{+MOi)^7ts%?QYKD)s;X002ov JPDHLkV1m)``fdOK diff --git a/kx_utils/icons/expand_s_y.png b/kx_utils/icons/expand_s_y.png deleted file mode 100644 index c2e8f78173c175483a1a98bff2ef435bc6ac7265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 577 zcmV-H0>1r;P)pZR(Utz}U)y$1I+ZZs8Kv2x`d2p3=gC8!C(U?VCUV@$jgNlX-R zi)>vH3`HxaDxCIkPE*eJy1>>DO^h(fY$ln%XXb@dnpG;5QW%Dp0RO+a<#PE0z(t+V zfU5zZnPq4++5|xkGXo4W!<>7ywV!9^->9c~@kvb{FRy zW;W{jL?$jwQm_)_97=QCzC43;H09FT60Ycx7pY?EYxQF^tCF;{(@^v4XHBi%)VCik zMeRLx;z&snD@kIdX{?2Jvr4-i^?Kc75CQN$Bap-5b9iOQgC|Gej#fZM+keOV48#4t zWuHN#@rh^aFGxrju@UCRrZAUdD9AIv@{ogEf)x|2TcVH^cyzsfoWb*rmn1IXaJWs! z#nj&{54tRj-($p|L2-ehUY-Zz_y1(Dxw)n7?JeDUJ)!1qsOD~{-LR#-{r!R8cy&cl z6lp(-1`G_SPCwQ9Ngio=+D1?N%40#LQu%0R*Zv|V{X(9S diff --git a/kx_utils/icons/expand_x.png b/kx_utils/icons/expand_x.png deleted file mode 100644 index 217e3eae51e02886363f3e14aeb62ec7435a1fa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 579 zcmV-J0=)f+P)%Z}XCd`boz{X>GMd&T3|I?#(&(&JlnpitEP6L9farDlW}D1A7>uj{~Xfc44i@Q zy3Rje=$xw?i+wqLhS);o#a$ZaYfG|#4LtWZ7IDu0!?nE%;KIwZj8KH2!QAU9hV?jm zKNPV-`PD@{j|MAHgeRxh3H%WHEzj-Z5;MgcG>yk;K=srrI$(_*1s=F_Zl0i-!>Gfk zBP)5zXRaY41JgF{z4xW%LxgF$6Q=RbZo)7;nx^T=c0dk5TY!XN_%=<``fn;9*V(uq Rx_tlu002ovPDHLkV1kJN18@KU diff --git a/kx_utils/icons/expand_y.png b/kx_utils/icons/expand_y.png deleted file mode 100644 index fedf9368a2fa13d85cb05ea6441438619a432d95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 577 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 IM6N<$f}#jh3;+NC diff --git a/kx_utils/icons/layer-visible-on.png b/kx_utils/icons/layer-visible-on.png deleted file mode 100644 index b24055207626a181301366abbf9c9992d6cfb1f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2001 zcmV;?2QK)DP)U5({sLAW~f0Da+&l;-5${=cTUBtIK+XlUq53WXx)^&S5;N1&zw1}|3ySZ1Tr!*P+ngC@Yu0qVH||Hx%rO=o}Qk*=IGI*Pvhd^ z5E&VX&6_vF)6)|hH*UnHO`F63Vq#(t6%{39Wo4nVvhpK)dwUBCLh^&bv$M0e78Dd9 zARquvPENhHwzdjOOUrl*3kyHqR#sMVGiJ=FSh8fvy$u^SV8@Of*tKgHh^=8_XpWwq zp5%Lj@7=rCCnqNdME_j^+ai%jtc{F}OpJ|<^$ZOSrM&5XJrffXV_jWcEBel=*|TR~ z@bdCPN=k}ADH){{{btHcSX*05D9=mj5X_u8GlxF1B2fKrdvDsbX;QkeIkB>a*y@zY zWX!~)l`B`;+Su4kDF$Q8r^d|8%!6+{Rb?|nIyyQwbLY;jWNlE@bkWB~-?_#qmlXu= zNYolW#{+a|OKIzAw{(IMl+ZG>v$NX~9UYD8>gxCSJCh^RTDx|w>%4jMmYbTI>Q4at z0yE9GnLmI2@2C>|eSCZZU0hsVrO!*wb;pXg(t@k`2}q=%PNQ&X!B9z6Jj#mTi#LPc(FF7os9zuv!pe=SwRA}!t0aoRAV zO4*c_mIilsciZQpQ|(HgrICW+tNd#B?%kzqLhJ<;Bv|R*-rn%_^@YE`KY2r-`0UW3 zL!jU)=p9RbckDcUeSM=jbLK=OCMGJGh3`~`9Q=X>3l-hN26Ey#A6c^QB;Pi!d#K_*p>eZ{r6~jfVrko3u zb9P4`ZA!)fjn=JO_b!t%S*M#u;#x!C>}-OEhX+zqQ_$Pfg_4HPaQ*fu&VMqDs@8u& z(WF7$pNG(J;|rX8{}!BAcwkFlfEYkhQj$m&K>mj_Tm#|3l5y?N6d*nB-D38QCf_@wzi_Qv;<-P zeh58(3*l++p}775f?_f;I52?z{(g`N2~>Vu8GIgyQ3tXcgE34h&;QOnwbR?weg&#= zp{c1!=<4bc54!l_Rpd1c!ROoq{5mQdaoeMDw73{lo^V;R2v+jbaBtQi;YtreQVO8H zc?-kC!x$VK6m>+Gf?O^aXn+|eoat;>6FH&2v$OMh?&(~1H1!C4`vJO5Zrr$up`jr$fWE#y?A*CiAOizU zPCPGM=aw;%HS4fY!otE7oI9qjt*uQM=YK9!shd+(gf;|ot%p2 zwRX2 zDu=_?6L`hzAQrBX!80h44U51B7@VmW_q}`fpj0XaEjX2KDRBGFPO<9QgxHolXh4F>VD7qi>MM`_m-tGi%nYwe-wEYdpr<;H5w1PdmxD j;H13A0u`VAFR%Xq565XnM?5ki00000NkvXXu0mjf-tF2E diff --git a/kx_utils/icons/media-playback-pause.png b/kx_utils/icons/media-playback-pause.png deleted file mode 100644 index 5c7d128ee8728707a6193eb41af32b4e28890533..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1145 zcmV-<1cv*GP)kdg00002b3#c}2nbc| zMg#x=010qNS#tmY19kua19ky@)q>0b000?uMObuGZ)S9NVRB^vcXxL#X>MzCV_|S* zE^l&Yo9;Xs000B{Nkl^Bw_qq@)F2oWehM>5RxKr%Hm6}!%+eJ5;P+bTi3lS*+iMTL0p`m}$nM`IT^X~QY zaG4NCay|}k4)2`reDBVC=eR(>eVF$r-4qj)1*i$D;c~M0PMbdKBbY0P8D8 zNRZe0(#=lS4j`Bv4AY$T#V)(F>5$@qgbX?I43H&hGVkVQTK`M%-dOl9R8v}PlTfBY zi6Kx_XPp{e(V)oOvODwsMjyfSW8sRgbZCm;7>{s>LF)-A9bt!GSz(YOIg)jEYVNmv z1n0)Wim$Y|!zjl&!d>KX1_-1=S4uXx!c9g*BZ^}mZ1f1;9t>A~RnmD}-Nz`9B_lW? z0AARoLt71gX2l*QS$4-iYC!^!PWx(`EtOXpXIQuMLe5;j%?k_(ck>KSD6@^PrqfZu zTjj9UEjB3e5=Y{bXGp9+X2H-k6+2RKUOr5==^p;LmOwhwEw*SeNk!$kNFa(HGKK-u zRZ!`3w1jRkodNeoK5Xumws?wX8B=*yiC?HsOV_htc8-SPJfF~|t$W)nvB)6?>h9je zpGZp`B~LIKJ2`?1ZgB&mdA7LD28rp&2~X$v@KS(GB*rNxdAP4PAj zxg#Mfs#4O^iJuSw4-k|P?C3C|O?k9NW=@#Snlh&M2Y27mKA zEr?d9!3_>$)>9G;NvH)J4GS>GWR~PWe;o5}V-&T-|4X2-ix-T>&Ur*`wm-HEFKilt zuO(p>asSD#JyU84ISQ2I(R#6!$GlZj6jqaPDd^{#{VCl@kf+FqJX$X{f|z$rRf;Yp zVTpQ%9ad=4p(}V53{#Rv>&23686AG2DFW(Y$pv2iG`yw>$eTRG5QX?gI{s@akKaO# zckR=1pMCXu0%0~Z#l`}6XweZQ5l`4(Y|?dCIiC~I12n@dB=B{O`HcAf;wlaCw*?)k z!5dP8Cbjkdfj`KLfO%Dt1z?WJOtrxGI3}@zeM2oyMbus8-%>#3%c|NNsxNA&2Aj$E z^C}f`g1y`TNQISea-KDt%T7aeVQ;7!g~ocQ=#cPC@ifIam82kQ`jKyNcEl<_wXkoj zo4qiG7K=BbLmcH%?&C0yTk3pGXxP9Lkdg00002b3#c}2nbc| zMg#x=010qNS#tmY19kua19ky@)q>0b000?uMObuGZ)S9NVRB^vcXxL#X>MzCV_|S* zE^l&Yo9;Xs000CGNklrkmC6Jy9WesR^^K8P&yuG_6BOq91w;O z0FIbYMal#}U|XkRx6FwT6Tku#*>#;1HyPf+y_n^2g($1BtyaSfaR;8k6ZA~sI(gSC zc%vyhSu{W$FX5Pt^Vi%%4psu)qlr?gpwL-XKAv1R_HEJ~1I0WF4?Jpm~W5GYEj ztH#jhkPumvF9GJYitJ75H}MpnMT6lX9Y15XR54~N2ULy4d;0$f``E+=_o>u3cZcqz ztB)Df#=OsD0F^qVjg&%)$pL|--KDEznj~;+%&Pn%Kky?%Ctk&nW;j|!4e%6}nAfZ3nxTO315g7c|Bk-L zfaG<;pbU5l8X*cRv9L2JXw=|y1iD;xnjS1dKkxTfK@nT`F9Ew5D9F>4bh~(rnSG8{ z9IwEKi+b)Ufs3v5z@c9-(K+Snz+2!?KjqVA*sc&7?)`d7C_O6|h0Pt^l*|)UbjczO zpHqs6{c1tr{jM{Ly^B^h(GM`fHiqD-BOIzeI|&rCUIitq#~4@XO$B|~3_nj_UbE*a z_zsUE(wSO(Of&e;r{TG7?{D~uDlKGfEwz9w%aCkX=Os-r_7})Orh+paP4EeXiDW3t zT2Q`-u^N!^S6smWBcueERN)jwd!i#FYW(a`Q(s>b2 zBl1;=3cRN8@g?$5rZwm&>RT`nX;=;&DABsmLiTnzs1o-Ne$v fC9`oMo%a0)Lk#jiOZi|800000NkvXXu0mjfdhQk9 diff --git a/kx_utils/icons/media-record.png b/kx_utils/icons/media-record.png deleted file mode 100644 index f926a8f27f85ef68165ae570e0237c53aabe19a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1843 zcmV-32h8}1P)lUEc!{aPp#3JQ)<`D13Lv)N_>h<(9s;-2Q_ zc+qG;l5J#}ye#g?=tMywWZBd$S+)lRkr9X?WFwinEWq?ZW{{XD22Dsb+oUx%LH?B% zXuI>f>G^W0aS(5Ma_@J0@A>`Cx#!+{t|b ztgp{7jQ%4>j)YgEcSQnCO-(KyQ^(CpCg8+)t|@UI6C(zedWO3?x!rK|=uzKG5ol~| zOyU2&;^tunbSy0`(c7p-5vo}5l6rKP12%G}%>&CJZu#KZ*od_Lu!^z?K^ z#%i@<-c6Q@IXM~L_?Jn%f8xZ6yDubg^5jWaJ`8Xunx39kfL^bc3JVKq&6+i2 zx7%TnDJakZ5)dp6Nc;VMx_b30O-)TvMn(q62#He0@jpkPuC5Mi{wITb01lUL-MW>w zZQDkmIJziJpXmxX+9$!M0EhiU_|`RojWN% zKOf)-Af14aNEGyoU_2~^!0pQY6%`dqH!y$&Oki8N)6T3rxYG`%rKP3H{cG2*1-Q7> z1cu#Hm#FT_xGQ%ac4P; z6F~!zEnBuwR#uj7k*O>?`HXyDe?viDPYb)(2rp2K=Y=PHH23=-^sJ|s3V-;Xl5$@K zfOrEQR!idXcvMg_7XEj#lp75G5f4Bo0#3G?oMg)^_n-ZaLcGUqOeP6pSSZwa_`wPS*uUZd z5K$uiL^Ho#NhDx;bKSaiz!Cy38-uvyhC{T9>&1F0f%Xov!815aQaOm2Xp)T;$D*{v z@et+cw#u$Y z6{9g8#DX?ND~bAaOoKsv0xWAUu175;t)v(#2wgnd#0#?$)cEF~`aiX}NXOUp;gr=+ zPak5yCjo~)<(`M=WHLYefFf8b7FfK*vcRZe7S#AgKmK>}SREW9Is<_Ku%u5B7{fpW z$fHM(^Z-F^DtM*l6LP%cr6q1JGN;8ja5$of;9K?Ey*nuT(~ouVW%};lzpt=RfNgO7 zD+_`T1Z0cA6FLDbAief;JEeHN3>G!P!y1X?9c5I|(XPho1ay559y~Df2w+=_i;Mr^ zL0=G)M-1S=z&(KNn7AXX8BWTst|EgoBDD;B{KnEa^I@yAzC28M=e|{AP{i#3#-)UN z;M%ooG&(wp`$6)?T6G)N)YSaQ_2+U~)YjJ0#*G_sD`K#mj3$v4iVhBsLMKu+q3ym-<7!nFM0!GkI-XUT^$SOLYmckiaMvNEwmPtWwV zhp6T2?d`>X2sjW%Tczb49UXU9e3(>LR_1ag4-Bt=iG-&4fjeP hxBD+$y0oh2`F|miFh-s2`rH5j002ovPDHLkV1mqrSN#A0 diff --git a/kx_utils/icons/view-refresh.png b/kx_utils/icons/view-refresh.png deleted file mode 100644 index afa2a9d77403a12cf6808fd4e551f8582e2599d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2182 zcmV;12zmF3P)Dnz#_!jKNQq7A*Lpp`badk2@PWXqYX-|G^Br&q=F$>Qi+zP5MsM!mpA*k zuf20;?#!HXoIAVOWm%yVoA{l4@5#OM_&bhbJb6n1`H5BQ;7S*8aYsrg z(%8Ii3;uED#FnEM{<>~)`;y+z_k9UfuL=Wd3^^--)HY-9vi9Yh?_cu(n!Jfy$zTS8 zFo2)}vyvn?9M|-r={nrdg{hj@bLQ6=E!AfxklAj3tAllJUis0Fqv}*~qbQ*$kCrho zG=SmJ;ke;A=O|2uVNMJp+ zu;cEWP$ayjH}ek0J-mASRn(kXt0W9x0rd%pBpxKBqw^{10_ z%oVjGo>@EUS*iKf;$&9;O=?7MYMcQXV9*`JiNOiUq?uH19(+43b^r%Qh*N0-8PySL@{C>NTq zmAl*&&j?%;7m=-I(Us~#EHN?vgcGQQ0hk0J4Qw(qsrZhsSEW?J(B&a8Ns-d@z$hB4 z&i!^|7&j3whr5FWPw_8BZN)_edGBODPKjlmU)OlN& z4dJ>|3B=t!-WZQFVw^yzWIt}A)jJn2p(fkv>~xUJ=8+4c!VW>LUW;RQ#vRl~YN%eT z0!}M&0-I$B!U~}7K&Z}?pjDR^9 zW{w1fBn%*okZ2@|Mo`dfPy?U|ddU}J(~;eB;yI9g(5#EJY7>RVjYkxMPzh1xRX_*Q zgGN}L>lt#-?Jo$$M-mwReI4(mI02!^YNO`Zp&|eVz{136M>f%FB&97#EC=ugZbOBQ z1{xQHVXx5y)hVYs5kve(BsILL3O2L2eVrEoM3QY?Kgcb3@949XR>=y| zN9HIt>tOA)An!&l_%Kg4mvO7o?ddELGctBk@|Iqbzuk#2Bo z&hBJ8ZldsmjWTmA?MYAi&~*-)hk2IVeh$Mc&Y~^q*Rk^U(roGHs0>XDKJW)w2D&} zLr@aI9y*b6*=b_SODgY>+mHwoplwY`2+TZC2}AP}PN!W?UpF;VD9pM2G~W zv=zcESwU4AVsN?%Clyk$t6K5CULaO>RB3=w+Hwq`F$PVc@dDDMA*^l<0R@VEwgoBC zK!`SB>s*LjR9s;~MEqP3GO_+i2^oFJ_AnvesgxX9l+N^$J}LPp={csqlMPa&i2+9F zj44oKhzaYFr6Ez$U5wc-8i@dIWNt}C(P%E(pO2sm(K&6A^9rN6E-jV4e5RI?33*KZ zT*_Gq#1IGMUb2DoFS?k2bZmYj#*0&+QxLHOlOr$$LS29}0T6%)0v1HT&Bz{0YhaLo z5K{6CO^Wlcm!ukdMp#^1ui8avBL6 zumS>~gG4_FIunN4<@%g)A+7>w`9$QyDB!ri&6~IH+`e=74rj)Dft>fM74Ow5-m6!A(5ZcI)cDc4`=i%{ z&;FA>MbG*YJM&%KtanNCzm}~0TD9(58vQ_3PJf*sx*a#*KTge&2WP$Eh2yPv3fb=FHi1=gyx$f8o-lOINO3 zxpwW^bs)HL{l<+OK=<6b1w^;*-o0}l2wwhp@apHoXK$XoeE;m(^XD&KymxLU<_se!oOSSHJy=wt8P$>76RpzF=_0L5$_~N$m z`N%+;Pog9dqk_ z`_6gKQZ7x3dQkCC^3xjQC1PLnO#DssMfYtw(Z#o~a=Ei2@29IX9w>aAy|9D#%bND) z1(IF{Z2JmWWm?30A0JD7>#4Ng@__i9OVve{ZGYCV3d$@^c<@=|*S_cVPaHff&g}dB z;oshyH{JcW<*#UZ@3iW#)d@Kf`NogF*%l02r!#%3EZY7-IQl|(Ba7);{toLW<$130 ztSf82m;Ac<+sNZi^b7g?WPippK4&km-qO2wz_yx8h%;Pmeb~X*vkex$f309S?bU;C zKb~F9(LC`}Kj!DxuV?#u-*8_uYm3~U^~C-MbLupf$NA@OJpg4iPgg&ebxsLQ0G2=) A&;S4c diff --git a/kx_utils/kx_coeffs.cpp b/kx_utils/kx_coeffs.cpp deleted file mode 100644 index 940ff36..0000000 --- a/kx_utils/kx_coeffs.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "kx_coeffs.h" -#include "kx_protocol_x.h" - -double X[KX_X_COUNT]; -PIVector K; - - -KX_Coefficients::KX_Coefficients(const PIString & config, const PIString & name, bool _pult) { - setName("kx_coeffs"); - PIConfig conf(config, PIIODevice::ReadOnly); - fname = conf.getValue(name).getValue("file", "k.dat"); - readCoeffs(); - int ns = piMaxi(conf.getValue(name).getValue("count", 0), K.size_s()); - if (ns > K.size_s()) { - K.resize(ns, 0.f); - formulas.resize(ns); - writeCoeffs(); - } - config_ = config; - name_ = name; - pult_ = _pult; - k_protocol = 0; - renew(); - //readCoeffs(); -} - - -KX_Coefficients::~KX_Coefficients() { - stop(); - k_protocol->stop(); - delete k_protocol; -} - - -void KX_Coefficients::readCoeffs() { - { - PIConfig conf(fname, PIIODevice::ReadOnly); - int cnt = conf.rootEntry().childCount(); - K.resize(cnt); - formulas.resize(cnt); - PIString kn, cf; - for (int i = 0; i < cnt; i++) { - kn = "k" + PIString::fromNumber(i); - K[i] = (double)conf.getValue(kn, 0.f); - cf = conf.getValue(kn + ".formula", ""); - if (cf.isEmpty()) cf = PIString::fromNumber(K[i]); - formulas[i] = cf; - } - } - k_content = PIFile(fname, PIIODevice::ReadOnly).readAll(); - //piCout << k_content.size(); - piCoutObj << "Readed" << K.size_s() << "coefficients in" << k_content.size_s() << "bytes"; - coeffs_cnt = K.size_s(); -} - - -void KX_Coefficients::writeCoeffs() { - PIFile::remove(fname); - PIFile conf(fname, PIIODevice::ReadWrite); - //conf.clear(); - for (int i = 0; i < K.size_s(); i++) { - conf << "k" + PIString::fromNumber(i) << " = " << PIString::fromNumber(K[i]).replaceAll(",", ".") << "\n"; - conf << "k" + PIString::fromNumber(i) << ".formula = " << formulas[i] << "\n"; - } - //conf.close(); - //conf.writeAll(); - k_content = conf.readAll(); - //piCout << k_content.size(); - piCoutObj << "Written" << K.size_s() << "coefficients in" << k_content.size_s() << "bytes"; - coeffs_cnt = K.size_s(); -} - - -void KX_Coefficients::setKFile(const PIString & f) { - fname = f; - readCoeffs(); -} - - -void KX_Coefficients::sendCoeffs() { - stop(); - int curcnt, pcnt = (k_content.size_s() - 1) / __BYTES_IN_PACKET + 1; - k_protocol->to_k.full_count = k_content.size_s(); - for (int i = 0; i < pcnt; i++) { - k_protocol->to_k.first_index = i * __BYTES_IN_PACKET; - if (i == pcnt - 1) curcnt = k_content.size_s() % __BYTES_IN_PACKET; - else curcnt = __BYTES_IN_PACKET; - //cout << "send " << curcnt << " coeffs\n"; - k_protocol->to_k.count = curcnt; - memcpy(k_protocol->to_k.coeffs, k_content.data(k_protocol->to_k.first_index), curcnt); - //for (int j = 0; j < curcnt; j++) k_protocol->to_k.coeffs[j] = K.at(k_protocol->to_k.first_index + j); - k_protocol->send(); - piMSleep(5); - } - //cout << "waiting for commit ...\n"; - waitingCommit = true; - tm.reset(); - start(10); -} - - -void KX_Coefficients::receiveCoeffs() { - stop(); - k_protocol->to_k.full_count = k_protocol->to_k.first_index = k_protocol->to_k.count = -6; - k_protocol->send(); - //cout << "request send\n"; - //cout << "waiting for receive ...\n"; - waitingCommit = false; - tm.reset(); - start(10); -} - - -void KX_Coefficients::received(bool correct) { - //cout << "kpi received " << correct << endl; - if (!correct) return; - k_syns = k_protocol->from_k; - if (waitingCommit) { - if (k_syns.first_index != -1 || - k_syns.full_count != -1 || - k_syns.count != -k_content.size_s()) return; - //cout << "commit received\n"; - waitingCommit = false; - stop(); - //cout << "send succeed\n"; - //emit sendSucceed(); - sendSucceed(); - return; - } else { - if (k_syns.first_index == -6 && k_syns.full_count == -6 && k_syns.count == -6) { - //cout << "request received\n"; - sendCoeffs(); - return; - }; - } - if (k_syns.first_index < 0 || k_syns.count < 0) return; - if (k_syns.first_index == 0) { - //cout << "first receive\n"; - k_tmp.resize(k_syns.full_count); - received_cnt = 0; - } - //for (int i = 0; i < k_syns.count; i++) K.at(k_syns.first_index + i) = k_syns.coeffs[i]; - //piCout << k_tmp.size() << k_syns.first_index << k_syns.count; - memcpy(k_tmp.data(k_syns.first_index), k_syns.coeffs, k_syns.count); - received_cnt += k_syns.count; - tm.reset(); - //cout << "received " << k_syns.count << " bytes with " << k_syns.first_index << " first\n"; - if (received_cnt < k_syns.full_count) return; - //cout << "finally received " << received_cnt << " bytes\n"; - stop(); - PIFile::remove(fname); - PIFile conf(fname, PIIODevice::ReadWrite); - conf.write(k_tmp.data(), k_tmp.size_s()); - conf.close(); - readCoeffs(); - //writeCoeffs(); - k_protocol->to_k.full_count = k_protocol->to_k.first_index = -1; - k_protocol->to_k.count = -received_cnt; - k_protocol->send(); - waitingCommit = false; - //emit receiveSucceed(); - receiveSucceed(); - //cout << "receive succeed\n"; -} - - -void KX_Coefficients::renew() { - if (k_protocol != 0) { - k_protocol->stop(); - delete k_protocol; - } - k_protocol = new __KPi(config_, name_, pult_); - CONNECT1(void, bool, k_protocol, received, this, received) - waitingCommit = false; -} - - -void KX_Coefficients::tick(void * , int ) { - //piCout << "timer" << tm.elapsed_s(); - if (tm.elapsed_s() < 10.) return; - if (waitingCommit) { - //cout << "commit timeout\n"; - //cout << "send failed\n"; - //emit sendFailed(); - sendFailed(); - } else { - //cout << "receive timeout\n"; - //cout << "receive failed\n"; - //emit receiveFailed(); - receiveFailed(); - } - waitingCommit = false; - stop(); -} diff --git a/kx_utils/kx_coeffs.h b/kx_utils/kx_coeffs.h deleted file mode 100644 index e6d31b7..0000000 --- a/kx_utils/kx_coeffs.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef KX_COEFFS_H -#define KX_COEFFS_H - -#include "piprotocol.h" - -#define __BYTES_IN_PACKET 4000 - -extern PIVector K; - -class __KPi: public PIProtocol -{ - PIOBJECT_SUBCLASS(__KPi, PIProtocol) -public: -#pragma pack (push, 1) - struct KX_K_Sync { - uchar type; - uchar addr_to; - int count; - int full_count; - int first_index; - uchar coeffs[__BYTES_IN_PACKET]; - uint checksum; - }; -#pragma pack (pop) - __KPi(const PIString & config, const PIString & name, bool _pult = false): PIProtocol(config, name, &from_k, 2, &(from_k.count), sizeof(from_k) - 2, &to_k, sizeof(to_k)) { - PIConfig conf(config, PIIODevice::ReadOnly); - PIConfig::Entry ce = conf.getValue(name); - to_k.type = from_k.type = ce.getValue("type", 0xA); - to_k.addr_to = ce.getValue("addr_k", 0x15); - from_k.addr_to = ce.getValue("addr_pult", 0x75); - if (_pult) piSwap(to_k.addr_to, from_k.addr_to); - packetExtractor()->setHeader(PIByteArray(&from_k, 2)); - start(); - } - KX_K_Sync to_k, from_k; -private: - bool validate() { - return (from_k.checksum == checksum_i(&from_k, sizeof(from_k) - 4)); - } - bool aboutSend() { - to_k.checksum = checksum_i(&to_k, sizeof(to_k) - 4); - return true; - } -}; - - -class KX_Coefficients: public PITimer -{ - PIOBJECT_SUBCLASS(KX_Coefficients, PITimer) - friend class KX_Pult; -public: - KX_Coefficients(const PIString & config, const PIString & name = "k", bool _pult = false); - ~KX_Coefficients(); - - void readCoeffs(); - void writeCoeffs(); - - void sendCoeffs(); - void receiveCoeffs(); - - bool isReady() const {return !waitingCommit;} - const PIString & fileName() const {return fname;} - const PIString * fileName_ptr() const {return &fname;} - int coeffsCount() {coeffs_cnt = K.size_s(); return coeffs_cnt;} - const int * coeffsCount_ptr() const {return &coeffs_cnt;} - - const PIString & formula(int index) const {return formulas[index];} - void setFormula(int index, const PIString & f) {formulas[index] = f;} - - void setKFile(const PIString & f); - - EVENT(sendSucceed) - EVENT(sendFailed) - EVENT(receiveSucceed) - EVENT(receiveFailed) - - - __KPi * k_protocol; - -private: - EVENT_HANDLER1(void, received, bool, correct); - void renew(); - void tick(void *, int); - - __KPi::KX_K_Sync k_syns; - bool pult_, waitingCommit; - int received_cnt, coeffs_cnt; - PIString fname, config_, name_; - PIStringList formulas; - PIByteArray k_content, k_tmp; - PITimeMeasurer tm; - -}; - -#endif // KX_COEFFS_H diff --git a/kx_utils/kx_protocol_c.h b/kx_utils/kx_protocol_c.h deleted file mode 100644 index 66a5441..0000000 --- a/kx_utils/kx_protocol_c.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef KX_PROTOCOL_C_H -#define KX_PROTOCOL_C_H - -#include "piprotocol.h" - - -#pragma pack (push, 1) - - -struct KX_C_Header { - uchar type; - uchar addr_to; -}; - - - -struct KX_C_Command: KX_C_Header { - KX_C_Command() {command = -1;} - int command; - uint checksum; -}; - - -struct KX_C_Event: KX_C_Header { - KX_C_Event() {event = -1;} - PISystemTime time; - int event; - uint checksum; -}; - - -#pragma pack (pop) - - -// Client side - -class KX_Protocol_C: public PIProtocol -{ - PIOBJECT_SUBCLASS(KX_Protocol_C, PIProtocol) -public: - KX_Protocol_C(const PIString & config, const PIString & name = "c"): PIProtocol(config, name, &from_buff, 2, &(from_buff.command), sizeof(from_buff) - 2, &to_pult, sizeof(to_pult)) { - PIConfig conf(config, PIIODevice::ReadOnly); - PIConfig::Entry ce = conf.getValue(name); - to_pult.type = from_buff.type = ce.getValue("type", 0xC); - to_pult.addr_to = ce.getValue("addr_pult", 0x15); - from_buff.addr_to = ce.getValue("addr_c", 0x75); - from_pult = from_buff; - packetExtractor()->setSplitMode(PIPacketExtractor::Header); - packetExtractor()->setHeader(PIByteArray(&from_buff, 2)); - startReceive(); - } - - void sendEvent(int ev) { - to_pult.time = PISystemTime::current(); - to_pult.event = ev; - send(); - } - EVENT1(commandReceived, int, command) - - KX_C_Command from_pult; - KX_C_Event to_pult; - -private: - bool validate() { - if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false; - from_pult = from_buff; - commandReceived(from_pult.command); - return true; - } - bool aboutSend() { - to_pult.checksum = checksum_i(&to_pult, sizeof(to_pult) - 4); - return true; - } - - KX_C_Command from_buff; - -}; - - - -// Pult side - -class __KX_Protocol_C: public PIProtocol -{ - PIOBJECT_SUBCLASS(__KX_Protocol_C, PIProtocol) -public: - __KX_Protocol_C(const PIString & config, const PIString & name): PIProtocol(config, name, &from_buff, 2, &(from_buff.time), sizeof(from_buff) - 2, &to_c, sizeof(to_c)) { - PIConfig conf(config, PIIODevice::ReadOnly); - PIConfig::Entry ce = conf.getValue(name); - to_c.type = from_buff.type = ce.getValue("type", 0xC); - to_c.addr_to = ce.getValue("addr_c", 0x75); - from_buff.addr_to = ce.getValue("addr_pult", 0x15); - from_c = from_buff; - packetExtractor()->setSplitMode(PIPacketExtractor::Header); - packetExtractor()->setHeader(PIByteArray(&from_buff, 2)); - startReceive(); - } - - void sendCommand(int cmd) { - to_c.command = cmd; - send(); - } - EVENT2(eventReceived, int, event, PISystemTime, time) - - KX_C_Event from_c; - KX_C_Command to_c; - -private: - bool validate() { - if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false; - from_c = from_buff; - eventReceived(from_c.event, from_c.time); - return true; - } - bool aboutSend() { - //piCout << "send command" << to_c.command; - to_c.checksum = checksum_i(&to_c, sizeof(to_c) - 4); - return true; - } - - KX_C_Event from_buff; - -}; - - -#endif // KX_PROTOCOL_C_H diff --git a/kx_utils/kx_protocol_x.h b/kx_utils/kx_protocol_x.h deleted file mode 100644 index 4805a50..0000000 --- a/kx_utils/kx_protocol_x.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef KX_PROTOCOL_X_H -#define KX_PROTOCOL_X_H - -#include "piprotocol.h" - -#define KX_X_PACKET_NUM 20 -#define KX_X_COUNT 16384 - -extern double X[KX_X_COUNT]; - - -#pragma pack (push, 1) - - -struct KX_X_Header { - uchar type; - uchar addr_to; -}; - - - -struct KX_X_Numbers: KX_X_Header { - int x_num[KX_X_PACKET_NUM]; - uint checksum; -}; - - -struct KX_X_Data: KX_X_Header { - int x_num[KX_X_PACKET_NUM]; - double x_data[KX_X_PACKET_NUM]; - uint checksum; -}; - - -#pragma pack (pop) - - -// Client side - -class KX_Protocol_X: public PIProtocol -{ - PIOBJECT_SUBCLASS(KX_Protocol_X, PIProtocol) -public: - KX_Protocol_X(const PIString & config, const PIString & name = "x"): PIProtocol(config, name, &from_buff, 2, &(from_buff.x_num[0]), sizeof(from_buff) - 2, &to_pult, sizeof(to_pult)) { - PIConfig conf(config, PIIODevice::ReadOnly); - PIConfig::Entry ce = conf.getValue(name); - to_pult.type = from_buff.type = ce.getValue("type", 0xB); - to_pult.addr_to = ce.getValue("addr_pult", 0x15); - from_buff.addr_to = ce.getValue("addr_x", 0x75); - from_pult = from_buff; - for (int i = 0; i < KX_X_PACKET_NUM; ++i) - to_pult.x_num[i] = from_pult.x_num[i] = -1; - packetExtractor()->setSplitMode(PIPacketExtractor::Header); - packetExtractor()->setHeader(PIByteArray(&from_buff, 2)); - start(); - } - - KX_X_Numbers from_pult; - KX_X_Data to_pult; - -private: - bool validate() { - if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false; - from_pult = from_buff; - return true; - } - bool aboutSend() { - for (int i = 0; i < KX_X_PACKET_NUM; ++i) { - to_pult.x_num[i] = from_pult.x_num[i]; - to_pult.x_data[i] = from_pult.x_num[i] < 0 ? 0. : X[from_pult.x_num[i]]; - } - to_pult.checksum = checksum_i(&to_pult, sizeof(to_pult) - 4); - return true; - } - - KX_X_Numbers from_buff; - -}; - - - -// Pult side - -class __KX_Protocol_X: public PIProtocol -{ - PIOBJECT_SUBCLASS(__KX_Protocol_X, PIProtocol) -public: - __KX_Protocol_X(const PIString & config, const PIString & name): PIProtocol(config, name, &from_buff, 2, &(from_buff.x_num[0]), sizeof(from_buff) - 2, &to_x, sizeof(to_x)) { - PIConfig conf(config, PIIODevice::ReadOnly); - PIConfig::Entry ce = conf.getValue(name); - to_x.type = from_buff.type = ce.getValue("type", 0xB); - to_x.addr_to = ce.getValue("addr_x", 0x75); - from_buff.addr_to = ce.getValue("addr_pult", 0x15); - from_x = from_buff; - for (int i = 0; i < KX_X_PACKET_NUM; ++i) - to_x.x_num[i] = -1; - packetExtractor()->setSplitMode(PIPacketExtractor::Header); - packetExtractor()->setHeader(PIByteArray(&from_buff, 2)); - start(); - } - - KX_X_Data from_x; - KX_X_Numbers to_x; - -private: - bool validate() { - if (checksum_i(&from_buff, sizeof(from_buff) - 4) != from_buff.checksum) return false; - from_x = from_buff; - return true; - } - bool aboutSend() { - to_x.checksum = checksum_i(&to_x, sizeof(to_x) - 4); - return true; - } - - KX_X_Data from_buff; - -}; - - -#endif // KX_PROTOCOL_X_H diff --git a/kx_utils/kx_pult.conf b/kx_utils/kx_pult.conf deleted file mode 100644 index e69de29..0000000 diff --git a/kx_utils/kx_pult.cpp b/kx_utils/kx_pult.cpp deleted file mode 100644 index 2e5fab9..0000000 --- a/kx_utils/kx_pult.cpp +++ /dev/null @@ -1,848 +0,0 @@ -#include -#include -#include -#include "kx_pult.h" -#include "ui_kx_pult.h" -#include "piqt.h" -#include "qpiconfig.h" - - -bool isNormalDouble(const double & v) { -#ifdef WINDOWS - return true; -#else - return !isnan(v) && !isinf(v); -#endif -} - - -XCheck::XCheck(int index): QWidget() { - index_ = index; - setProperty("index", index); - setMouseTracking(true); - check.setText(QString::number(index + 1) + " "); - check.setAutoFillBackground(true); - spin.setMaximum(KX_X_COUNT - 1); - QBoxLayout * l = new QBoxLayout(QBoxLayout::LeftToRight); - l->setMargin(0); - l->setSpacing(2); - l->addWidget(&check); - l->addWidget(&spin); - setLayout(l); - //check.installEventFilter(this); - //spin.installEventFilter(this); - connect(&spin, SIGNAL(valueChanged(int)), this, SLOT(spinChanged(int))); - connect(&check, SIGNAL(toggled(bool)), this, SLOT(checkChanged_(bool))); -} - - -bool XCheck::eventFilter(QObject * o, QEvent * e) { - if (e->type() == QEvent::Enter) - qApp->postEvent(this, new QEvent(e->type())); - return QWidget::eventFilter(o, e); -} - - - - -KX_Pult::KX_Pult(): QMainWindow(), config_("kx_pult.conf"), name_x("x"), name_c("c"), -config(piqt(config_), QIODevice::ReadWrite), coeffs(config_, "k", true) { - //cout << sizeof(coeffsK.k_protocol->to_k) << endl; - ui = new Ui::KX_Pult(); - ui->setupUi(this); - ui->configWidget->setQPIConfig(&config); - ui->configWidget->expandAll(); - ui->list->viewport()->installEventFilter(this); - ui->treeK->viewport()->installEventFilter(this); - ui->scrollArea->setAutoFillBackground(false); - ui->scrollAreaWidgetContents->setAutoFillBackground(false); - ui->widget->setAutoFillBackground(false); - ui->label_17->setFixedSize(preferredIconSize(1.25, this)); - log_menu.addAction(ui->actionClear); - prot_x = 0; - prot_c = 0; - show_x = config.getValue("show_x", true); - if (!show_x) - ui->tabWidget->removeTab(1); - session.setFile("session_KX_Pult.conf"); - session.addEntry(this); - session.addEntry(ui->tabWidget); - session.addEntry(ui->checkKHideEmpty); - session.addEntry(ui->checkKHideNormal); - session.addEntry(ui->checkKHideExpressions); - session.addEntry(ui->checkKAutoCalculate); - needWrite = isPause = false; - timer = 0; - //x.resize(KX_X_PACKET_NUM); - //k.resize(K_NUM); - QPalette pal = palette(); - QColor col; - ui->graphic->setGraphicsCount(0); - for (int i = 0; i < KX_X_PACKET_NUM; ++i) { - XCheck * xc = new XCheck(i); - xc->installEventFilter(this); - connect(xc, SIGNAL(valueChanged(int, int)), this, SLOT(changedX(int,int))); - connect(xc, SIGNAL(checkChanged(int, bool)), this, SLOT(toggledX(int, bool))); - col = QColor::fromHsv(360 / KX_X_PACKET_NUM * i, 255, 200); - pal.setColor(QPalette::Button, col); - pal.setColor(QPalette::Window, col); - pal.setColor(QPalette::WindowText, invertColor(col)); - xc->check.setPalette(pal); - ui->graphic->addGraphic(QString::number(i), col); - ui->graphic->setGraphicVisible(false, i); - checks << xc; - ((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(xc, (i / 10) * 2, i % 10); - QLabel * lbl = new QLabel("0"); lbl->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); - values << lbl; - ((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(lbl, (i / 10) * 2 + 1, i % 10); - //xc->show(); - } - renew(); - icon_record = QIcon(":/icons/media-record.png"); - icon_stop = QIcon(":/icons/media-playback-stop.png"); - outdir = dir.absolutePath(); - if (!dir.exists()) dir.mkdir(outdir); - outdir += "/"; - ui->treeK->setColumnWidth(0, 60); - ui->treeK->setColumnWidth(1, 250); - ui->treeK->setColumnWidth(3, 100); - ui->treeK->setColumnWidth(4, 100); - //ui->table->setK(coeffsK.k()->data(), coeffsK.count()); - ui->spinSize->setValue(K.size_s()); - addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta); - CONNECT(void, &coeffs, sendFailed, this, pip_sendFailed); - CONNECT(void, &coeffs, sendSucceed, this, pip_sendSucceed); - CONNECT(void, &coeffs, receiveFailed, this, pip_receiveFailed); - CONNECT(void, &coeffs, receiveSucceed, this, pip_receiveSucceed); - connect(this, SIGNAL(q_k_sendFailed()), this, SLOT(k_sendFailed()), Qt::QueuedConnection); - connect(this, SIGNAL(q_k_sendSucceed()), this, SLOT(k_sendSucceed()), Qt::QueuedConnection); - connect(this, SIGNAL(q_k_receiveFailed()), this, SLOT(k_receiveFailed()), Qt::QueuedConnection); - connect(this, SIGNAL(q_k_receiveSucceed()), this, SLOT(k_receiveSucceed()), Qt::QueuedConnection); - connect(&timer_diag, SIGNAL(timeout()), this, SLOT(updateDiag())); - connect(&session, SIGNAL(loading(QPIConfig&)), this, SLOT(loading(QPIConfig&))); - connect(&session, SIGNAL(saving(QPIConfig&)), this, SLOT(saving(QPIConfig&))); - connect(ui->checkKHideEmpty, SIGNAL(toggled(bool)), this, SLOT(filterTree())); - connect(ui->checkKHideNormal, SIGNAL(toggled(bool)), this, SLOT(filterTree())); - connect(ui->checkKHideExpressions, SIGNAL(toggled(bool)), this, SLOT(filterTree())); - connect(ui->lineKSearch, SIGNAL(textChanged(QString)), this, SLOT(filterTree())); - session.load(); - updateKDesc(); - updateCDesc(); - timer_diag.start(40); - timer_update = startTimer(25); -} - - -KX_Pult::~KX_Pult() { - session.save(); -} - - -void KX_Pult::loading(QPIConfig & conf) { - kdesc_file = conf.getValue("kdesc_file").stringValue(); - cdesc_file = conf.getValue("cdesc_file").stringValue(); -} - - -void KX_Pult::saving(QPIConfig & conf) { - conf.setValue("kdesc_file", kdesc_file); - conf.setValue("cdesc_file", cdesc_file); -} - - -bool KX_Pult::eventFilter(QObject * o, QEvent * e) { - if (o == ui->list->viewport()) { - if (e->type() == QEvent::ContextMenu) { - clear_target = 0; - log_menu.popup(((QContextMenuEvent*)e)->globalPos()); - } - return QMainWindow::eventFilter(o, e); - } - if (o == ui->treeK->viewport()) { - if (e->type() == QEvent::ContextMenu) { - clear_target = 1; - log_menu.popup(((QContextMenuEvent*)e)->globalPos()); - } - return QMainWindow::eventFilter(o, e); - } - int ind = o->property("index").toInt(); - //qDebug() << "event" << i << e->type(); - switch (e->type()) { - case QEvent::Enter: - ui->graphic->setAutoUpdate(false); - for (int i = 0; i < KX_X_PACKET_NUM; ++i) - ui->graphic->setGraphicLineWidth(ind == i ? 3. : 1., i); - ui->graphic->setAutoUpdate(true); - ui->graphic->update(); - break; - case QEvent::Leave: - ui->graphic->setAutoUpdate(false); - for (int i = 0; i < KX_X_PACKET_NUM; ++i) - ui->graphic->setGraphicLineWidth(1., i); - ui->graphic->setAutoUpdate(true); - ui->graphic->update(); - break; - default: break; - } - return QMainWindow::eventFilter(o, e); -} - - -void KX_Pult::timerEvent(QTimerEvent * e) { - if (e->timerId() == timer_update) { - if (need_update) { - need_update = false; - ui->graphic->updateGraphics(); - } - } - if (e->timerId() == timer) { - static QString sPI = QString::number(atan(1) * 4., 'f', 14).leftJustified(14); - static int cnt = 0; - int si = qMax(cnt - 6, 0); - ++cnt; - cnt %= 23; - ui->labelWait->setText(QString(si, QChar(' ')) + sPI.mid(cnt - 6, 6).trimmed()); - if (!coeffs.isReady()) return; - //ui->table->setK(coeffsK.k()->data(), coeffsK.count()); - //ui->table->showK(); - } -} - - -void KX_Pult::setControlsEnable(bool enable) { - foreach (XCheck * i, checks) - i->setEnabled(enable); - ui->buttonShowAll->setEnabled(enable); - ui->buttonHideAll->setEnabled(enable); -} - - -void KX_Pult::setX(const KX_X_Data & data) { - if (!show_x) return; - //ui->graphic->lock(); - for (int i = 0; i < KX_X_PACKET_NUM; ++i) { - if (!isNormalDouble(data.x_data[i])) continue; - ui->graphic->addPoint(data.x_data[i], i, false); - values[i]->setText(QString("(%1): %2").arg(data.x_num[i]).arg(data.x_data[i])); - } - //ui->graphic->unlock(); - if (!isPause) { - need_update = true; - } - if (!needWrite) return; - stream << QString::number(tm.elapsed() / 1000., 'f', 3) << " " << QTime::currentTime().toString("hh:mm:ss") << " " << wcnt++; - for (int i = 0; i < KX_X_PACKET_NUM; ++i) - stream << " " << QString::number(data.x_data[i], 'f', 4); - stream << "\n"; -} - - -void KX_Pult::addToList(const QString & s, const QColor & c) { - ui->list->addItem(QDateTime::currentDateTime().toString("dd/MM/yyyy hh:ss - ") + s); - ui->list->item(ui->list->count() - 1)->setTextColor(c); - ui->list->scrollToBottom(); -} - - -void KX_Pult::on_buttonRecord_clicked() { - static bool isRec = false; - int cinc = 0; - QString str; - isRec = !isRec; - setControlsEnable(!isRec); - if (isRec) { - tm.restart(); - file.close(); - file.setFileName(outdir + getNewFileName(cinc)); - while (file.exists()) - file.setFileName(outdir + getNewFileName(cinc++)); - file.open(QIODevice::ReadWrite); - stream.setDevice(&file); - stream << "T V C"; - for (int i = 0; i < KX_X_PACKET_NUM; ++i) - stream << " X" + QString::number(checks[i]->spin.value()); - stream << "\n"; - wcnt = 0; - needWrite = true; - ui->buttonRecord->setText(trUtf8("Finish record")); - ui->buttonRecord->setIcon(icon_stop); - emit recordStarted(QFileInfo(file).completeBaseName()); - } else { - needWrite = false; - stream.setDevice(0); - file.close(); - ui->buttonRecord->setText(trUtf8("Start record")); - ui->buttonRecord->setIcon(icon_record); - emit recordStopped(QFileInfo(file).completeBaseName()); - } -} - - -void KX_Pult::on_actionClear_triggered() { - switch (clear_target) { - case 0: - ui->list->clear(); - break; - case 1: - clearSelected(); - break; - default: break; - } -} - - -void KX_Pult::clearSelected() { - QList si = ui->treeK->selectedItems(); - ui->treeK->setUpdatesEnabled(false); - ui->treeK->blockSignals(true); - foreach (QTreeWidgetItem * i, si) { - int ki = i->text(0).toInt(); - i->setText(2, ""); - coeffs.setFormula(ki, ""); - } - ui->treeK->blockSignals(false); - ui->treeK->setUpdatesEnabled(true); - if (ui->checkKAutoCalculate->isChecked()) { - QApplication::processEvents(); - calculate(); - } -} - - -QString KX_Pult::typeName(const QString & n) const { - if (n.isEmpty()) return ""; - switch (n[0].toLatin1()) { - case 'l': return trUtf8("list"); break; - case 'b': return trUtf8("bool"); break; - case 'n': return trUtf8("int"); break; - case 'f': return trUtf8("double"); break; - case 'c': return trUtf8("color"); break; - case 'r': return trUtf8("rect"); break; - case 'a': return trUtf8("rect"); break; - case 'p': return trUtf8("point"); break; - case 'v': return trUtf8("vector"); break; - case 'i': return trUtf8("IP"); break; - case 'e': return trUtf8("enum"); break; - case 'F': return trUtf8("file"); break; - case 'D': return trUtf8("dir"); break; - } - return ""; -} - - -void KX_Pult::received(bool ok) { - if (!ok) return; - setX(prot_x->from_x); -} - - -void KX_Pult::on_treeK_itemClicked(QTreeWidgetItem * item, int column) { - Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; - if (column == 2) f |= Qt::ItemIsEditable; - item->setFlags(f); -} - - -void KX_Pult::on_treeK_itemChanged(QTreeWidgetItem * item, int column) { - if (column != 2) return; - int ki = item->text(0).toInt(); - coeffs.setFormula(ki, piqt(item->text(column))); - if (ui->checkKAutoCalculate->isChecked()) - calculate(); -} - - -QString KX_Pult::getNewFileName(int inc) { - dir.refresh(); - dir.setNameFilters(QStringList("Experiment_*.txt")); - return "Experiment_" + QDateTime::currentDateTime().toString("dd_MM_yy__hh_mm_ss") + "__" + - QString::number(dir.entryList().count() + inc) + ".txt"; -} - - -void KX_Pult::on_buttonSendK_clicked() { - on_buttonWrite_clicked(); - coeffs.sendCoeffs(); - if (timer != 0) killTimer(timer); - timer = startTimer(100); -} - - -void KX_Pult::on_buttonReceiveK_clicked() { - coeffs.receiveCoeffs(); - if (timer != 0) killTimer(timer); - timer = startTimer(100); -} - - -void KX_Pult::on_buttonShowAll_clicked() { - for (int i = 0; i < KX_X_PACKET_NUM; ++i) { - checks[i]->check.setChecked(true); - //ui->graphic->setGraphicVisible(true, i); - } -} - - -void KX_Pult::on_buttonHideAll_clicked() { - for (int i = 0; i < KX_X_PACKET_NUM; ++i) { - checks[i]->check.setChecked(false); - //ui->graphic->setGraphicVisible(false, i); - } -} - - -void KX_Pult::on_buttonRead_clicked() { - coeffs.readCoeffs(); - addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta); - updateTree(); -} - - -void KX_Pult::on_buttonWrite_clicked() { - coeffs.writeCoeffs(); - addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta); -} - - -void KX_Pult::on_buttonResize_clicked() { - K.resize(ui->spinSize->value()); - coeffs.formulas.resize(ui->spinSize->value()); - ui->spinSize->setStyleSheet(""); - updateTree(); -} - - -void KX_Pult::on_buttonSetKDesc_clicked() { - QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with K description"), kdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)"); - if (ret.isEmpty()) return; - kdesc_file = QDir::current().relativeFilePath(ret); - updateKDesc(true); -} - - -void KX_Pult::on_buttonSetCDesc_clicked() { - QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with C description"), cdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)"); - if (ret.isEmpty()) return; - cdesc_file = QDir::current().relativeFilePath(ret); - updateCDesc(); -} - - -void KX_Pult::on_spinSize_valueChanged(int) { - ui->spinSize->setStyleSheet(""); -} - - -void KX_Pult::k_sendFailed() { - stopWait(); - addToList(trUtf8("K not sended"), Qt::darkRed); -} - - -void KX_Pult::k_sendSucceed() { - stopWait(); - addToList(trUtf8("K sended"), Qt::darkGreen); -} - - -void KX_Pult::k_receiveFailed() { - stopWait(); - addToList(trUtf8("K not received"), Qt::darkRed); -} - - -void KX_Pult::k_receiveSucceed() { - stopWait(); - addToList(trUtf8("K received"), Qt::darkGreen); - addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta); - ui->spinSize->setValue(K.size_s()); - updateTree(); - //ui->table->setK(coeffsK.k()->data(), coeffsK.count()); -} - - -void KX_Pult::on_spinBuffer_editingFinished() { - ui->graphic->setHistorySize(ui->spinBuffer->value()); -} - - -void KX_Pult::stopWait() { - killTimer(timer); - timer = 0; - ui->labelWait->setText(" "); -} - - -void KX_Pult::updateGraph() { - ui->graphic->updateGraphics(); -} - - -void KX_Pult::updateDiag() { - ui->labelKReceiver->setText(piqt(coeffs.k_protocol->receiverDeviceName() + " - " + coeffs.k_protocol->receiverDeviceState())); - ui->labelKSender->setText(piqt(coeffs.k_protocol->senderDeviceName())); - ui->spinKSended->setValue(coeffs.k_protocol->sendCount()); - ui->spinKReceived->setValue(coeffs.k_protocol->receiveCount()); - ui->spinKWrong->setValue(coeffs.k_protocol->wrongCount()); - ui->spinKMissed->setValue(coeffs.k_protocol->missedCount()); - ui->labelKType->setText("0x" + QString::number(coeffs.k_protocol->from_k.type, 16).toUpper().rightJustified(2, '0')); - ui->labelKAddrPult->setText("0x" + QString::number(coeffs.k_protocol->from_k.addr_to, 16).toUpper().rightJustified(2, '0')); - ui->labelKAddr->setText("0x" + QString::number(coeffs.k_protocol->to_k.addr_to, 16).toUpper().rightJustified(2, '0')); - - ui->labelXReceiver->setText(piqt(prot_x->receiverDeviceName() + " - " + prot_x->receiverDeviceState())); - ui->labelXSender->setText(piqt(prot_x->senderDeviceName())); - ui->spinXSended->setValue(prot_x->sendCount()); - ui->spinXReceived->setValue(prot_x->receiveCount()); - ui->spinXWrong->setValue(prot_x->wrongCount()); - ui->spinXMissed->setValue(prot_x->missedCount()); - ui->labelXType->setText("0x" + QString::number(prot_x->from_x.type, 16).toUpper().rightJustified(2, '0')); - ui->labelXAddrPult->setText("0x" + QString::number(prot_x->from_x.addr_to, 16).toUpper().rightJustified(2, '0')); - ui->labelXAddr->setText("0x" + QString::number(prot_x->to_x.addr_to, 16).toUpper().rightJustified(2, '0')); - - ui->labelCReceiver->setText(piqt(prot_c->receiverDeviceName() + " - " + prot_c->receiverDeviceState())); - ui->labelCSender->setText(piqt(prot_c->senderDeviceName())); - ui->spinCSended->setValue(prot_c->sendCount()); - ui->spinCReceived->setValue(prot_c->receiveCount()); - ui->spinCWrong->setValue(prot_c->wrongCount()); - ui->spinCMissed->setValue(prot_c->missedCount()); - ui->labelCType->setText("0x" + QString::number(prot_c->from_c.type, 16).toUpper().rightJustified(2, '0')); - ui->labelCAddrPult->setText("0x" + QString::number(prot_c->from_c.addr_to, 16).toUpper().rightJustified(2, '0')); - ui->labelCAddr->setText("0x" + QString::number(prot_c->to_c.addr_to, 16).toUpper().rightJustified(2, '0')); -} - - -int KX_Pult::parseHeader(const QString & file, QMap & map) { - map.clear(); - QFile f(file); - if (!f.open(QIODevice::ReadOnly)) { - updateTree(); - addToList(trUtf8("Update descriptions from \"%1\": error").arg(file), Qt::darkRed); - return 0; - } - addToList(trUtf8("Update descriptions from \"%1\"").arg(file), Qt::darkMagenta); - QTextStream s(&f); - int cind = -1; - bool found = false; - //qDebug() << "\nparse" << file; - while (!s.atEnd()) { - QString line = s.readLine().trimmed(), num, name, type, comment; - int i = line.indexOf("//"); - if (i >= 0) { - comment = line.right(line.length() - i - 2); - type = comment.left(1); - comment = comment.right(comment.length() - 1).trimmed(); - line = line.left(i).trimmed(); - } - if (line.isEmpty()) continue; - if (line.contains("enum")) { - found = true; - continue; - } - if (!found) continue; - if (line.contains('}')) - break; - line.remove(',').remove(' ').remove('\t'); - i = line.indexOf("="); - if (i >= 0) { - num = line.right(line.length() - i - 1).trimmed(); - line = line.left(i).trimmed(); - } - name = line; - if (num.isEmpty()) - ++cind; - else - cind = Q2PIString(num).toInt(); - KDesc kd; - kd.index = cind; - kd.name = name; - kd.type = type; - kd.comment = comment; - map[kd.index] = kd; - //qDebug() << name << cind << type << comment; - } - cind++; - return cind; -} - - -void KX_Pult::updateKDesc(bool ask_move) { - int cind = parseHeader(kdesc_file, kdesc); - if (K.size_s() < cind) { - ui->spinSize->setValue(cind); - ui->spinSize->setStyleSheet("background-color: rgb(220, 220, 255);"); - } - bool move = false; - if (ask_move) - move = (QMessageBox::question(this, "KX Pult", "Save values at associated names?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes); - updateTree(move); -} - - -void KX_Pult::updateCDesc() { - parseHeader(cdesc_file, cdesc); - updateCommands(); -} - - -bool stringComp(const QString & s1, const QString & s2) { - if (s1.size() != s2.size()) - return s1.size() > s2.size(); - return s1 > s2; -} - - -void KX_Pult::updateTree(bool move) { - int sp = ui->treeK->verticalScrollBar()->value(); - QApplication::setOverrideCursor(Qt::WaitCursor); - //qDebug() << "fill tree ..."; - QMap prev_val; - if (move) { - for (int i = 0; i < ui->treeK->topLevelItemCount(); ++i) { - QTreeWidgetItem * ti = ui->treeK->topLevelItem(i); - if (!ti->text(1).isEmpty()) - prev_val[ti->text(1)] = ti->text(2); - } - } - ui->treeK->clear(); - ui->treeK->setUpdatesEnabled(false); - eval.clearCustomVariables(); - for (int i = 0; i < K.size_s(); ++i) { - QTreeWidgetItem * ti = new QTreeWidgetItem(); - KDesc kd = kdesc[i]; - QString kn = QString("k%1").arg(i); - knames[kn] = i; - knames_sort << kn; - if (eval.content.findVariable(kn) < 0) - eval.content.addVariable(kn, 0., false); - if (!kd.name.isEmpty()) { - knames[kd.name] = i; - knames_sort << kd.name; - eval.content.addVariable(kd.name, 0., false); - } - if (move && !kd.name.isEmpty()) { - if (prev_val.contains(kd.name)) - coeffs.setFormula(i, Q2PIString(prev_val[kd.name])); - } - ti->setText(0, QString::number(i)); - ti->setText(1, kd.name); - ti->setText(2, PI2QString(coeffs.formula(i))); - ti->setText(3, QString::number(K[i])); - ti->setText(4, typeName(kd.type)); - ti->setText(5, kd.comment); - ui->treeK->addTopLevelItem(ti); - } - eval.content.sortVariables(); - //qDebug() << "fill tree ok"; - //qDebug() << "sort ..."; - qSort(knames_sort.begin(), knames_sort.end(), stringComp); - //qDebug() << "names" << knames_sort; - //qDebug() << "sort ok"; - QApplication::restoreOverrideCursor(); - ui->treeK->setUpdatesEnabled(true); - ui->treeK->verticalScrollBar()->setValue(sp); - calculate(); - filterTree(); -} - - -void KX_Pult::updateCommands() { - while (ui->layoutCommands->count() > 0) - delete ui->layoutCommands->itemAt(0)->widget(); - QMapIterator it(cdesc); - while (it.hasNext()) { - it.next(); - KDesc kd = it.value(); - QPushButton * b = new QPushButton(); - QString text = kd.name; - if (!kd.comment.isEmpty()) - text += QString("\n(%1)").arg(kd.comment); - b->setText(text); - b->setProperty("_command", kd.index); - connect(b, SIGNAL(clicked()), this, SLOT(commandClicked())); - ui->layoutCommands->addWidget(b); - } -} - - -void KX_Pult::filterTree() { - bool he = ui->checkKHideEmpty->isChecked(); - bool hn = ui->checkKHideNormal->isChecked(); - bool hs = ui->checkKHideExpressions->isChecked(); - bool ok = false; - QString fl = ui->lineKSearch->text(); - int lc = ui->treeK->topLevelItemCount(); - for (int i = 0; i < lc; ++i) { - QTreeWidgetItem * ti = ui->treeK->topLevelItem(i); - if (ti->text(1).isEmpty() && he) - ti->setHidden(true); - else - if (fl.isEmpty()) - ti->setHidden(false); - else - ti->setHidden(!ti->text(0).contains(fl, Qt::CaseInsensitive) && - !ti->text(1).contains(fl, Qt::CaseInsensitive) && - !ti->text(2).contains(fl, Qt::CaseInsensitive) && - !ti->text(3).contains(fl, Qt::CaseInsensitive) && - !ti->text(4).contains(fl, Qt::CaseInsensitive)); - if (hn) - if (ti->data(0, Qt::UserRole).toBool()) - ti->setHidden(true); - if (hs) { - ti->data(2, Qt::DisplayRole).toDouble(&ok); - if (!ok) - ti->setHidden(true); - } - } -} - - -void KX_Pult::calculate() { - calculated.clear(); - ui->treeK->setUpdatesEnabled(false); - ui->treeK->blockSignals(true); - QApplication::setOverrideCursor(Qt::WaitCursor); - progress(0, 100); - ui->buttonCalculate->setEnabled(false); - QApplication::processEvents(); - for (int i = 0; i < K.size_s(); ++i) { - ui->treeK->topLevelItem(i)->setToolTip(2, QString()); - ui->treeK->topLevelItem(i)->setToolTip(3, QString()); - } - for (int i = 0; i < K.size_s(); ++i) { - progress(i, K.size_s()); - calculateExpression(i, QVector()); - } - ui->buttonCalculate->setEnabled(true); - ui->progress->setValue(100); - QApplication::restoreOverrideCursor(); - ui->treeK->blockSignals(false); - ui->treeK->setUpdatesEnabled(true); -} - - -bool KX_Pult::calculateExpression(int i, QVector trace) { - if (calculated.contains(i)) return true; - trace << i; - QTreeWidgetItem * ti = ui->treeK->topLevelItem(i); - QString expr = ti->text(2); - if (expr.isEmpty() || expr == "0" || expr == "0,00000000" || expr == "0.00000000") { - markNormal(ti); - calculated << i; - K[i] = 0.; - ti->setText(3, "0"); - return true; - } - //ti->setToolTip(2, QString()); - if (!eval.check(expr)) { - markError(ti, eval.error()); - return false; - } - foreach (const QString & n, knames_sort) { - if (expr.contains(n)) { - int ki = knames.value(n, -1); - if (trace.contains(ki)) { - QString strace; - trace << ki; - for (int j = 0; j < trace.size(); ++j) { - //calculated << trace[j]; - if (j > 0) strace += " -> "; - strace += "k" + QString::number(trace[j]); - } - for (int j = 0; j < trace.size(); ++j) { - QTreeWidgetItem * pti = ui->treeK->topLevelItem(trace[j]); - markError(pti, QString("Circular dependency: %1!").arg(strace)); - } - return false; - } - if (ki < 0) { - markError(ti); - return false; - } - if (calculated.contains(ki)) { - eval.setVariable(n, K[ki]); - } else { - if (calculateExpression(ki, trace)) - eval.setVariable(n, K[ki]); - else { - markError(ti); - return false; - } - } - } - } - markNormal(ti); - calculated << i; - complexd ret = eval.evaluate(); - K[i] = ret.real(); - ti->setText(3, QString::number(K[i])); - return true; -} - - -void KX_Pult::markError(QTreeWidgetItem * item, const QString & tool_tip) { - int cc = item->columnCount(); - for (int i = 0; i < cc; ++i) - item->setBackgroundColor(i, QColor(255, 200, 200)); - if (item->toolTip(2).isEmpty()) - item->setToolTip(2, tool_tip); - if (item->toolTip(3).isEmpty()) - item->setToolTip(3, tool_tip); - item->setData(0, Qt::UserRole, false); - item->setText(3, "Error"); -} - - -void KX_Pult::markNormal(QTreeWidgetItem * item) { - int cc = item->columnCount(); - for (int i = 0; i < cc; ++i) - item->setBackground(i, Qt::NoBrush); - item->setToolTip(2, QString()); - item->setToolTip(3, QString()); - item->setData(0, Qt::UserRole, true); -} - - -void KX_Pult::progress(int val, int max) { - if (ctm.elapsed() < 50) return; - ctm.restart(); - ui->progress->setValue(qRound(val * 100. / max)); - QApplication::processEvents(); -} - - -void KX_Pult::renew(bool write) { - addToList(trUtf8("Update settings from \"%1\"").arg(PI2QString(config_)), Qt::darkMagenta); - dir.setPath(config.getValue("x.output_dir", "./Experiments/").stringValue()); - setWindowTitle(config.getValue("title", "Noname").stringValue() + trUtf8(" - KX Pult")); - //if (write) ui->configWidget->write(); - if (prot_x != 0) { - prot_x->stop(); - delete prot_x; - } - if (prot_c != 0) { - prot_c->stop(); - delete prot_c; - } - prot_x = new __KX_Protocol_X(config_, name_x); - prot_c = new __KX_Protocol_C(config_, name_c); - ui->graphic->setAutoXIncrement(prot_x->expectedFrequency() > 0. ? 1. / prot_x->expectedFrequency() : 1.); - coeffs.renew(); - CONNECT1(void, bool, prot_x, received, this, received); -} - - -void KX_Pult::toggledX(int index, bool on) { - ui->graphic->setGraphicVisible(on, index); -} - - -void KX_Pult::changedX(int index, int num) { - prot_x->to_x.x_num[index] = num; -} - - -void KX_Pult::commandClicked() { - QPushButton * b = qobject_cast(sender()); - if (!b) return; - prot_c->sendCommand(b->property("_command").toInt()); -} diff --git a/kx_utils/kx_pult.h b/kx_utils/kx_pult.h deleted file mode 100644 index 2e2d21b..0000000 --- a/kx_utils/kx_pult.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef KX_PULT_H -#define KX_PULT_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "kx_coeffs.h" -#include "kx_protocol_x.h" -#include "kx_protocol_c.h" -#include "piqt.h" -#include "session_manager.h" -#include "qpievaluator.h" - - -class XCheck: public QWidget { - Q_OBJECT -public: - explicit XCheck(int index); - QCheckBox check; - QSpinBox spin; -private: - bool eventFilter(QObject * o, QEvent * e); - int index_; -private slots: - void spinChanged(int value) {check.setChecked(true); emit valueChanged(index_, value);} - void checkChanged_(bool value) {emit checkChanged(index_, value);} -signals: - void valueChanged(int index, int value); - void checkChanged(int index, bool on); -}; - - -namespace Ui { - class KX_Pult; -}; - -class KX_Pult: public QMainWindow, public PIObject -{ - Q_OBJECT - PIOBJECT(KX_Pult) -public: - KX_Pult(); - ~KX_Pult(); - -private: - struct KDesc { - KDesc() {index = -1;} - int index; - QString name; - QString type; - QString comment; - QString value; - }; - - bool eventFilter(QObject * o, QEvent * e); - void timerEvent(QTimerEvent * ); - void setControlsEnable(bool enable); - void setX(const KX_X_Data & data); - void addToList(const QString & s, const QColor & c); - QString getNewFileName(int inc); - QColor invertColor(QColor col) {return QColor(255 - col.red(), 255 - col.green(), 255 - col.blue());} - void stopWait(); - bool calculateExpression(int i, QVector trace); - void markError(QTreeWidgetItem * item, const QString & tool_tip = QString()); - void markNormal(QTreeWidgetItem * item); - void progress(int val, int max); - void clearSelected(); - QString typeName(const QString & n) const; - int parseHeader(const QString & file, QMap & map); - - EVENT_HANDLER1(void, received, bool, ok); - EVENT_HANDLER(void, pip_sendFailed) {emit q_k_sendFailed();} - EVENT_HANDLER(void, pip_sendSucceed) {emit q_k_sendSucceed();} - EVENT_HANDLER(void, pip_receiveFailed) {emit q_k_receiveFailed();} - EVENT_HANDLER(void, pip_receiveSucceed) {emit q_k_receiveSucceed();} - - QVector checks; - QVector values; - - Ui::KX_Pult * ui; - PIString config_, name_x, name_c; - QDir dir; - QString outdir, kdesc_file, cdesc_file; - QFile file; - QTime tm, ctm; - QIcon icon_record, icon_stop; - QTextStream stream; - QTimer timer_diag; - QMap kdesc, cdesc; - QMap knames; - QSet calculated; - QStringList knames_sort; - QPIEvaluator eval; - SessionManager session; - QPIConfig config; - QMenu log_menu; - //QVector k, x; - KX_Coefficients coeffs; - __KX_Protocol_X * prot_x; - __KX_Protocol_C * prot_c; - int csize, wcnt, timer, timer_update, clear_target; - bool needWrite, isPause, need_update, show_x; - -private slots: - void loading(QPIConfig & conf); - void saving(QPIConfig & conf); - void updateGraph(); - void updateDiag(); - void updateKDesc(bool ask_move = false); - void updateCDesc(); - void updateTree(bool move = false); - void updateCommands(); - void filterTree(); - void calculate(); - void renew(bool write = true); - void toggledX(int index, bool on); - void changedX(int index, int num); - void commandClicked(); - void k_sendFailed(); - void k_sendSucceed(); - void k_receiveFailed(); - void k_receiveSucceed(); - void on_spinBuffer_editingFinished(); - void on_buttonSendK_clicked(); - void on_buttonReceiveK_clicked(); - void on_buttonShowAll_clicked(); - void on_buttonHideAll_clicked(); - void on_buttonRead_clicked(); - void on_buttonWrite_clicked(); - void on_buttonResize_clicked(); - void on_buttonSetKDesc_clicked(); - void on_buttonReparseKDesc_clicked() {updateKDesc(true);} - void on_buttonSetCDesc_clicked(); - void on_buttonReparseCDesc_clicked() {updateCDesc();} - void on_buttonCalculate_clicked() {calculate();} - void on_buttonApply_clicked() {renew();} - void on_spinSize_valueChanged(int); - void on_buttonPause_toggled(bool on) {isPause = on;} - void on_buttonRecord_clicked(); - void on_treeK_itemClicked(QTreeWidgetItem * item, int column); - void on_treeK_itemChanged(QTreeWidgetItem * item, int column); - void on_actionClear_triggered(); - -signals: - void q_k_sendFailed(); - void q_k_sendSucceed(); - void q_k_receiveFailed(); - void q_k_receiveSucceed(); - void recordStarted(const QString & fileName); - void recordStopped(const QString & fileName); - -}; - -#endif // KX_PULT_H - diff --git a/kx_utils/kx_pult.qrc b/kx_utils/kx_pult.qrc deleted file mode 100644 index 99f4688..0000000 --- a/kx_utils/kx_pult.qrc +++ /dev/null @@ -1,40 +0,0 @@ - - - icons/dialog-close.png - icons/edit-clear-.png - icons/edit-guides.png - icons/view-grid.png - icons/zoom-fit-best.png - icons/configure.png - icons/alpha.png - icons/document-save.png - icons/edit-clear-locationbar-rtl.png - icons/edit-find.png - icons/list-add.png - icons/edit-delete.png - icons/item-add.png - icons/item.png - icons/node-add.png - icons/node.png - icons/edit-copy.png - icons/edit-paste.png - icons/expand_s_x.png - icons/expand_s_y.png - icons/expand_x.png - icons/expand_y.png - icons/media-playback-pause.png - icons/media-playback-stop.png - icons/media-record.png - icons/application-exit.png - icons/document-save-.png - icons/view-refresh.png - icons/document-open.png - icons/archive-extract.png - icons/document-export.png - icons/document-import.png - icons/zoom-fit-height.png - icons/layer-visible-off.png - icons/layer-visible-on.png - icons/accessories-calculator.png - - diff --git a/kx_utils/kx_pult.ui b/kx_utils/kx_pult.ui deleted file mode 100644 index ab30c52..0000000 --- a/kx_utils/kx_pult.ui +++ /dev/null @@ -1,1311 +0,0 @@ - - - KX_Pult - - - - 0 - 0 - 1759 - 852 - - - - KX Pult - - - - - - - 0 - - - - Coefficients (K) - - - - - - - - Reparse K desc - - - - :/icons/view-refresh.png:/icons/view-refresh.png - - - - - - - Resize - - - - :/icons/zoom-fit-height.png:/icons/zoom-fit-height.png - - - - - - - Read file K - - - - :/icons/archive-extract.png:/icons/archive-extract.png - - - - - - - Send - - - - :/icons/document-export.png:/icons/document-export.png - - - - - - - Write file K - - - - :/icons/document-save-.png:/icons/document-save-.png - - - - - - - - 0 - 0 - - - - Qt::CustomContextMenu - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::NoSelection - - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - - - - - - - Receive - - - - :/icons/document-import.png:/icons/document-import.png - - - - - - - Set K desc file ... - - - - :/icons/document-open.png:/icons/document-open.png - - - - - - - 65536 - - - - - - - - 0 - 0 - - - - - 200 - 0 - - - - - - - - - - - - - - - Hide empty - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 20 - - - - - - - - Hide expressions - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 20 - - - - - - - - Hide without errors - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 20 - - - - - - - - :/icons/edit-find.png - - - true - - - Qt::AlignCenter - - - - - - - Search: - - - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 40 - 20 - - - - - - - - Auto calculate - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 20 - - - - - - - - Calculate - - - Calculate - - - - :/icons/accessories-calculator.png:/icons/accessories-calculator.png - - - - - - - 100 - - - Calculate %p% - - - - - - - - - Qt::CustomContextMenu - - - QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed - - - true - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::ScrollPerPixel - - - QAbstractItemView::ScrollPerPixel - - - false - - - false - - - 6 - - - 200 - - - 20 - - - - Index - - - - - Name - - - - - Expression - - - - - Calculated - - - - - Type - - - - - Comment - - - - - - - - - Commands (C) - - - - - - - - Set C desc file ... - - - - :/icons/document-open.png:/icons/document-open.png - - - - - - - Reparse C desc - - - - :/icons/view-refresh.png:/icons/view-refresh.png - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - Commands - - - - - - QFrame::NoFrame - - - true - - - - - 0 - 0 - 1370 - 655 - - - - - 0 - - - 0 - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 66 - 441 - - - - - - - - - - - - - - - - - - Graphics (X) - - - - - - - 10 - - - - - - - - - - - 0 - 0 - - - - Show all - - - - :/icons/layer-visible-on.png:/icons/layer-visible-on.png - - - - - - - - 0 - 0 - - - - Hide all - - - - :/icons/layer-visible-off.png:/icons/layer-visible-off.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Start record - - - - :/icons/media-record.png:/icons/media-record.png - - - - - - - - - - - Pause - - - - :/icons/media-playback-pause.png:/icons/media-playback-pause.png - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Show - - - - - - - - 0 - 0 - - - - с - - - 1 - - - 0.100000000000000 - - - 9999.000000000000000 - - - 10.000000000000000 - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 40 - 20 - - - - - - - - Save - - - - - - - - 0 - 0 - - - - с - - - 1 - - - 0.100000000000000 - - - 9999.000000000000000 - - - 60.000000000000000 - - - - - - - - - Graphic::Autofit|Graphic::BorderInputs|Graphic::Clear|Graphic::Configure|Graphic::CursorAxis|Graphic::Grid|Graphic::OnlyExpandX|Graphic::OnlyExpandY|Graphic::Save - - - false - - - false - - - 60.000000000000000 - - - 10.000000000000000 - - - - - - - - Configuration - - - - - - K - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - receiver: - - - - - - - - - - - - - - sender: - - - - - - - - - - - - - - sended count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - wrong received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - type: - - - - - - - - - - - - - - address K: - - - - - - - - - - - - - - - - - - - - - missed received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - address pult: - - - - - - - - - - X - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - receiver: - - - - - - - - - - - - - - sender: - - - - - - - - - - - - - - type: - - - - - - - - - - - - - - address X: - - - - - - - address pult: - - - - - - - - - - - - - - sended count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - wrong received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - - - - - - - - missed received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - - - - C - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - receiver: - - - - - - - - - - - - - - sender: - - - - - - - - - - - - - - type: - - - - - - - - - - - - - - address C: - - - - - - - address pult: - - - - - - - - - - - - - - sended count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - wrong received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - - - - - - - - missed received count: - - - - - - - true - - - 0 - - - 1999999999 - - - - - - - - - - - - true - - - true - - - true - - - false - - - 20 - - - - - - - Apply - - - - :/icons/document-save-.png:/icons/document-save-.png - - - - - - - - - - - - - - - :/icons/edit-clear-.png:/icons/edit-clear-.png - - - Clear - - - - - - Graphic - QFrame -
graphic.h
-
- - CLineEdit - QLineEdit -
clineedit.h
-
- - QPIConfigWidget - QTreeWidget -
qpiconfigwidget.h
-
-
- - - - - - spinHistory - valueChanged(double) - graphic - setMaxVisibleTime(double) - - - 919 - 107 - - - 932 - 132 - - - - -
diff --git a/kx_utils/main_kx_pult.cpp b/kx_utils/main_kx_pult.cpp deleted file mode 100644 index e5c1786..0000000 --- a/kx_utils/main_kx_pult.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include "kx_pult.h" - - -int main(int argc, char *argv[]) { - QApplication a(argc, argv); - KX_Pult w; - w.show(); - return a.exec(); -} diff --git a/kx_utils/make_lib.bat b/kx_utils/make_lib.bat deleted file mode 100644 index 0148a43..0000000 --- a/kx_utils/make_lib.bat +++ /dev/null @@ -1 +0,0 @@ -cmake -G "MinGW Makefiles" -DLIB=1 && make install . %* diff --git a/kx_utils/piprotocol.cpp b/kx_utils/piprotocol.cpp deleted file mode 100644 index 9b9f048..0000000 --- a/kx_utils/piprotocol.cpp +++ /dev/null @@ -1,718 +0,0 @@ -/* - PIP - Platform Independent Primitives - Protocol, input/output channel (COM, UDP) - Copyright (C) 2020 Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "piprotocol.h" - -/** \class PIProtocol - * \brief - * \details - * \section PIProtocol_sec0 Synopsis - * - * - * - * */ - - /// DEPRECATED -PIProtocol::PIProtocol(const PIString & config, const PIString & name_, void * recHeaderPtr, int recHeaderSize, void * recDataPtr, int recDataSize, void * sendDataPtr_, int sendDataSize_): PIObject() { - init(); - protName = name_; - PIObject::setName(name_); - PIConfig conf(config, PIIODevice::ReadOnly); - if (!conf.isOpened()) { - piCoutObj << "Can`t open \"" << config << "\"!"; - devReceiverState = devSenderState = "Config error"; - return; - } - PIConfig::Entry & b(conf.getValue(name_)), - & rb(b.getValue("receiver")), - & sb(b.getValue("sender")); - - init_receiver(b, rb, config); - init_sender(b, sb, config); - - headerPtr = (uchar * )recHeaderPtr; - headerSize = recHeaderSize; - dataPtr = (uchar * )recDataPtr; - dataSize = recDataSize; - sendDataPtr = (uchar * )sendDataPtr_; - sendDataSize = sendDataSize_; - packet_ext->setHeader(PIByteArray(recHeaderPtr, recHeaderSize)); - packet_ext->setPayloadSize(recDataSize); - packet_ext->setPacketSize(recDataSize); - packet_ext->setSplitMode(PIPacketExtractor::Header); - bool null_h = (recHeaderPtr == 0 || recHeaderSize == 0), null_d = (recDataPtr == 0 || recDataSize == 0); - if (null_h && null_d) packet_ext->setSplitMode(PIPacketExtractor::None); - else { - if (null_h) packet_ext->setSplitMode(PIPacketExtractor::Size); - } -} - - -PIProtocol::~PIProtocol() { - delete diagTimer; - delete sendTimer; - delete secTimer; - delete packet_ext; - if (eth != 0) delete eth; - if (ser != 0) delete ser; -} - - -void PIProtocol::init() { - packet_ext = new PIPacketExtractor(0, PIPacketExtractor::None); - packet_ext->setThreadedReadData(this); - packet_ext->setThreadedReadSlot(receiveEvent); - packet_ext->setHeaderCheckSlot(headerValidateEvent); - packet_ext->setName("__S__PIProtocol::packet_ext"); - work = new_mp_prot = false; - eth = 0; - ser = 0; - ret_func = 0; - mp_owner = 0; - net_diag = PIProtocol::Unknown; - cur_pckt = 0; - packets[0] = packets[1] = pckt_cnt = pckt_cnt_max = 0; - diagTimer = 0; - timeout_ = 3.f; - sendTimer = new PITimer(sendEvent, this); - diagTimer = new PITimer(diagEvent, this); - secTimer = new PITimer(secEvent, this); - sendTimer->setName("__S__PIProtocol::sendTimer"); - diagTimer->setName("__S__PIProtocol::diagTimer"); - secTimer->setName("__S__PIProtocol::secTimer"); - wrong_count = receive_count = send_count = missed_count = 0; - packets_in_sec = packets_out_sec = bytes_in_sec = bytes_out_sec = 0; - immediate_freq = integral_freq = ifreq = 0.f; - headerPtr = dataPtr = sendDataPtr = 0; - headerSize = dataSize = sendDataSize = 0; - type_rec = type_send = PIProtocol::None; - devSenderState = devReceiverState = "Unknown"; - devSenderName = devReceiverName = "no device"; - secTimer->start(1000.); - /*addEvent("receiver started"); - addEvent("receiver stopped"); - addEvent("sender started"); - addEvent("sender stopped"); - addEvent("received"); - addEvent("quality changed"); - addEventHandler(HANDLER(PIProtocol, startReceive)); - addEventHandler(HANDLER(PIProtocol, startSend)); - addEventHandler(HANDLER(PIProtocol, start)); - addEventHandler(HANDLER(PIProtocol, stopReceive)); - addEventHandler(HANDLER(PIProtocol, stopSend)); - addEventHandler(HANDLER(PIProtocol, stop));*/ -} - - -void PIProtocol::init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config) { - int ps, gps; - bool ok, gok, flag, gflag, has_dev = false; - float freq, gfreq; - PIFlags pp(0); - PIString dev, gdev; - - if (sb.isEntryExists("ip") && sb.isEntryExists("device")) { - piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - dev = sb.getValue("ip", "", &ok); - gdev = b.getValue("ip", "", &gok); - has_dev = false; - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - ps = sb.getValue("port", 0, &ok); - gps = b.getValue("port", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous send port in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - eth->setName("__S__PIProtocol::eth"); - setSenderAddress(dev, ps); - //setReceiverAddress(dev, ps); - has_dev = true; - flag = sb.getValue("reconnectEnabled", true, &ok); - gflag = b.getValue("reconnectEnabled", true, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenEnabled(flag); - } - freq = sb.getValue("reconnectTimeout", 1., &ok); - gfreq = b.getValue("reconnectTimeout", 1., &gok); - if (ok || gok) { - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenTimeout(freq * 1000); - } - /*if (sendDataPtr_ == 0) - piCoutObj << "Warning: null send data pointer!"; - if (sendDataSize_ == 0) - piCoutObj << "Warning: null send data size!";*/ - } else { - piCoutObj << "Can`t find \"" << name() << ".sender.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - } - dev = sb.getValue("device", "", &ok); - gdev = b.getValue("device", "", &gok); - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous sender type in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - ps = sb.getValue("speed", 0, &ok); - gps = b.getValue("speed", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous send \"speed\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - flag = sb.getValue("parity", false, &ok); - gflag = b.getValue("parity", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous send \"parity\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - pp.setFlag(PISerial::ParityControl, flag); - } - flag = sb.getValue("twoStopBits", false, &ok); - gflag = b.getValue("twoStopBits", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous send \"twoStopBits\" parity in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - pp.setFlag(PISerial::TwoStopBits, flag); - } - } else { - piCoutObj << "Can`t find \"" << name() << ".sender.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - type_send = PIProtocol::Serial; - if (ser == 0) ser = new PISerial(dev); - ser->setName("__S__PIProtocol::ser"); - setSenderDevice(dev, (PISerial::Speed)ps); - ser->setOutSpeed((PISerial::Speed)ps); - ser->setParameters(pp); - has_dev = true; - /*if (sendDataPtr_ == 0) - piCoutObj << "Warning: null send data pointer!"; - if (sendDataSize_ == 0) - piCoutObj << "Warning: null send data size!";*/ - } - freq = sb.getValue("frequency", -1.f, &ok); - gfreq = b.getValue("frequency", -1.f, &gok); - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous sender frequency in \"" << config << "\"!"; - devSenderState = "Config error"; - return; - } - if (freq > 0.f && !has_dev) - piCoutObj << "Warning: no sender device and not null send frequency!"; - setSenderFrequency(freq); -} - - -void PIProtocol::init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config) { - int ps, gps; - bool ok, gok, flag, gflag, has_dev = false; - float freq, gfreq; - PIFlags pp(0); - PIString dev, gdev; - - if (rb.isEntryExists("ip") && rb.isEntryExists("device")) { - piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - dev = rb.getValue("ip", "", &ok); - gdev = b.getValue("ip", "", &gok); - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - ps = rb.getValue("port", 0, &ok); - gps = b.getValue("port", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous receive port in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - type_rec = PIProtocol::Ethernet; - eth = new PIEthernet(); - eth->setName("__S__PIProtocol::eth"); - packet_ext->setDevice(eth); - //setSenderAddress(dev, ps); - setReceiverAddress(dev, ps); - has_dev = true; - flag = rb.getValue("reconnectEnabled", true, &ok); - gflag = b.getValue("reconnectEnabled", true, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous \"reconnectEnabled\" flag in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenEnabled(flag); - } - freq = rb.getValue("reconnectTimeout", 1., &ok); - gfreq = b.getValue("reconnectTimeout", 1., &gok); - if (ok || gok) { - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous \"reconnectTimeout\" value in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - eth->setReopenTimeout(freq * 1000); - } - /*if (recDataPtr == 0) - piCoutObj << "Warning: null receive data pointer!"; - if (recDataSize == 0) - piCoutObj << "Warning: null receive data size!";*/ - } else { - piCoutObj << "Can`t find \"" << name() << ".receiver.port\" or \"" << name() << ".port\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - } - dev = rb.getValue("device", "", &ok); - gdev = b.getValue("device", "", &gok); - if (ok || gok) { - if (gok && !ok) dev = gdev; - if (gok && ok && (dev != gdev)) { - piCoutObj << "Ambiguous receiver type in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - ps = rb.getValue("speed", 0, &ok); - gps = b.getValue("speed", 0, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous receive \"speed\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - flag = rb.getValue("parity", false, &ok); - gflag = b.getValue("parity", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous receive \"parity\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - pp.setFlag(PISerial::ParityControl, flag); - } - flag = rb.getValue("twoStopBits", false, &ok); - gflag = b.getValue("twoStopBits", false, &gok); - if (ok || gok) { - if (gok && !ok) flag = gflag; - if (gok && ok && (flag != gflag)) { - piCoutObj << "Ambiguous receive \"twoStopBits\" parity in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - pp.setFlag(PISerial::TwoStopBits, flag); - } - type_rec = PIProtocol::Serial; - type_send = PIProtocol::Serial; - ser = new PISerial(dev); - ser->setName("__S__PIProtocol::ser"); - packet_ext->setDevice(ser); - //setSenderDevice(dev, (PISerial::Speed)ps); - setReceiverDevice(dev, (PISerial::Speed)ps); - ser->setInSpeed((PISerial::Speed)ps); - ser->setParameters(pp); - ps = rb.getValue("vtime", 1, &ok); - gps = b.getValue("vtime", 1, &gok); - if (ok || gok) { - if (gok && !ok) ps = gps; - if (gok && ok && (ps != gps)) { - piCoutObj << "Ambiguous receive \"vtime\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - ser->setVTime(ps); - } - has_dev = true; - /*if (recDataPtr == 0) - piCoutObj << "Warning: null receive data pointer!"; - if (recDataSize == 0) - piCoutObj << "Warning: null receive data size!";*/ - } else { - piCoutObj << "Can`t find \"" << name() << ".receiver.speed\" or \"" << name() << ".speed\" in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - } - freq = rb.getValue("frequency", -1.f, &ok); - gfreq = b.getValue("frequency", -1.f, &gok); - if (gok && !ok) freq = gfreq; - if (gok && ok && (freq != gfreq)) { - piCoutObj << "Ambiguous expected frequency in \"" << config << "\"!"; - devReceiverState = "Config error"; - return; - } - if (freq > 0.f && !has_dev) - piCoutObj << "Warning: no receiver device and not null expected frequency!"; - float tm = b.getValue("disconnectTimeout", 3.f); - if (tm <= 0.f) - piCoutObj << "Warning: diconnect timeout <= 0 s!"; - timeout_ = (tm < 0.f) ? 0.f : tm; - setExpectedFrequency(freq); -} - - -void PIProtocol::setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force) { - if (force) { - type_send = type_rec = PIProtocol::Serial; - if (ser == 0) { - ser = new PISerial(); - ser->setName("__S__PIProtocol::ser"); - packet_ext->setDevice(ser); - } - } - if (type_rec == PIProtocol::Serial && ser != 0) { - ser->setDevice(device); - ser->setSpeed(speed); - devReceiverName = device; - devSenderName = device; - } -} - - -void PIProtocol::setReceiverAddress(const PIString & ip, int port, bool force) { - if (force) { - type_rec = PIProtocol::Ethernet; - if (eth == 0) { - eth = new PIEthernet(); - eth->setName("__S__PIProtocol::eth"); - packet_ext->setDevice(eth); - } - } - if (type_rec == PIProtocol::Ethernet && eth != 0) { - eth->setReadAddress(ip, port); - if (ip.trimmed().isEmpty()) devReceiverName = "no ip"; - else devReceiverName = ip + ":" + PIString::fromNumber(port); - } -} - - -void PIProtocol::setSenderDevice(const PIString & device, PISerial::Speed speed, bool force) { - if (force) { - type_send = type_rec = PIProtocol::Serial; - if (ser == 0) ser = new PISerial(); - ser->setName("__S__PIProtocol::ser"); - } - if (type_send == PIProtocol::Serial && ser != 0) { - ser->setDevice(device); - ser->setSpeed(speed); - ser->open(); - devSenderName = device; - } -} - - -void PIProtocol::setSenderAddress(const PIString & ip, int port, bool force) { - if (force) { - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - eth->setName("__S__PIProtocol::eth"); - } - if (type_send == PIProtocol::Ethernet && eth != 0) { - eth->setSendAddress(ip, port); - if (ip.isEmpty()) devSenderName = "no ip"; - else devSenderName = ip + ":" + PIString::fromNumber(port); - } -} - - -void PIProtocol::setSenderIP(const PIString & ip, bool force) { - if (force) { - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - } - if (type_send == PIProtocol::Ethernet && eth != 0) { - eth->setSendIP(ip); - if (ip.isEmpty()) devSenderName = "no ip"; - else devSenderName = ip + ":" + PIString::fromNumber(eth->sendPort()); - } -} - - -void PIProtocol::setSenderPort(int port, bool force) { - if (force) { - type_send = PIProtocol::Ethernet; - if (eth == 0) eth = new PIEthernet(); - eth->setName("__S__PIProtocol::eth"); - } - if (type_send == PIProtocol::Ethernet && eth != 0) { - eth->setSendPort(port); - if (eth->sendIP().isEmpty()) devSenderName = "no ip"; - else devSenderName = eth->sendIP() + ":" + PIString::fromNumber(port); - } -} - - -void PIProtocol::setExpectedFrequency(float frequency) { - exp_freq = frequency; - changeDisconnectTimeout(); -} - - -void PIProtocol::changeDisconnectTimeout() { - pckt_cnt_max = int(piRound(timeout_ * exp_freq)); - if (pckt_cnt_max < 3) pckt_cnt_max = 3; - last_packets.resize(pckt_cnt_max); -} - - -void PIProtocol::startReceive(float exp_frequency) { - if (exp_frequency > 0.f) exp_freq = exp_frequency; - //if (type_rec == PIProtocol::Serial) ser->start(); - //if (type_rec == PIProtocol::Ethernet) eth->start(); - packet_ext->startThreadedRead(); - msleep(1); - check_state(); - if (exp_freq <= 0.f) return; - setExpectedFrequency(exp_freq); - diagTimer->start(1000. / exp_freq); - diag_tm.reset(); - receiverStarted(); -} - - -void PIProtocol::startSend(float frequency) { - //cout << "** start send " << send_freq << ", " << frequency << endl; - if (frequency > 0.f) send_freq = frequency; - msleep(1); - check_state(); - if (send_freq <= 0.f) return; - sendTimer->start(1000. / send_freq); - diag_tm.reset(); - senderStarted(); -} - - -void PIProtocol::stopReceive() { - //if (type_rec == PIProtocol::Serial) ser->stop(); - //if (type_rec == PIProtocol::Ethernet) eth->stop(); - packet_ext->stop(); - diagTimer->stop(); - receiverStopped(); -} - - -bool PIProtocol::receiveEvent(void * t, uchar * data, int size) { - PIProtocol * p = (PIProtocol * )t; - if (!p->receive(data, size)) return false; - p->work = true; - //p->lock(); - if (p->validate()) { - p->received(true); - //p->unlock(); - p->ifreq = p->diag_tm.elapsed_m(); - if (p->ifreq > 0.) p->ifreq = 1000. / p->ifreq; - p->diag_tm.reset(); - p->receive_count++; - p->packets_in_sec++; - p->bytes_in_sec += size; - p->cur_pckt = 1; - if (p->ret_func != 0) p->ret_func(p); - if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, true, data, size); - return true; - } - p->received(false); - //p->unlock(); - p->wrong_count++; - if (p->mp_owner != 0) PIMultiProtocolBase::receiveEvent(p->mp_owner, p, false, data, size); - return false; -} - - -void PIProtocol::diagEvent(void * t, int) { - PIProtocol * p = (PIProtocol * )t; - p->calc_freq(); - p->calc_diag(); - p->check_state(); - if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); -} - - -void PIProtocol::secEvent(void * t, int ) { - PIProtocol * p = (PIProtocol * )t; - p->speedIn = PIString::readableSize(p->bytes_in_sec) + "/s"; - p->speedOut = PIString::readableSize(p->bytes_out_sec) + "/s"; - p->bytes_in_sec = p->bytes_out_sec = p->packets_in_sec = p->packets_out_sec = 0; - if (p->ser != 0) p->missed_count = p->packet_ext->missedPackets(); -} - - -void PIProtocol::calc_diag() { - PIProtocol::Quality diag; - if (!work) { - diag = PIProtocol::Unknown; - return; - } - if (pckt_cnt < pckt_cnt_max) { - last_packets[pckt_cnt] = cur_pckt; - pckt_cnt++; - } else { - packets[(int)last_packets.back()]--; - if (!last_packets.isEmpty()) last_packets.pop_back(); - last_packets.push_front(cur_pckt); - } - packets[(int)cur_pckt]++; - cur_pckt = 0; - float good_percents; - good_percents = (float)packets[1] / pckt_cnt * 100.f; - if (good_percents == 0.f) diag = PIProtocol::Failure; - else if (good_percents <= 20.f) diag = PIProtocol::Bad; - else if (good_percents > 20.f && good_percents <= 80.f) diag = PIProtocol::Average; - else diag = PIProtocol::Good; - if (diag != net_diag) { - qualityChanged(diag, net_diag); - net_diag = diag; - } -} - - -void PIProtocol::calc_freq() { - float tf;// = float(1000.f / diagTimer->elapsed_m()); - tf = immediate_freq = ifreq; - ifreq = 0.f; - if (last_freq.size_s() >= pckt_cnt_max && last_freq.size_s() > 0) last_freq.pop_front(); - last_freq.push_back(tf); - tf = last_freq[0]; - for (uint i = 1; i < last_freq.size(); ++i) - tf += last_freq[i]; - integral_freq = tf / last_freq.size(); -} - - -void PIProtocol::check_state() { - if (type_rec == PIProtocol::Serial) { - if (ser != 0) { - if (ser->isOpened()) devReceiverState = "Opened"; - else devReceiverState = "Not opened"; - } - else devReceiverState = "Not exists"; - } - if (type_rec == PIProtocol::Ethernet) { - if (eth != 0) { - if (eth->isOpened()) devReceiverState = "Opened"; - else devReceiverState = "Not opened"; - } - else devReceiverState = "Not exists"; - } - if (type_send == PIProtocol::Serial) { - if (ser != 0) { - if (ser->isOpened()) devSenderState = "Opened"; - else devSenderState = "Not opened"; - } - else devSenderState = "Not exists"; - } - if (type_send == PIProtocol::Ethernet) { - if (eth != 0) { - if (eth->isOpened()) devSenderState = "Opened"; - else devSenderState = "Not opened"; - } - else devSenderState = "Not exists"; - } -} - - -void PIProtocol::send(const void * data, int size, bool direct) { - if (!direct) { - if (data == 0 || size == 0) return; - if (!aboutSend()) return; - } - if (type_send == PIProtocol::Serial) - if (ser->send(data, size)) { - send_count++; - packets_out_sec++; - bytes_out_sec += size; - } - if (type_send == PIProtocol::Ethernet) - if (eth->send(data, size)) { - send_count++; - packets_out_sec++; - bytes_out_sec += size; - } -} - - -void PIProtocol::send() { - //lock(); - //memcpy(packet, sendDataPtr, sendDataSize); - //unlock(); - if (!aboutSend()) return; - if (sendDataPtr == 0 || sendDataSize == 0) return; - if (type_send == PIProtocol::Serial) - if (ser->send(sendDataPtr, sendDataSize)) { - send_count++; - packets_out_sec++; - bytes_out_sec += sendDataSize; - } - if (type_send == PIProtocol::Ethernet) - if (eth->send(sendDataPtr, sendDataSize)) { - send_count++; - packets_out_sec++; - bytes_out_sec += sendDataSize; - } -} diff --git a/kx_utils/piprotocol.h b/kx_utils/piprotocol.h deleted file mode 100644 index 496d786..0000000 --- a/kx_utils/piprotocol.h +++ /dev/null @@ -1,238 +0,0 @@ -/*! \file piprotocol.h - * \brief Highly configurable from file I/O channel -*/ -/* - PIP - Platform Independent Primitives - Protocol, input/output channel (COM, UDP) - Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef PIPROTOCOL_H -#define PIPROTOCOL_H - -#include "piserial.h" -#include "piethernet.h" -#include "pipacketextractor.h" -#include "pitimer.h" -#include "piconfig.h" -#include "pifile.h" - -class PIProtocol; /// DEPRECATED - -class PIP_EXPORT PIMultiProtocolBase: protected PIObject /// DEPRECATED -{ - PIOBJECT_SUBCLASS(PIMultiProtocolBase, PIObject) - friend class PIProtocol; -public: - PIMultiProtocolBase() {;} /// DEPRECATED - virtual ~PIMultiProtocolBase() {;} - -protected: - virtual void received(PIProtocol * prot, bool corrected, uchar * data, int size) {;} - -private: - static void receiveEvent(PIMultiProtocolBase * p, PIProtocol * prot, bool corrected, uchar * data, int size) {p->mutex_receive.lock(); p->received(prot, corrected, data, size); p->mutex_receive.unlock();} - - PIMutex mutex_receive; - -}; - -typedef void (*ReceiveFunc)(void * ); - -/// events: -/// void receiverStarted() -/// void receiverStopped() -/// void senderStarted() -/// void senderStopped() -/// void received(bool validate_is_ok) -/// void qualityChanged(PIProtocol::Quality old_quality, PIProtocol::Quality new_quality) -/// -/// handlers: -/// void startReceive(float exp_frequency = -1.f) -/// void stopReceive() -/// void startSend(float frequency = -1.f) -/// void stopSend() -/// void start() -/// void stop() -/// void send() -/// void send(const void * data, int size, bool direct = false) -class PIP_EXPORT PIProtocol: public PIObject /// DEPRECATED -{ - PIOBJECT_SUBCLASS(PIProtocol, PIObject) - friend class PIMultiProtocolBase; - friend class PIMultiProtocol; - enum Type {None, Serial, Ethernet}; -public: - - //! Contructs an empty unconfigured protocol - PIProtocol(): PIObject() {init();} /// DEPRECATED - - //! Contructs protocol configured from file "config", config file section "name" - PIProtocol(const PIString & config, const PIString & name, void * recHeaderPtr = 0, int recHeaderSize = 0, - void * recDataPtr = 0, int recDataSize = 0, void * sendDataPtr = 0, int sendDataSize = 0); // from config - - virtual ~PIProtocol(); - - //! Connection quality - enum Quality { - Unknown /** Unknown, no one packet received yet */ = 1, - Failure /** No connection, no one correct packet received for last period */ = 2, - Bad /** Bad connection, correct packets received <= 20% */ = 3, - Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, - Good /** Good connection, correct packets received > 80% */ = 5 - }; - - EVENT_HANDLER0(void, startReceive) {startReceive(-1.f);} - EVENT_HANDLER1(void, startReceive, float, exp_frequency); // if "frequency = -1" used last passed value - EVENT_HANDLER0(void, stopReceive); - void setExpectedFrequency(float frequency); // for connection quality diagnostic - void setReceiverDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial - void setReceiverData(void * dataPtr, int dataSize) {this->dataPtr = (uchar * )dataPtr; this->dataSize = dataSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);} - void setReceiverDataHeader(void * headerPtr, int headerSize) {this->headerPtr = (uchar * )headerPtr; this->headerSize = headerSize; packet_ext->setHeader(PIByteArray(headerPtr, headerSize)); packet_ext->setPayloadSize(dataSize); packet_ext->setPacketSize(dataSize);} - void setReceiverAddress(const PIString & ip, int port, bool force = false); // for Ethernet - void setReceiverParameters(PIFlags parameters) {if (type_rec == PIProtocol::Serial || type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial - void setReceiveSlot(ReceiveFunc slot) {ret_func = slot;} - float expectedFrequency() const {return exp_freq;} - - EVENT_HANDLER0(void, startSend) {startSend(-1.f);} // if "frequency = -1" used last passed value - EVENT_HANDLER1(void, startSend, float, frequency); // if "frequency = -1" used last passed value - EVENT_HANDLER0(void, stopSend) {sendTimer->stop(); senderStopped();} - void setSenderFrequency(float frequency) {send_freq = frequency;} - void setSenderDevice(const PIString & device, PISerial::Speed speed, bool force = false); // for Serial - void setSenderData(void * dataPtr, int dataSize) {sendDataPtr = (uchar * )dataPtr; sendDataSize = dataSize;} - void setSenderAddress(const PIString & ip, int port, bool force = false); // for Ethernet - void setSenderIP(const PIString & ip, bool force = false); // for Ethernet - void setSenderPort(int port, bool force = false); // for Ethernet - void setSenderParameters(PIFlags parameters) {if (type_send == PIProtocol::Serial) ser->setParameters(parameters);} // for Serial - float senderFrequency() const {return send_freq;} - - EVENT_HANDLER0(void, start) {startReceive(); startSend();} - EVENT_HANDLER0(void, stop) {stopReceive(); stopSend();} - EVENT_HANDLER0(void, send); - EVENT_HANDLER2(void, send, const void *, data, int, size) {send(data, size, false);} - EVENT_HANDLER3(void, send, const void *, data, int, size, bool, direct); - - void setName(const PIString & name) {protName = name; PIObject::setName(name);} - PIString name() const {return protName;} - void setDisconnectTimeout(float timeout) {timeout_ = timeout; changeDisconnectTimeout();} - float disconnectTimeout() const {return timeout_;} - const float * disconnectTimeout_ptr() const {return &timeout_;} - float immediateFrequency() const {return immediate_freq;} - float integralFrequency() const {return integral_freq;} - const float * immediateFrequency_ptr() const {return &immediate_freq;} - const float * integralFrequency_ptr() const {return &integral_freq;} - ullong receiveCountPerSec() const {return packets_in_sec;} - const ullong * receiveCountPerSec_ptr() const {return &packets_in_sec;} - ullong sendCountPerSec() const {return packets_out_sec;} - const ullong * sendCountPerSec_ptr() const {return &packets_out_sec;} - ullong receiveBytesPerSec() const {return bytes_in_sec;} - const ullong * receiveBytesPerSec_ptr() const {return &bytes_in_sec;} - ullong sendBytesPerSec() const {return bytes_out_sec;} - const ullong * sendBytesPerSec_ptr() const {return &bytes_out_sec;} - ullong receiveCount() const {return receive_count;} - const ullong * receiveCount_ptr() const {return &receive_count;} - ullong wrongCount() const {return wrong_count;} - const ullong * wrongCount_ptr() const {return &wrong_count;} - ullong sendCount() const {return send_count;} - const ullong * sendCount_ptr() const {return &send_count;} - ullong missedCount() const {return missed_count;} - const ullong * missedCount_ptr() const {return &missed_count;} - PIProtocol::Quality quality() const {return net_diag;} // receive quality - const int * quality_ptr() const {return (int * )&net_diag;} // receive quality pointer - PIString receiverDeviceName() const {return devReceiverName;} - PIString senderDeviceName() const {return devSenderName;} - PIString receiverDeviceState() const {return devReceiverState;} - const PIString * receiverDeviceState_ptr() const {return &devReceiverState;} - PIString senderDeviceState() const {return devSenderState;} - const PIString * senderDeviceState_ptr() const {return &devSenderState;} - PIString receiveSpeed() const {return speedIn;} - const PIString * receiveSpeed_ptr() const {return &speedIn;} - PIString sendSpeed() const {return speedOut;} - const PIString * sendSpeed_ptr() const {return &speedOut;} - - void * receiveData() {return dataPtr;} - void * sendData() {return sendDataPtr;} - - PIPacketExtractor * packetExtractor() {return packet_ext;} -// PIByteArray lastHeader() {return packet_ext->lastHeader();} - - EVENT0(receiverStarted) - EVENT0(receiverStopped) - EVENT0(senderStarted) - EVENT0(senderStopped) - EVENT1(received, bool, validate_is_ok) - EVENT2(qualityChanged, PIProtocol::Quality, new_quality, PIProtocol::Quality, old_quality) - -protected: - virtual bool receive(uchar * data, int size) {if (dataPtr != 0) memcpy(dataPtr, data, size); return true;} // executed when raw data received, break if 'false' return - virtual bool validate() {return true;} // function for validate algorithm and save data from dataPtr to external struct - virtual bool headerValidate(uchar * src, uchar * rec, int size) {for (int i = 0; i < size; ++i) if (src[i] != rec[i]) return false; return true;} // function for validate header (COM-port and headerSize > 0) - virtual uint checksum_i(void * data, int size) { // function for checksum (uint) - uint c = 0; - for (int i = 0; i < size; ++i) - c += ((uchar*)data)[i]; - return ~(c + 1); - } - virtual uchar checksum_c(void * data, int size) { // function for checksum (uchar) - uchar c = 0; - for (int i = 0; i < size; ++i) - c += ((uchar*)data)[i]; - return ~(c + 1); - } - virtual bool aboutSend() {return true;} // executed before send data, if return 'false' then data is not sending - - void init(); - void init_sender(PIConfig::Entry & b, PIConfig::Entry & sb, const PIString & config); - void init_receiver(PIConfig::Entry & b, PIConfig::Entry & rb, const PIString & config); - void check_state(); - void calc_freq(); - void calc_diag(); - - PISerial * ser; - PIEthernet * eth; - uint dataSize, headerSize, sendDataSize; - uchar * dataPtr, * headerPtr, * sendDataPtr; - -private: - static void sendEvent(void * e, int) {((PIProtocol * )e)->send();} - static bool receiveEvent(void * t, uchar * data, int size); - static bool headerValidateEvent(void * t, uchar * src, uchar * rec, int size) {return ((PIProtocol * )t)->headerValidate(src, rec, size);} - static void diagEvent(void * t, int); - static void secEvent(void * t, int); - - void setMultiProtocolOwner(PIMultiProtocolBase * mp) {mp_owner = mp;} - PIMultiProtocolBase * multiProtocolOwner() const {return mp_owner;} - void changeDisconnectTimeout(); - - ReceiveFunc ret_func; - PIPacketExtractor * packet_ext; - PITimer * diagTimer, * sendTimer, * secTimer; - PITimeMeasurer diag_tm; - PIMultiProtocolBase * mp_owner; - PIProtocol::Type type_send, type_rec; - PIProtocol::Quality net_diag; - PIDeque last_freq; - PIDeque last_packets; - PIString protName, devReceiverName, devReceiverState, devSenderName, devSenderState, speedIn, speedOut; - bool work, new_mp_prot; - float exp_freq, send_freq, ifreq, immediate_freq, integral_freq, timeout_; - int packets[2], pckt_cnt, pckt_cnt_max; - char cur_pckt; - ullong wrong_count, receive_count, send_count, missed_count, packets_in_sec, packets_out_sec, bytes_in_sec, bytes_out_sec; - -}; - -#endif // PIPROTOCOL_H diff --git a/qad/libs/CMakeLists.txt b/libs/CMakeLists.txt similarity index 100% rename from qad/libs/CMakeLists.txt rename to libs/CMakeLists.txt diff --git a/qad/libs/application/CMakeLists.txt b/libs/application/CMakeLists.txt similarity index 100% rename from qad/libs/application/CMakeLists.txt rename to libs/application/CMakeLists.txt diff --git a/qad/libs/application/aboutwindow.cpp b/libs/application/aboutwindow.cpp similarity index 100% rename from qad/libs/application/aboutwindow.cpp rename to libs/application/aboutwindow.cpp diff --git a/qad/libs/application/aboutwindow.h b/libs/application/aboutwindow.h similarity index 100% rename from qad/libs/application/aboutwindow.h rename to libs/application/aboutwindow.h diff --git a/qad/libs/application/aboutwindow.ui b/libs/application/aboutwindow.ui similarity index 100% rename from qad/libs/application/aboutwindow.ui rename to libs/application/aboutwindow.ui diff --git a/qad/libs/application/edockwidget.cpp b/libs/application/edockwidget.cpp similarity index 100% rename from qad/libs/application/edockwidget.cpp rename to libs/application/edockwidget.cpp diff --git a/qad/libs/application/edockwidget.h b/libs/application/edockwidget.h similarity index 100% rename from qad/libs/application/edockwidget.h rename to libs/application/edockwidget.h diff --git a/qad/libs/application/emainwindow.cpp b/libs/application/emainwindow.cpp similarity index 100% rename from qad/libs/application/emainwindow.cpp rename to libs/application/emainwindow.cpp diff --git a/qad/libs/application/emainwindow.h b/libs/application/emainwindow.h similarity index 100% rename from qad/libs/application/emainwindow.h rename to libs/application/emainwindow.h diff --git a/qad/libs/application/etabwidget.cpp b/libs/application/etabwidget.cpp similarity index 100% rename from qad/libs/application/etabwidget.cpp rename to libs/application/etabwidget.cpp diff --git a/qad/libs/application/etabwidget.h b/libs/application/etabwidget.h similarity index 100% rename from qad/libs/application/etabwidget.h rename to libs/application/etabwidget.h diff --git a/qad/libs/application/historyview.cpp b/libs/application/historyview.cpp similarity index 100% rename from qad/libs/application/historyview.cpp rename to libs/application/historyview.cpp diff --git a/qad/libs/application/historyview.h b/libs/application/historyview.h similarity index 100% rename from qad/libs/application/historyview.h rename to libs/application/historyview.h diff --git a/qad/libs/application/lang/qad_application_en.ts b/libs/application/lang/qad_application_en.ts similarity index 100% rename from qad/libs/application/lang/qad_application_en.ts rename to libs/application/lang/qad_application_en.ts diff --git a/qad/libs/application/lang/qad_application_ru.ts b/libs/application/lang/qad_application_ru.ts similarity index 100% rename from qad/libs/application/lang/qad_application_ru.ts rename to libs/application/lang/qad_application_ru.ts diff --git a/qad/libs/application/lang/update.bat b/libs/application/lang/update.bat similarity index 100% rename from qad/libs/application/lang/update.bat rename to libs/application/lang/update.bat diff --git a/qad/libs/application/logview.cpp b/libs/application/logview.cpp similarity index 100% rename from qad/libs/application/logview.cpp rename to libs/application/logview.cpp diff --git a/qad/libs/application/logview.h b/libs/application/logview.h similarity index 100% rename from qad/libs/application/logview.h rename to libs/application/logview.h diff --git a/qad/libs/application/logview.ui b/libs/application/logview.ui similarity index 100% rename from qad/libs/application/logview.ui rename to libs/application/logview.ui diff --git a/qad/libs/application/plugin/CMakeLists.txt b/libs/application/plugin/CMakeLists.txt similarity index 100% rename from qad/libs/application/plugin/CMakeLists.txt rename to libs/application/plugin/CMakeLists.txt diff --git a/qad/libs/application/plugin/edockwidgetplugin.cpp b/libs/application/plugin/edockwidgetplugin.cpp similarity index 100% rename from qad/libs/application/plugin/edockwidgetplugin.cpp rename to libs/application/plugin/edockwidgetplugin.cpp diff --git a/qad/libs/application/plugin/edockwidgetplugin.h b/libs/application/plugin/edockwidgetplugin.h similarity index 100% rename from qad/libs/application/plugin/edockwidgetplugin.h rename to libs/application/plugin/edockwidgetplugin.h diff --git a/qad/libs/application/plugin/emainwindowplugin.cpp b/libs/application/plugin/emainwindowplugin.cpp similarity index 100% rename from qad/libs/application/plugin/emainwindowplugin.cpp rename to libs/application/plugin/emainwindowplugin.cpp diff --git a/qad/libs/application/plugin/emainwindowplugin.h b/libs/application/plugin/emainwindowplugin.h similarity index 100% rename from qad/libs/application/plugin/emainwindowplugin.h rename to libs/application/plugin/emainwindowplugin.h diff --git a/qad/libs/application/plugin/historyviewplugin.cpp b/libs/application/plugin/historyviewplugin.cpp similarity index 100% rename from qad/libs/application/plugin/historyviewplugin.cpp rename to libs/application/plugin/historyviewplugin.cpp diff --git a/qad/libs/application/plugin/historyviewplugin.h b/libs/application/plugin/historyviewplugin.h similarity index 100% rename from qad/libs/application/plugin/historyviewplugin.h rename to libs/application/plugin/historyviewplugin.h diff --git a/qad/libs/application/plugin/logviewplugin.cpp b/libs/application/plugin/logviewplugin.cpp similarity index 100% rename from qad/libs/application/plugin/logviewplugin.cpp rename to libs/application/plugin/logviewplugin.cpp diff --git a/qad/libs/application/plugin/logviewplugin.h b/libs/application/plugin/logviewplugin.h similarity index 100% rename from qad/libs/application/plugin/logviewplugin.h rename to libs/application/plugin/logviewplugin.h diff --git a/qad/libs/application/plugin/qad_application.cpp b/libs/application/plugin/qad_application.cpp similarity index 100% rename from qad/libs/application/plugin/qad_application.cpp rename to libs/application/plugin/qad_application.cpp diff --git a/qad/libs/application/plugin/qad_application.h b/libs/application/plugin/qad_application.h similarity index 100% rename from qad/libs/application/plugin/qad_application.h rename to libs/application/plugin/qad_application.h diff --git a/qad/libs/application/qad_application.qrc b/libs/application/qad_application.qrc similarity index 100% rename from qad/libs/application/qad_application.qrc rename to libs/application/qad_application.qrc diff --git a/qad/libs/application/qsingleapplication.cpp b/libs/application/qsingleapplication.cpp similarity index 100% rename from qad/libs/application/qsingleapplication.cpp rename to libs/application/qsingleapplication.cpp diff --git a/qad/libs/application/qsingleapplication.h b/libs/application/qsingleapplication.h similarity index 100% rename from qad/libs/application/qsingleapplication.h rename to libs/application/qsingleapplication.h diff --git a/qad/libs/application/ribbon.cpp b/libs/application/ribbon.cpp similarity index 100% rename from qad/libs/application/ribbon.cpp rename to libs/application/ribbon.cpp diff --git a/qad/libs/application/ribbon.h b/libs/application/ribbon.h similarity index 100% rename from qad/libs/application/ribbon.h rename to libs/application/ribbon.h diff --git a/qad/libs/blockview/CMakeLists.txt b/libs/blockview/CMakeLists.txt similarity index 100% rename from qad/libs/blockview/CMakeLists.txt rename to libs/blockview/CMakeLists.txt diff --git a/qad/libs/blockview/alignedtextitem.cpp b/libs/blockview/alignedtextitem.cpp similarity index 100% rename from qad/libs/blockview/alignedtextitem.cpp rename to libs/blockview/alignedtextitem.cpp diff --git a/qad/libs/blockview/alignedtextitem.h b/libs/blockview/alignedtextitem.h similarity index 100% rename from qad/libs/blockview/alignedtextitem.h rename to libs/blockview/alignedtextitem.h diff --git a/qad/libs/blockview/blockbase.cpp b/libs/blockview/blockbase.cpp similarity index 100% rename from qad/libs/blockview/blockbase.cpp rename to libs/blockview/blockbase.cpp diff --git a/qad/libs/blockview/blockbase.h b/libs/blockview/blockbase.h similarity index 100% rename from qad/libs/blockview/blockbase.h rename to libs/blockview/blockbase.h diff --git a/qad/libs/blockview/blockbusitem.cpp b/libs/blockview/blockbusitem.cpp similarity index 100% rename from qad/libs/blockview/blockbusitem.cpp rename to libs/blockview/blockbusitem.cpp diff --git a/qad/libs/blockview/blockbusitem.h b/libs/blockview/blockbusitem.h similarity index 100% rename from qad/libs/blockview/blockbusitem.h rename to libs/blockview/blockbusitem.h diff --git a/qad/libs/blockview/blockeditor.cpp b/libs/blockview/blockeditor.cpp similarity index 100% rename from qad/libs/blockview/blockeditor.cpp rename to libs/blockview/blockeditor.cpp diff --git a/qad/libs/blockview/blockeditor.h b/libs/blockview/blockeditor.h similarity index 100% rename from qad/libs/blockview/blockeditor.h rename to libs/blockview/blockeditor.h diff --git a/qad/libs/blockview/blockeditor.ui b/libs/blockview/blockeditor.ui similarity index 100% rename from qad/libs/blockview/blockeditor.ui rename to libs/blockview/blockeditor.ui diff --git a/qad/libs/blockview/blockitem.cpp b/libs/blockview/blockitem.cpp similarity index 100% rename from qad/libs/blockview/blockitem.cpp rename to libs/blockview/blockitem.cpp diff --git a/qad/libs/blockview/blockitem.h b/libs/blockview/blockitem.h similarity index 100% rename from qad/libs/blockview/blockitem.h rename to libs/blockview/blockitem.h diff --git a/qad/libs/blockview/blockitempin.cpp b/libs/blockview/blockitempin.cpp similarity index 100% rename from qad/libs/blockview/blockitempin.cpp rename to libs/blockview/blockitempin.cpp diff --git a/qad/libs/blockview/blockitempin.h b/libs/blockview/blockitempin.h similarity index 100% rename from qad/libs/blockview/blockitempin.h rename to libs/blockview/blockitempin.h diff --git a/qad/libs/blockview/blockview.cpp b/libs/blockview/blockview.cpp similarity index 100% rename from qad/libs/blockview/blockview.cpp rename to libs/blockview/blockview.cpp diff --git a/qad/libs/blockview/blockview.h b/libs/blockview/blockview.h similarity index 100% rename from qad/libs/blockview/blockview.h rename to libs/blockview/blockview.h diff --git a/qad/libs/blockview/blockviewwavetrace.cpp b/libs/blockview/blockviewwavetrace.cpp similarity index 100% rename from qad/libs/blockview/blockviewwavetrace.cpp rename to libs/blockview/blockviewwavetrace.cpp diff --git a/qad/libs/blockview/blockviewwavetrace.h b/libs/blockview/blockviewwavetrace.h similarity index 100% rename from qad/libs/blockview/blockviewwavetrace.h rename to libs/blockview/blockviewwavetrace.h diff --git a/qad/libs/blockview/drawtools.cpp b/libs/blockview/drawtools.cpp similarity index 100% rename from qad/libs/blockview/drawtools.cpp rename to libs/blockview/drawtools.cpp diff --git a/qad/libs/blockview/drawtools.h b/libs/blockview/drawtools.h similarity index 100% rename from qad/libs/blockview/drawtools.h rename to libs/blockview/drawtools.h diff --git a/qad/libs/blockview/drawtools.ui b/libs/blockview/drawtools.ui similarity index 100% rename from qad/libs/blockview/drawtools.ui rename to libs/blockview/drawtools.ui diff --git a/qad/libs/blockview/lang/qad_blockview_en.ts b/libs/blockview/lang/qad_blockview_en.ts similarity index 100% rename from qad/libs/blockview/lang/qad_blockview_en.ts rename to libs/blockview/lang/qad_blockview_en.ts diff --git a/qad/libs/blockview/lang/qad_blockview_ru.ts b/libs/blockview/lang/qad_blockview_ru.ts similarity index 100% rename from qad/libs/blockview/lang/qad_blockview_ru.ts rename to libs/blockview/lang/qad_blockview_ru.ts diff --git a/qad/libs/blockview/lang/update.bat b/libs/blockview/lang/update.bat similarity index 100% rename from qad/libs/blockview/lang/update.bat rename to libs/blockview/lang/update.bat diff --git a/qad/libs/blockview/plugin/CMakeLists.txt b/libs/blockview/plugin/CMakeLists.txt similarity index 100% rename from qad/libs/blockview/plugin/CMakeLists.txt rename to libs/blockview/plugin/CMakeLists.txt diff --git a/qad/libs/blockview/plugin/blockviewplugin.cpp b/libs/blockview/plugin/blockviewplugin.cpp similarity index 100% rename from qad/libs/blockview/plugin/blockviewplugin.cpp rename to libs/blockview/plugin/blockviewplugin.cpp diff --git a/qad/libs/blockview/plugin/blockviewplugin.h b/libs/blockview/plugin/blockviewplugin.h similarity index 100% rename from qad/libs/blockview/plugin/blockviewplugin.h rename to libs/blockview/plugin/blockviewplugin.h diff --git a/qad/libs/blockview/plugin/qad_blockview.cpp b/libs/blockview/plugin/qad_blockview.cpp similarity index 100% rename from qad/libs/blockview/plugin/qad_blockview.cpp rename to libs/blockview/plugin/qad_blockview.cpp diff --git a/qad/libs/blockview/plugin/qad_blockview.h b/libs/blockview/plugin/qad_blockview.h similarity index 100% rename from qad/libs/blockview/plugin/qad_blockview.h rename to libs/blockview/plugin/qad_blockview.h diff --git a/qad/libs/blockview/qad_blockview.qrc b/libs/blockview/qad_blockview.qrc similarity index 100% rename from qad/libs/blockview/qad_blockview.qrc rename to libs/blockview/qad_blockview.qrc diff --git a/qad/libs/doc/CMakeLists.txt b/libs/doc/CMakeLists.txt similarity index 100% rename from qad/libs/doc/CMakeLists.txt rename to libs/doc/CMakeLists.txt diff --git a/qad/libs/doc/markdown.cpp b/libs/doc/markdown.cpp similarity index 100% rename from qad/libs/doc/markdown.cpp rename to libs/doc/markdown.cpp diff --git a/qad/libs/doc/markdown.h b/libs/doc/markdown.h similarity index 100% rename from qad/libs/doc/markdown.h rename to libs/doc/markdown.h diff --git a/qad/libs/graphic/CMakeLists.txt b/libs/graphic/CMakeLists.txt similarity index 100% rename from qad/libs/graphic/CMakeLists.txt rename to libs/graphic/CMakeLists.txt diff --git a/qad/libs/graphic/graphic.cpp b/libs/graphic/graphic.cpp similarity index 100% rename from qad/libs/graphic/graphic.cpp rename to libs/graphic/graphic.cpp diff --git a/qad/libs/graphic/graphic.h b/libs/graphic/graphic.h similarity index 100% rename from qad/libs/graphic/graphic.h rename to libs/graphic/graphic.h diff --git a/qad/libs/graphic/graphic.ui b/libs/graphic/graphic.ui similarity index 100% rename from qad/libs/graphic/graphic.ui rename to libs/graphic/graphic.ui diff --git a/qad/libs/graphic/graphic_conf.cpp b/libs/graphic/graphic_conf.cpp similarity index 100% rename from qad/libs/graphic/graphic_conf.cpp rename to libs/graphic/graphic_conf.cpp diff --git a/qad/libs/graphic/graphic_conf.h b/libs/graphic/graphic_conf.h similarity index 100% rename from qad/libs/graphic/graphic_conf.h rename to libs/graphic/graphic_conf.h diff --git a/qad/libs/graphic/graphic_conf.ui b/libs/graphic/graphic_conf.ui similarity index 100% rename from qad/libs/graphic/graphic_conf.ui rename to libs/graphic/graphic_conf.ui diff --git a/qad/libs/graphic/lang/qad_graphic_en.ts b/libs/graphic/lang/qad_graphic_en.ts similarity index 100% rename from qad/libs/graphic/lang/qad_graphic_en.ts rename to libs/graphic/lang/qad_graphic_en.ts diff --git a/qad/libs/graphic/lang/qad_graphic_ru.ts b/libs/graphic/lang/qad_graphic_ru.ts similarity index 100% rename from qad/libs/graphic/lang/qad_graphic_ru.ts rename to libs/graphic/lang/qad_graphic_ru.ts diff --git a/qad/libs/graphic/lang/update.bat b/libs/graphic/lang/update.bat similarity index 100% rename from qad/libs/graphic/lang/update.bat rename to libs/graphic/lang/update.bat diff --git a/qad/libs/graphic/plugin/CMakeLists.txt b/libs/graphic/plugin/CMakeLists.txt similarity index 100% rename from qad/libs/graphic/plugin/CMakeLists.txt rename to libs/graphic/plugin/CMakeLists.txt diff --git a/qad/libs/graphic/plugin/graphicplugin.cpp b/libs/graphic/plugin/graphicplugin.cpp similarity index 100% rename from qad/libs/graphic/plugin/graphicplugin.cpp rename to libs/graphic/plugin/graphicplugin.cpp diff --git a/qad/libs/graphic/plugin/graphicplugin.h b/libs/graphic/plugin/graphicplugin.h similarity index 100% rename from qad/libs/graphic/plugin/graphicplugin.h rename to libs/graphic/plugin/graphicplugin.h diff --git a/qad/libs/graphic/plugin/qad_graphic.cpp b/libs/graphic/plugin/qad_graphic.cpp similarity index 100% rename from qad/libs/graphic/plugin/qad_graphic.cpp rename to libs/graphic/plugin/qad_graphic.cpp diff --git a/qad/libs/graphic/plugin/qad_graphic.h b/libs/graphic/plugin/qad_graphic.h similarity index 100% rename from qad/libs/graphic/plugin/qad_graphic.h rename to libs/graphic/plugin/qad_graphic.h diff --git a/qad/libs/graphic/qad_graphic.qrc b/libs/graphic/qad_graphic.qrc similarity index 100% rename from qad/libs/graphic/qad_graphic.qrc rename to libs/graphic/qad_graphic.qrc diff --git a/qad/libs/graphic/uglwidget.h b/libs/graphic/uglwidget.h similarity index 100% rename from qad/libs/graphic/uglwidget.h rename to libs/graphic/uglwidget.h diff --git a/qad/libs/graphic/uwidget.h b/libs/graphic/uwidget.h similarity index 100% rename from qad/libs/graphic/uwidget.h rename to libs/graphic/uwidget.h diff --git a/piqt/libs/core/CMakeLists.txt b/libs/piqt/CMakeLists.txt similarity index 100% rename from piqt/libs/core/CMakeLists.txt rename to libs/piqt/CMakeLists.txt diff --git a/piqt/libs/core/piqt.cpp b/libs/piqt/piqt.cpp similarity index 100% rename from piqt/libs/core/piqt.cpp rename to libs/piqt/piqt.cpp diff --git a/piqt/libs/core/piqt.h b/libs/piqt/piqt.h similarity index 100% rename from piqt/libs/core/piqt.h rename to libs/piqt/piqt.h diff --git a/piqt/libs/core/qpiconnection.cpp b/libs/piqt/qpiconnection.cpp similarity index 100% rename from piqt/libs/core/qpiconnection.cpp rename to libs/piqt/qpiconnection.cpp diff --git a/piqt/libs/core/qpiconnection.h b/libs/piqt/qpiconnection.h similarity index 100% rename from piqt/libs/core/qpiconnection.h rename to libs/piqt/qpiconnection.h diff --git a/piqt/libs/widgets/CMakeLists.txt b/libs/piqt_widgets/CMakeLists.txt similarity index 100% rename from piqt/libs/widgets/CMakeLists.txt rename to libs/piqt_widgets/CMakeLists.txt diff --git a/piqt/libs/widgets/piqt_connection_edit.cpp b/libs/piqt_widgets/piqt_connection_edit.cpp similarity index 100% rename from piqt/libs/widgets/piqt_connection_edit.cpp rename to libs/piqt_widgets/piqt_connection_edit.cpp diff --git a/piqt/libs/widgets/piqt_connection_edit.h b/libs/piqt_widgets/piqt_connection_edit.h similarity index 100% rename from piqt/libs/widgets/piqt_connection_edit.h rename to libs/piqt_widgets/piqt_connection_edit.h diff --git a/piqt/libs/widgets/piqt_connection_edit.ui b/libs/piqt_widgets/piqt_connection_edit.ui similarity index 100% rename from piqt/libs/widgets/piqt_connection_edit.ui rename to libs/piqt_widgets/piqt_connection_edit.ui diff --git a/piqt/libs/widgets/piqt_connection_view.cpp b/libs/piqt_widgets/piqt_connection_view.cpp similarity index 100% rename from piqt/libs/widgets/piqt_connection_view.cpp rename to libs/piqt_widgets/piqt_connection_view.cpp diff --git a/piqt/libs/widgets/piqt_connection_view.h b/libs/piqt_widgets/piqt_connection_view.h similarity index 100% rename from piqt/libs/widgets/piqt_connection_view.h rename to libs/piqt_widgets/piqt_connection_view.h diff --git a/piqt/libs/widgets/piqt_highlighter.cpp b/libs/piqt_widgets/piqt_highlighter.cpp similarity index 100% rename from piqt/libs/widgets/piqt_highlighter.cpp rename to libs/piqt_widgets/piqt_highlighter.cpp diff --git a/piqt/libs/widgets/piqt_highlighter.h b/libs/piqt_widgets/piqt_highlighter.h similarity index 100% rename from piqt/libs/widgets/piqt_highlighter.h rename to libs/piqt_widgets/piqt_highlighter.h diff --git a/piqt/libs/widgets/piqt_iodevice_edit.cpp b/libs/piqt_widgets/piqt_iodevice_edit.cpp similarity index 100% rename from piqt/libs/widgets/piqt_iodevice_edit.cpp rename to libs/piqt_widgets/piqt_iodevice_edit.cpp diff --git a/piqt/libs/widgets/piqt_iodevice_edit.h b/libs/piqt_widgets/piqt_iodevice_edit.h similarity index 100% rename from piqt/libs/widgets/piqt_iodevice_edit.h rename to libs/piqt_widgets/piqt_iodevice_edit.h diff --git a/piqt/libs/widgets/piqt_iodevice_edit_dialog.cpp b/libs/piqt_widgets/piqt_iodevice_edit_dialog.cpp similarity index 100% rename from piqt/libs/widgets/piqt_iodevice_edit_dialog.cpp rename to libs/piqt_widgets/piqt_iodevice_edit_dialog.cpp diff --git a/piqt/libs/widgets/piqt_iodevice_edit_dialog.h b/libs/piqt_widgets/piqt_iodevice_edit_dialog.h similarity index 100% rename from piqt/libs/widgets/piqt_iodevice_edit_dialog.h rename to libs/piqt_widgets/piqt_iodevice_edit_dialog.h diff --git a/piqt/libs/widgets/piqt_iodevice_edit_dialog.ui b/libs/piqt_widgets/piqt_iodevice_edit_dialog.ui similarity index 100% rename from piqt/libs/widgets/piqt_iodevice_edit_dialog.ui rename to libs/piqt_widgets/piqt_iodevice_edit_dialog.ui diff --git a/piqt/libs/qcd/CMakeLists.txt b/libs/qcd/CMakeLists.txt similarity index 100% rename from piqt/libs/qcd/CMakeLists.txt rename to libs/qcd/CMakeLists.txt diff --git a/piqt/libs/qcd/qcd_core.cpp b/libs/qcd/qcd_core.cpp similarity index 100% rename from piqt/libs/qcd/qcd_core.cpp rename to libs/qcd/qcd_core.cpp diff --git a/piqt/libs/qcd/qcd_core.h b/libs/qcd/qcd_core.h similarity index 100% rename from piqt/libs/qcd/qcd_core.h rename to libs/qcd/qcd_core.h diff --git a/piqt/libs/qcd/qcd_graphic.cpp b/libs/qcd/qcd_graphic.cpp similarity index 100% rename from piqt/libs/qcd/qcd_graphic.cpp rename to libs/qcd/qcd_graphic.cpp diff --git a/piqt/libs/qcd/qcd_graphic.h b/libs/qcd/qcd_graphic.h similarity index 100% rename from piqt/libs/qcd/qcd_graphic.h rename to libs/qcd/qcd_graphic.h diff --git a/piqt/libs/qcd/qcd_graphic.ui b/libs/qcd/qcd_graphic.ui similarity index 100% rename from piqt/libs/qcd/qcd_graphic.ui rename to libs/qcd/qcd_graphic.ui diff --git a/piqt/libs/qcd/qcd_modedialog.cpp b/libs/qcd/qcd_modedialog.cpp similarity index 100% rename from piqt/libs/qcd/qcd_modedialog.cpp rename to libs/qcd/qcd_modedialog.cpp diff --git a/piqt/libs/qcd/qcd_modedialog.h b/libs/qcd/qcd_modedialog.h similarity index 100% rename from piqt/libs/qcd/qcd_modedialog.h rename to libs/qcd/qcd_modedialog.h diff --git a/piqt/libs/qcd/qcd_modedialog.ui b/libs/qcd/qcd_modedialog.ui similarity index 100% rename from piqt/libs/qcd/qcd_modedialog.ui rename to libs/qcd/qcd_modedialog.ui diff --git a/piqt/libs/qcd/qcd_model.cpp b/libs/qcd/qcd_model.cpp similarity index 100% rename from piqt/libs/qcd/qcd_model.cpp rename to libs/qcd/qcd_model.cpp diff --git a/piqt/libs/qcd/qcd_model.h b/libs/qcd/qcd_model.h similarity index 100% rename from piqt/libs/qcd/qcd_model.h rename to libs/qcd/qcd_model.h diff --git a/piqt/libs/qcd/qcd_view.cpp b/libs/qcd/qcd_view.cpp similarity index 100% rename from piqt/libs/qcd/qcd_view.cpp rename to libs/qcd/qcd_view.cpp diff --git a/piqt/libs/qcd/qcd_view.h b/libs/qcd/qcd_view.h similarity index 100% rename from piqt/libs/qcd/qcd_view.h rename to libs/qcd/qcd_view.h diff --git a/qglview/CMakeLists.txt b/libs/qglview/CMakeLists.txt similarity index 97% rename from qglview/CMakeLists.txt rename to libs/qglview/CMakeLists.txt index 018fbe7..b6fcdf8 100644 --- a/qglview/CMakeLists.txt +++ b/libs/qglview/CMakeLists.txt @@ -1,8 +1,8 @@ -find_package(OpenGL REQUIRED) -_qt_project(qglview FALSE "QAD" "Gui;OpenGL;Xml" "qad_widgets;qad_utils;${OPENGL_LIBRARIES}") -_qt_install(qglview FALSE "qad" "out_HDR" "out_QM") - -qt_sources(test_SRC DIR "qglview_test") -qt_wrap(${test_SRC} CPPS test_CPP) -qt_add_executable(qglview_test test_CPP) -qt_target_link_libraries(qglview_test qglview) +find_package(OpenGL REQUIRED) +_qt_project(qglview FALSE "QAD" "Gui;OpenGL;Xml" "qad_widgets;qad_utils;${OPENGL_LIBRARIES}") +_qt_install(qglview FALSE "qad" "out_HDR" "out_QM") + +qt_sources(test_SRC DIR "qglview_test") +qt_wrap(${test_SRC} CPPS test_CPP) +qt_add_executable(qglview_test test_CPP) +qt_target_link_libraries(qglview_test qglview) diff --git a/cd_utils/LICENSE.txt b/libs/qglview/LICENSE.txt similarity index 100% rename from cd_utils/LICENSE.txt rename to libs/qglview/LICENSE.txt diff --git a/qglview/glcamera.cpp b/libs/qglview/glcamera.cpp similarity index 100% rename from qglview/glcamera.cpp rename to libs/qglview/glcamera.cpp diff --git a/qglview/glcamera.h b/libs/qglview/glcamera.h similarity index 100% rename from qglview/glcamera.h rename to libs/qglview/glcamera.h diff --git a/qglview/glframebuffer.cpp b/libs/qglview/glframebuffer.cpp similarity index 100% rename from qglview/glframebuffer.cpp rename to libs/qglview/glframebuffer.cpp diff --git a/qglview/glframebuffer.h b/libs/qglview/glframebuffer.h similarity index 100% rename from qglview/glframebuffer.h rename to libs/qglview/glframebuffer.h diff --git a/qglview/glmaterial.cpp b/libs/qglview/glmaterial.cpp similarity index 100% rename from qglview/glmaterial.cpp rename to libs/qglview/glmaterial.cpp diff --git a/qglview/glmaterial.h b/libs/qglview/glmaterial.h similarity index 100% rename from qglview/glmaterial.h rename to libs/qglview/glmaterial.h diff --git a/qglview/globject.cpp b/libs/qglview/globject.cpp similarity index 100% rename from qglview/globject.cpp rename to libs/qglview/globject.cpp diff --git a/qglview/globject.h b/libs/qglview/globject.h similarity index 100% rename from qglview/globject.h rename to libs/qglview/globject.h diff --git a/qglview/globject_editor.cpp b/libs/qglview/globject_editor.cpp similarity index 100% rename from qglview/globject_editor.cpp rename to libs/qglview/globject_editor.cpp diff --git a/qglview/globject_editor.h b/libs/qglview/globject_editor.h similarity index 100% rename from qglview/globject_editor.h rename to libs/qglview/globject_editor.h diff --git a/qglview/globject_editor.ui b/libs/qglview/globject_editor.ui similarity index 100% rename from qglview/globject_editor.ui rename to libs/qglview/globject_editor.ui diff --git a/qglview/glparticles_system.cpp b/libs/qglview/glparticles_system.cpp similarity index 100% rename from qglview/glparticles_system.cpp rename to libs/qglview/glparticles_system.cpp diff --git a/qglview/glparticles_system.h b/libs/qglview/glparticles_system.h similarity index 100% rename from qglview/glparticles_system.h rename to libs/qglview/glparticles_system.h diff --git a/qglview/glprimitives.cpp b/libs/qglview/glprimitives.cpp similarity index 100% rename from qglview/glprimitives.cpp rename to libs/qglview/glprimitives.cpp diff --git a/qglview/glprimitives.h b/libs/qglview/glprimitives.h similarity index 100% rename from qglview/glprimitives.h rename to libs/qglview/glprimitives.h diff --git a/qglview/glrendererbase.cpp b/libs/qglview/glrendererbase.cpp similarity index 100% rename from qglview/glrendererbase.cpp rename to libs/qglview/glrendererbase.cpp diff --git a/qglview/glrendererbase.h b/libs/qglview/glrendererbase.h similarity index 100% rename from qglview/glrendererbase.h rename to libs/qglview/glrendererbase.h diff --git a/qglview/glshaders.cpp b/libs/qglview/glshaders.cpp similarity index 100% rename from qglview/glshaders.cpp rename to libs/qglview/glshaders.cpp diff --git a/qglview/glshaders.h b/libs/qglview/glshaders.h similarity index 100% rename from qglview/glshaders.h rename to libs/qglview/glshaders.h diff --git a/qglview/gltexture_manager.cpp b/libs/qglview/gltexture_manager.cpp similarity index 100% rename from qglview/gltexture_manager.cpp rename to libs/qglview/gltexture_manager.cpp diff --git a/qglview/gltexture_manager.h b/libs/qglview/gltexture_manager.h similarity index 100% rename from qglview/gltexture_manager.h rename to libs/qglview/gltexture_manager.h diff --git a/qglview/gltypes.cpp b/libs/qglview/gltypes.cpp similarity index 100% rename from qglview/gltypes.cpp rename to libs/qglview/gltypes.cpp diff --git a/qglview/gltypes.h b/libs/qglview/gltypes.h similarity index 100% rename from qglview/gltypes.h rename to libs/qglview/gltypes.h diff --git a/qglview/glvbo.cpp b/libs/qglview/glvbo.cpp similarity index 100% rename from qglview/glvbo.cpp rename to libs/qglview/glvbo.cpp diff --git a/qglview/glvbo.h b/libs/qglview/glvbo.h similarity index 100% rename from qglview/glvbo.h rename to libs/qglview/glvbo.h diff --git a/qglview/glwidget.cpp b/libs/qglview/glwidget.cpp similarity index 94% rename from qglview/glwidget.cpp rename to libs/qglview/glwidget.cpp index c6d75f8..22c905a 100644 --- a/qglview/glwidget.cpp +++ b/libs/qglview/glwidget.cpp @@ -1,236 +1,236 @@ -#include "glwidget.h" -#include "renderer_simple.h" -#include "renderer_deferred_shading.h" -#include - - -GLWidget::GLWidget(QWidget *parent) : QWidget(parent) { - view_ = new QGLView(); - view_->setFlags(windowFlags() | Qt::FramelessWindowHint); - container = QWidget::createWindowContainer(view_, this); - lay = new QVBoxLayout(this); - lay->addWidget(container); - lay->setContentsMargins(0, 0, 0, 0); - lay->setSpacing(0); - setMouseTracking(true); - setWindowIcon(QIcon("://icons/qglview.png")); - connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked); -} - - -QColor GLWidget::backColor() const { - return view_->backColor(); -} - - -qreal GLWidget::lineWidth() const { - return view_->lineWidth(); -} - - -qreal GLWidget::FOV() const { - return view_->FOV(); -} - - -qreal GLWidget::depthStart() const { - return view_->depthStart(); -} - - -qreal GLWidget::depthEnd() const { - return view_->depthEnd(); -} - - -QColor GLWidget::ambientColor() const { - return view_->ambientColor(); -} - - -bool GLWidget::isLightEnabled() const { - return view_->isLightEnabled(); -} - - -bool GLWidget::isGrabMouseEnabled() const { - return view_->isGrabMouseEnabled(); -} - - -bool GLWidget::isMouseRotateEnabled() const { - return view_->isMouseRotateEnabled(); -} - - -bool GLWidget::isMouseSelectionEnabled() const { - return view_->isMouseSelectionEnabled(); -} - - -bool GLWidget::isCameraOrbit() const -{ - return view_->isCameraOrbit(); -} - - -bool GLWidget::isHoverHaloEnabled() const { - return view_->isHoverHaloEnabled(); -} - - -QColor GLWidget::hoverHaloColor() const { - return view_->hoverHaloColor(); -} - - -qreal GLWidget::hoverHaloFillAlpha() const { - return view_->hoverHaloFillAlpha(); -} - - -bool GLWidget::isSelectionHaloEnabled() const { - return view_->isSelectionHaloEnabled(); -} - - -QColor GLWidget::selectionHaloColor() const { - return view_->selectionHaloColor(); -} - - -qreal GLWidget::selectionHaloFillAlpha() const { - return view_->selectionHaloFillAlpha(); -} - - -void GLWidget::addObject(GLObjectBase * o) { - view_->addObject(o); -} - - -QByteArray GLWidget::saveCamera() { - return view_->saveCamera(); -} - - -void GLWidget::restoreCamera(const QByteArray &ba) { - view_->restoreCamera(ba); -} - - -void GLWidget::stop() { - view_->stop(); -} - - -void GLWidget::start(float freq, GLRendererBase * r) { - if (r == nullptr) r = new RendererSimple(view_); - GLRendererBase * pr = nullptr; - view_->setRenderer(r, &pr); - if (pr != nullptr && pr != r) delete pr; - view_->start(freq); -} - - -void GLWidget::setBackColor(const QColor & c) { - view_->setBackColor(c); -} - - -void GLWidget::setLineWidth(const qreal & arg) { - view_->setLineWidth(arg); -} - - -void GLWidget::setFOV(const qreal & arg) { - view_->setFOV(arg); -} - - -void GLWidget::setDepthStart(const qreal & arg) { - view_->setDepthStart(arg); -} - - -void GLWidget::setDepthEnd(const qreal & arg) { - view_->setDepthEnd(arg); -} - - -void GLWidget::setAmbientColor(const QColor & arg) { - view_->setAmbientColor(arg); -} - - -void GLWidget::setLightEnabled(const bool & arg) { - view_->setLightEnabled(arg); -} - - -void GLWidget::setGrabMouseEnabled(const bool & arg) { - view_->setGrabMouseEnabled(arg); -} - - -void GLWidget::setMouseRotateEnabled(const bool & arg) { - view_->setMouseRotateEnabled(arg); -} - - -void GLWidget::setMouseSelectionEnabled(const bool & arg) { - view_->setMouseSelectionEnabled(arg); -} - - -void GLWidget::setCameraOrbit(const bool & arg) { - view_->setCameraOrbit(arg); -} - - -void GLWidget::setHoverHaloEnabled(const bool & arg) { - view_->setHoverHaloEnabled(arg); -} - - -void GLWidget::setHoverHaloColor(const QColor & arg) { - view_->setHoverHaloColor(arg); -} - - -void GLWidget::setHoverHaloFillAlpha(const qreal & arg) { - view_->setHoverHaloFillAlpha(arg); -} - - -void GLWidget::setSelectionHaloEnabled(const bool & arg) { - view_->setSelectionHaloEnabled(arg); -} - - -void GLWidget::setSelectionHaloColor(const QColor & arg) { - view_->setSelectionHaloColor(arg); -} - - -void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) { - view_->setSelectionHaloFillAlpha(arg); -} - - -void GLWidget::viewDoubleClicked() { -// qDebug() << "click widget!!"; - if (view_->windowState() == Qt::WindowFullScreen) { -// view_->hide(); - container = QWidget::createWindowContainer(view_, this); - lay->addWidget(container); - container->show(); -// show(); - } else { -// hide(); - view_->setParent(nullptr); - view_->showFullScreen(); - lay->removeWidget(container); - } -// qDebug() << "click widge done!"; -} +#include "glwidget.h" +#include "renderer_simple.h" +#include "renderer_deferred_shading.h" +#include + + +GLWidget::GLWidget(QWidget *parent) : QWidget(parent) { + view_ = new QGLView(); + view_->setFlags(windowFlags() | Qt::FramelessWindowHint); + container = QWidget::createWindowContainer(view_, this); + lay = new QVBoxLayout(this); + lay->addWidget(container); + lay->setContentsMargins(0, 0, 0, 0); + lay->setSpacing(0); + setMouseTracking(true); + setWindowIcon(QIcon("://icons/qglview.png")); + connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked); +} + + +QColor GLWidget::backColor() const { + return view_->backColor(); +} + + +qreal GLWidget::lineWidth() const { + return view_->lineWidth(); +} + + +qreal GLWidget::FOV() const { + return view_->FOV(); +} + + +qreal GLWidget::depthStart() const { + return view_->depthStart(); +} + + +qreal GLWidget::depthEnd() const { + return view_->depthEnd(); +} + + +QColor GLWidget::ambientColor() const { + return view_->ambientColor(); +} + + +bool GLWidget::isLightEnabled() const { + return view_->isLightEnabled(); +} + + +bool GLWidget::isGrabMouseEnabled() const { + return view_->isGrabMouseEnabled(); +} + + +bool GLWidget::isMouseRotateEnabled() const { + return view_->isMouseRotateEnabled(); +} + + +bool GLWidget::isMouseSelectionEnabled() const { + return view_->isMouseSelectionEnabled(); +} + + +bool GLWidget::isCameraOrbit() const +{ + return view_->isCameraOrbit(); +} + + +bool GLWidget::isHoverHaloEnabled() const { + return view_->isHoverHaloEnabled(); +} + + +QColor GLWidget::hoverHaloColor() const { + return view_->hoverHaloColor(); +} + + +qreal GLWidget::hoverHaloFillAlpha() const { + return view_->hoverHaloFillAlpha(); +} + + +bool GLWidget::isSelectionHaloEnabled() const { + return view_->isSelectionHaloEnabled(); +} + + +QColor GLWidget::selectionHaloColor() const { + return view_->selectionHaloColor(); +} + + +qreal GLWidget::selectionHaloFillAlpha() const { + return view_->selectionHaloFillAlpha(); +} + + +void GLWidget::addObject(GLObjectBase * o) { + view_->addObject(o); +} + + +QByteArray GLWidget::saveCamera() { + return view_->saveCamera(); +} + + +void GLWidget::restoreCamera(const QByteArray &ba) { + view_->restoreCamera(ba); +} + + +void GLWidget::stop() { + view_->stop(); +} + + +void GLWidget::start(float freq, GLRendererBase * r) { + if (r == nullptr) r = new RendererSimple(view_); + GLRendererBase * pr = nullptr; + view_->setRenderer(r, &pr); + if (pr != nullptr && pr != r) delete pr; + view_->start(freq); +} + + +void GLWidget::setBackColor(const QColor & c) { + view_->setBackColor(c); +} + + +void GLWidget::setLineWidth(const qreal & arg) { + view_->setLineWidth(arg); +} + + +void GLWidget::setFOV(const qreal & arg) { + view_->setFOV(arg); +} + + +void GLWidget::setDepthStart(const qreal & arg) { + view_->setDepthStart(arg); +} + + +void GLWidget::setDepthEnd(const qreal & arg) { + view_->setDepthEnd(arg); +} + + +void GLWidget::setAmbientColor(const QColor & arg) { + view_->setAmbientColor(arg); +} + + +void GLWidget::setLightEnabled(const bool & arg) { + view_->setLightEnabled(arg); +} + + +void GLWidget::setGrabMouseEnabled(const bool & arg) { + view_->setGrabMouseEnabled(arg); +} + + +void GLWidget::setMouseRotateEnabled(const bool & arg) { + view_->setMouseRotateEnabled(arg); +} + + +void GLWidget::setMouseSelectionEnabled(const bool & arg) { + view_->setMouseSelectionEnabled(arg); +} + + +void GLWidget::setCameraOrbit(const bool & arg) { + view_->setCameraOrbit(arg); +} + + +void GLWidget::setHoverHaloEnabled(const bool & arg) { + view_->setHoverHaloEnabled(arg); +} + + +void GLWidget::setHoverHaloColor(const QColor & arg) { + view_->setHoverHaloColor(arg); +} + + +void GLWidget::setHoverHaloFillAlpha(const qreal & arg) { + view_->setHoverHaloFillAlpha(arg); +} + + +void GLWidget::setSelectionHaloEnabled(const bool & arg) { + view_->setSelectionHaloEnabled(arg); +} + + +void GLWidget::setSelectionHaloColor(const QColor & arg) { + view_->setSelectionHaloColor(arg); +} + + +void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) { + view_->setSelectionHaloFillAlpha(arg); +} + + +void GLWidget::viewDoubleClicked() { +// qDebug() << "click widget!!"; + if (view_->windowState() == Qt::WindowFullScreen) { +// view_->hide(); + container = QWidget::createWindowContainer(view_, this); + lay->addWidget(container); + container->show(); +// show(); + } else { +// hide(); + view_->setParent(nullptr); + view_->showFullScreen(); + lay->removeWidget(container); + } +// qDebug() << "click widge done!"; +} diff --git a/qglview/glwidget.h b/libs/qglview/glwidget.h similarity index 97% rename from qglview/glwidget.h rename to libs/qglview/glwidget.h index 87eb6f1..1f8597e 100644 --- a/qglview/glwidget.h +++ b/libs/qglview/glwidget.h @@ -1,88 +1,88 @@ -#ifndef GLWIDGET_H -#define GLWIDGET_H - -#include - - -class QGLView; -class GLRendererBase; -class GLObjectBase; - -class GLWidget : public QWidget -{ - Q_OBJECT - Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) - Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth) - Q_PROPERTY (qreal FOV READ FOV WRITE setFOV) - Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart) - Q_PROPERTY (qreal depthEnd READ depthEnd WRITE setDepthEnd) - Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) - Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) - Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) - Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) - Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) - Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) - Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) - Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) - Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) - Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) - Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) -public: - explicit GLWidget(QWidget *parent = nullptr); - QGLView * view() {return view_;} - - QColor backColor() const; - qreal lineWidth() const; - qreal FOV() const; - qreal depthStart() const; - qreal depthEnd() const; - QColor ambientColor() const; - bool isLightEnabled() const; - bool isGrabMouseEnabled() const; - bool isMouseRotateEnabled() const; - bool isMouseSelectionEnabled() const; - bool isCameraOrbit() const; - bool isHoverHaloEnabled() const; - QColor hoverHaloColor() const; - qreal hoverHaloFillAlpha() const; - bool isSelectionHaloEnabled() const; - QColor selectionHaloColor() const; - qreal selectionHaloFillAlpha() const; - - void addObject(GLObjectBase * o); - QByteArray saveCamera(); - void restoreCamera(const QByteArray & ba); - -public slots: - void stop(); - void start(float freq = 60.0, GLRendererBase * r = nullptr); - void setBackColor(const QColor & c); - void setLineWidth(const qreal & arg); - void setFOV(const qreal & arg); - void setDepthStart(const qreal & arg); - void setDepthEnd(const qreal & arg); - void setAmbientColor(const QColor & arg); - void setLightEnabled(const bool & arg); - void setGrabMouseEnabled(const bool & arg); - void setMouseRotateEnabled(const bool & arg); - void setMouseSelectionEnabled(const bool & arg); - void setCameraOrbit(const bool & arg); - void setHoverHaloEnabled(const bool & arg); - void setHoverHaloColor(const QColor & arg); - void setHoverHaloFillAlpha(const qreal & arg); - void setSelectionHaloEnabled(const bool & arg); - void setSelectionHaloColor(const QColor & arg); - void setSelectionHaloFillAlpha(const qreal & arg); - -private slots: - void viewDoubleClicked(); - -private: - QWidget * container; - QGLView * view_; - QLayout * lay; - -signals: -}; - -#endif // GLWIDGET_H +#ifndef GLWIDGET_H +#define GLWIDGET_H + +#include + + +class QGLView; +class GLRendererBase; +class GLObjectBase; + +class GLWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) + Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth) + Q_PROPERTY (qreal FOV READ FOV WRITE setFOV) + Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart) + Q_PROPERTY (qreal depthEnd READ depthEnd WRITE setDepthEnd) + Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) + Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) + Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) + Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) + Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) + Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) + Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) + Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) + Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) + Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) + Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) +public: + explicit GLWidget(QWidget *parent = nullptr); + QGLView * view() {return view_;} + + QColor backColor() const; + qreal lineWidth() const; + qreal FOV() const; + qreal depthStart() const; + qreal depthEnd() const; + QColor ambientColor() const; + bool isLightEnabled() const; + bool isGrabMouseEnabled() const; + bool isMouseRotateEnabled() const; + bool isMouseSelectionEnabled() const; + bool isCameraOrbit() const; + bool isHoverHaloEnabled() const; + QColor hoverHaloColor() const; + qreal hoverHaloFillAlpha() const; + bool isSelectionHaloEnabled() const; + QColor selectionHaloColor() const; + qreal selectionHaloFillAlpha() const; + + void addObject(GLObjectBase * o); + QByteArray saveCamera(); + void restoreCamera(const QByteArray & ba); + +public slots: + void stop(); + void start(float freq = 60.0, GLRendererBase * r = nullptr); + void setBackColor(const QColor & c); + void setLineWidth(const qreal & arg); + void setFOV(const qreal & arg); + void setDepthStart(const qreal & arg); + void setDepthEnd(const qreal & arg); + void setAmbientColor(const QColor & arg); + void setLightEnabled(const bool & arg); + void setGrabMouseEnabled(const bool & arg); + void setMouseRotateEnabled(const bool & arg); + void setMouseSelectionEnabled(const bool & arg); + void setCameraOrbit(const bool & arg); + void setHoverHaloEnabled(const bool & arg); + void setHoverHaloColor(const QColor & arg); + void setHoverHaloFillAlpha(const qreal & arg); + void setSelectionHaloEnabled(const bool & arg); + void setSelectionHaloColor(const QColor & arg); + void setSelectionHaloFillAlpha(const qreal & arg); + +private slots: + void viewDoubleClicked(); + +private: + QWidget * container; + QGLView * view_; + QLayout * lay; + +signals: +}; + +#endif // GLWIDGET_H diff --git a/qad/icons/alpha.png b/libs/qglview/icons/alpha.png similarity index 100% rename from qad/icons/alpha.png rename to libs/qglview/icons/alpha.png diff --git a/kx_utils/icons/application-exit.png b/libs/qglview/icons/application-exit.png similarity index 100% rename from kx_utils/icons/application-exit.png rename to libs/qglview/icons/application-exit.png diff --git a/kx_utils/icons/configure.png b/libs/qglview/icons/configure.png similarity index 100% rename from kx_utils/icons/configure.png rename to libs/qglview/icons/configure.png diff --git a/kx_utils/icons/dialog-close.png b/libs/qglview/icons/dialog-close.png similarity index 100% rename from kx_utils/icons/dialog-close.png rename to libs/qglview/icons/dialog-close.png diff --git a/qglview/icons/document-import.png b/libs/qglview/icons/document-import.png similarity index 100% rename from qglview/icons/document-import.png rename to libs/qglview/icons/document-import.png diff --git a/qglview/icons/document-new.png b/libs/qglview/icons/document-new.png similarity index 100% rename from qglview/icons/document-new.png rename to libs/qglview/icons/document-new.png diff --git a/qglview/icons/document-open.png b/libs/qglview/icons/document-open.png similarity index 100% rename from qglview/icons/document-open.png rename to libs/qglview/icons/document-open.png diff --git a/qglview/icons/document-save-.png b/libs/qglview/icons/document-save-.png similarity index 100% rename from qglview/icons/document-save-.png rename to libs/qglview/icons/document-save-.png diff --git a/qglview/icons/document-save-all.png b/libs/qglview/icons/document-save-all.png similarity index 100% rename from qglview/icons/document-save-all.png rename to libs/qglview/icons/document-save-all.png diff --git a/kx_utils/icons/document-save.png b/libs/qglview/icons/document-save.png similarity index 100% rename from kx_utils/icons/document-save.png rename to libs/qglview/icons/document-save.png diff --git a/kx_utils/icons/edit-clear-locationbar-rtl.png b/libs/qglview/icons/edit-clear-locationbar-rtl.png similarity index 100% rename from kx_utils/icons/edit-clear-locationbar-rtl.png rename to libs/qglview/icons/edit-clear-locationbar-rtl.png diff --git a/kx_utils/icons/edit-clear.png b/libs/qglview/icons/edit-clear.png similarity index 100% rename from kx_utils/icons/edit-clear.png rename to libs/qglview/icons/edit-clear.png diff --git a/kx_utils/icons/edit-copy.png b/libs/qglview/icons/edit-copy.png similarity index 100% rename from kx_utils/icons/edit-copy.png rename to libs/qglview/icons/edit-copy.png diff --git a/kx_utils/icons/edit-delete.png b/libs/qglview/icons/edit-delete.png similarity index 100% rename from kx_utils/icons/edit-delete.png rename to libs/qglview/icons/edit-delete.png diff --git a/kx_utils/icons/edit-find.png b/libs/qglview/icons/edit-find.png similarity index 100% rename from kx_utils/icons/edit-find.png rename to libs/qglview/icons/edit-find.png diff --git a/kx_utils/icons/edit-guides.png b/libs/qglview/icons/edit-guides.png similarity index 100% rename from kx_utils/icons/edit-guides.png rename to libs/qglview/icons/edit-guides.png diff --git a/kx_utils/icons/edit-paste.png b/libs/qglview/icons/edit-paste.png similarity index 100% rename from kx_utils/icons/edit-paste.png rename to libs/qglview/icons/edit-paste.png diff --git a/qad/icons/item-add.png b/libs/qglview/icons/item-add.png similarity index 100% rename from qad/icons/item-add.png rename to libs/qglview/icons/item-add.png diff --git a/qad/icons/item.png b/libs/qglview/icons/item.png similarity index 100% rename from qad/icons/item.png rename to libs/qglview/icons/item.png diff --git a/kx_utils/icons/list-add.png b/libs/qglview/icons/list-add.png similarity index 100% rename from kx_utils/icons/list-add.png rename to libs/qglview/icons/list-add.png diff --git a/qad/icons/node-add.png b/libs/qglview/icons/node-add.png similarity index 100% rename from qad/icons/node-add.png rename to libs/qglview/icons/node-add.png diff --git a/qad/icons/node.png b/libs/qglview/icons/node.png similarity index 100% rename from qad/icons/node.png rename to libs/qglview/icons/node.png diff --git a/qglengine/icons/qglview.png b/libs/qglview/icons/qglview.png similarity index 100% rename from qglengine/icons/qglview.png rename to libs/qglview/icons/qglview.png diff --git a/qglengine/icons/qglview.xcf b/libs/qglview/icons/qglview.xcf similarity index 100% rename from qglengine/icons/qglview.xcf rename to libs/qglview/icons/qglview.xcf diff --git a/qglview/icons/type-camera.png b/libs/qglview/icons/type-camera.png similarity index 100% rename from qglview/icons/type-camera.png rename to libs/qglview/icons/type-camera.png diff --git a/qglview/icons/type-geo.png b/libs/qglview/icons/type-geo.png similarity index 100% rename from qglview/icons/type-geo.png rename to libs/qglview/icons/type-geo.png diff --git a/qglview/icons/type-light.png b/libs/qglview/icons/type-light.png similarity index 100% rename from qglview/icons/type-light.png rename to libs/qglview/icons/type-light.png diff --git a/kx_utils/icons/view-grid.png b/libs/qglview/icons/view-grid.png similarity index 100% rename from kx_utils/icons/view-grid.png rename to libs/qglview/icons/view-grid.png diff --git a/kx_utils/icons/zoom-fit-best.png b/libs/qglview/icons/zoom-fit-best.png similarity index 100% rename from kx_utils/icons/zoom-fit-best.png rename to libs/qglview/icons/zoom-fit-best.png diff --git a/qglview/loader_3ds.cpp b/libs/qglview/loader_3ds.cpp similarity index 100% rename from qglview/loader_3ds.cpp rename to libs/qglview/loader_3ds.cpp diff --git a/qglview/loader_3ds.h b/libs/qglview/loader_3ds.h similarity index 100% rename from qglview/loader_3ds.h rename to libs/qglview/loader_3ds.h diff --git a/qglview/loader_ase.cpp b/libs/qglview/loader_ase.cpp similarity index 100% rename from qglview/loader_ase.cpp rename to libs/qglview/loader_ase.cpp diff --git a/qglview/loader_ase.h b/libs/qglview/loader_ase.h similarity index 100% rename from qglview/loader_ase.h rename to libs/qglview/loader_ase.h diff --git a/qglview/loader_dae.cpp b/libs/qglview/loader_dae.cpp similarity index 100% rename from qglview/loader_dae.cpp rename to libs/qglview/loader_dae.cpp diff --git a/qglview/loader_dae.h b/libs/qglview/loader_dae.h similarity index 100% rename from qglview/loader_dae.h rename to libs/qglview/loader_dae.h diff --git a/qglview/loader_obj.cpp b/libs/qglview/loader_obj.cpp similarity index 100% rename from qglview/loader_obj.cpp rename to libs/qglview/loader_obj.cpp diff --git a/qglview/loader_obj.h b/libs/qglview/loader_obj.h similarity index 100% rename from qglview/loader_obj.h rename to libs/qglview/loader_obj.h diff --git a/qglview/loader_qgl.cpp b/libs/qglview/loader_qgl.cpp similarity index 100% rename from qglview/loader_qgl.cpp rename to libs/qglview/loader_qgl.cpp diff --git a/qglview/loader_qgl.h b/libs/qglview/loader_qgl.h similarity index 100% rename from qglview/loader_qgl.h rename to libs/qglview/loader_qgl.h diff --git a/qglview/material_editor.cpp b/libs/qglview/material_editor.cpp similarity index 100% rename from qglview/material_editor.cpp rename to libs/qglview/material_editor.cpp diff --git a/qglview/material_editor.h b/libs/qglview/material_editor.h similarity index 100% rename from qglview/material_editor.h rename to libs/qglview/material_editor.h diff --git a/qglview/material_editor.ui b/libs/qglview/material_editor.ui similarity index 100% rename from qglview/material_editor.ui rename to libs/qglview/material_editor.ui diff --git a/qglview/material_map_editor.cpp b/libs/qglview/material_map_editor.cpp similarity index 100% rename from qglview/material_map_editor.cpp rename to libs/qglview/material_map_editor.cpp diff --git a/qglview/material_map_editor.h b/libs/qglview/material_map_editor.h similarity index 100% rename from qglview/material_map_editor.h rename to libs/qglview/material_map_editor.h diff --git a/qglview/material_map_editor.ui b/libs/qglview/material_map_editor.ui similarity index 100% rename from qglview/material_map_editor.ui rename to libs/qglview/material_map_editor.ui diff --git a/qglview/openglwindow.cpp b/libs/qglview/openglwindow.cpp similarity index 95% rename from qglview/openglwindow.cpp rename to libs/qglview/openglwindow.cpp index 375d1fa..cb3bc2a 100644 --- a/qglview/openglwindow.cpp +++ b/libs/qglview/openglwindow.cpp @@ -1,96 +1,96 @@ -#include "openglwindow.h" -#include -#include -#include -#include -#include - - -OpenGLWindow::OpenGLWindow(QWindow *parent) - : QWindow(parent) - , m_context(nullptr) - , m_device(nullptr) -{ - setFlags(flags() | Qt::FramelessWindowHint); - setSurfaceType(QWindow::OpenGLSurface); - QSurfaceFormat format = QSurfaceFormat::defaultFormat(); -// qDebug() << format; -#ifdef QT_OPENGL_ES_2 - format.setRenderableType(QSurfaceFormat::OpenGLES); -#else - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { - format.setVersion(2, 0); - format.setProfile(QSurfaceFormat::NoProfile); - } -#endif - format.setDepthBufferSize(24); - format.setSamples(8); -// format.setStencilBufferSize(8); - setFormat(format); - QSurfaceFormat::setDefaultFormat(format); -} - - -OpenGLWindow::~OpenGLWindow() { - delete m_device; -} - - -void OpenGLWindow::render(QPainter *painter) { -} - - -void OpenGLWindow::initialize() { -} - - -void OpenGLWindow::render() { -// if (!m_device) m_device = new QOpenGLPaintDevice; -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); -// m_device->setSize(size() * devicePixelRatio()); -// m_device->setDevicePixelRatio(devicePixelRatio()); -// QPainter painter(m_device); -// render(&painter); -} - - -void OpenGLWindow::renderLater() { - requestUpdate(); -} - - -bool OpenGLWindow::event(QEvent *event) { - switch (event->type()) { - case QEvent::UpdateRequest: - renderNow(); - return true; - default: - return QWindow::event(event); - } -} - - -void OpenGLWindow::exposeEvent(QExposeEvent *event) { - if (isExposed()) renderNow(); -} - - -void OpenGLWindow::renderNow() { - if (!isExposed()) - return; - bool needsInitialize = false; - if (!m_context) { - m_context = new QOpenGLContext(this); - m_context->setFormat(requestedFormat()); - m_context->create(); - needsInitialize = true; - } - m_context->makeCurrent(this); - if (needsInitialize) { - initializeOpenGLFunctions(); - initialize(); - } - render(); - m_context->swapBuffers(this); -} - +#include "openglwindow.h" +#include +#include +#include +#include +#include + + +OpenGLWindow::OpenGLWindow(QWindow *parent) + : QWindow(parent) + , m_context(nullptr) + , m_device(nullptr) +{ + setFlags(flags() | Qt::FramelessWindowHint); + setSurfaceType(QWindow::OpenGLSurface); + QSurfaceFormat format = QSurfaceFormat::defaultFormat(); +// qDebug() << format; +#ifdef QT_OPENGL_ES_2 + format.setRenderableType(QSurfaceFormat::OpenGLES); +#else + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(2, 0); + format.setProfile(QSurfaceFormat::NoProfile); + } +#endif + format.setDepthBufferSize(24); + format.setSamples(8); +// format.setStencilBufferSize(8); + setFormat(format); + QSurfaceFormat::setDefaultFormat(format); +} + + +OpenGLWindow::~OpenGLWindow() { + delete m_device; +} + + +void OpenGLWindow::render(QPainter *painter) { +} + + +void OpenGLWindow::initialize() { +} + + +void OpenGLWindow::render() { +// if (!m_device) m_device = new QOpenGLPaintDevice; +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); +// m_device->setSize(size() * devicePixelRatio()); +// m_device->setDevicePixelRatio(devicePixelRatio()); +// QPainter painter(m_device); +// render(&painter); +} + + +void OpenGLWindow::renderLater() { + requestUpdate(); +} + + +bool OpenGLWindow::event(QEvent *event) { + switch (event->type()) { + case QEvent::UpdateRequest: + renderNow(); + return true; + default: + return QWindow::event(event); + } +} + + +void OpenGLWindow::exposeEvent(QExposeEvent *event) { + if (isExposed()) renderNow(); +} + + +void OpenGLWindow::renderNow() { + if (!isExposed()) + return; + bool needsInitialize = false; + if (!m_context) { + m_context = new QOpenGLContext(this); + m_context->setFormat(requestedFormat()); + m_context->create(); + needsInitialize = true; + } + m_context->makeCurrent(this); + if (needsInitialize) { + initializeOpenGLFunctions(); + initialize(); + } + render(); + m_context->swapBuffers(this); +} + diff --git a/qglview/openglwindow.h b/libs/qglview/openglwindow.h similarity index 94% rename from qglview/openglwindow.h rename to libs/qglview/openglwindow.h index 6816665..504028c 100644 --- a/qglview/openglwindow.h +++ b/libs/qglview/openglwindow.h @@ -1,36 +1,36 @@ -#include -#include - -class QPainter; -class QOpenGLContext; -class QOpenGLPaintDevice; - - -class OpenGLWindow : public QWindow, protected QOpenGLFunctions -{ - Q_OBJECT -public: - explicit OpenGLWindow(QWindow *parent = nullptr); - ~OpenGLWindow(); - - virtual void render(QPainter *painter); - virtual void render(); - - virtual void initialize(); - - QOpenGLContext * context() {return m_context;} - -public slots: - void renderLater(); - void renderNow(); - -protected: - bool event(QEvent *event) override; - - void exposeEvent(QExposeEvent *event) override; - -private: - QOpenGLContext *m_context; - QOpenGLPaintDevice *m_device; -}; - +#include +#include + +class QPainter; +class QOpenGLContext; +class QOpenGLPaintDevice; + + +class OpenGLWindow : public QWindow, protected QOpenGLFunctions +{ + Q_OBJECT +public: + explicit OpenGLWindow(QWindow *parent = nullptr); + ~OpenGLWindow(); + + virtual void render(QPainter *painter); + virtual void render(); + + virtual void initialize(); + + QOpenGLContext * context() {return m_context;} + +public slots: + void renderLater(); + void renderNow(); + +protected: + bool event(QEvent *event) override; + + void exposeEvent(QExposeEvent *event) override; + +private: + QOpenGLContext *m_context; + QOpenGLPaintDevice *m_device; +}; + diff --git a/qglview/plugin/CMakeLists.txt b/libs/qglview/plugin/CMakeLists.txt similarity index 98% rename from qglview/plugin/CMakeLists.txt rename to libs/qglview/plugin/CMakeLists.txt index 2fd203c..4245507 100644 --- a/qglview/plugin/CMakeLists.txt +++ b/libs/qglview/plugin/CMakeLists.txt @@ -1 +1 @@ -_qt_plugin(qglview "Gui;Widgets;OpenGL" "qglview") +_qt_plugin(qglview "Gui;Widgets;OpenGL" "qglview") diff --git a/qglengine/plugin/qglview_designerplugin.cpp b/libs/qglview/plugin/qglview_designerplugin.cpp similarity index 100% rename from qglengine/plugin/qglview_designerplugin.cpp rename to libs/qglview/plugin/qglview_designerplugin.cpp diff --git a/qglengine/plugin/qglview_designerplugin.h b/libs/qglview/plugin/qglview_designerplugin.h similarity index 100% rename from qglengine/plugin/qglview_designerplugin.h rename to libs/qglview/plugin/qglview_designerplugin.h diff --git a/qglview/plugin/qglviewplugin.cpp b/libs/qglview/plugin/qglviewplugin.cpp similarity index 100% rename from qglview/plugin/qglviewplugin.cpp rename to libs/qglview/plugin/qglviewplugin.cpp diff --git a/qglengine/plugin/qglviewplugin.h b/libs/qglview/plugin/qglviewplugin.h similarity index 100% rename from qglengine/plugin/qglviewplugin.h rename to libs/qglview/plugin/qglviewplugin.h diff --git a/qglview/propertyeditor.cpp b/libs/qglview/propertyeditor.cpp similarity index 100% rename from qglview/propertyeditor.cpp rename to libs/qglview/propertyeditor.cpp diff --git a/qglview/propertyeditor.h b/libs/qglview/propertyeditor.h similarity index 100% rename from qglview/propertyeditor.h rename to libs/qglview/propertyeditor.h diff --git a/qglview/qglview.cpp b/libs/qglview/qglview.cpp similarity index 96% rename from qglview/qglview.cpp rename to libs/qglview/qglview.cpp index 74adf53..1878a40 100644 --- a/qglview/qglview.cpp +++ b/libs/qglview/qglview.cpp @@ -1,846 +1,846 @@ -/* - QGLView - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "qglview.h" - -#include -#include - - -QGLView::QGLView(): OpenGLWindow(), fbo_selection(3) { -// setFrameShape(QFrame::NoFrame); -// setViewportUpdateMode(FullViewportUpdate); -// setCacheMode(CacheNone); -// setMouseTracking(true); -// setFocusPolicy(Qt::WheelFocus); -// setScene(new QGraphicsScene()); -// setInteractive(true); - setIcon(QIcon("://icons/qglview.png")); - deleting_ = false; - timer = 0; - need_init_ = is_first_draw = true; - objects_.is_root = true; - objects_.view_ = this; - backColor_ = Qt::darkGray; - hoverHaloColor_ = QColor(195, 140, 255, 96); - selectionHaloColor_ = QColor(175, 255, 140); - ambientColor_ = QColor(10, 10, 10); - lastPos = QPoint(-1, -1); - lineWidth_ = 1.; - max_anisotropic = 1; - max_texture_chanels = 8; - cameraOrbit_ = lightEnabled_ = true; - shaders_supported = selecting_ = customMouseMove_ = false; - sel_button = Qt::LeftButton; - sel_mod = Qt::NoModifier; - renderer_ = nullptr; - fps_cnt = 0; - fps_tm = fps_ = 0.; - sel_obj = hov_obj = nullptr; - fogDensity_ = fogEnd_ = 1.; - fogStart_ = 0.; - fogMode_ = Exp; - hoverHaloFill_ = 0.333f; - selectionHaloFill_ = 0.5f; - //lmode = Simple; - shader_select = shader_halo = nullptr; - setFeature(qglMSAA, false); - setFeature(qglFXAA, false); - setFeature(qglLinearFiltering, true); - setFeature(qglAnisotropicLevel, 8); - setFeature(qglHDR, false); - setFeature(qglEyeAccomodationEnabled, false); - setFeature(qglEyeAccomodationTime, 16.); - setFeature(qglEyeAccomodationMaxSpeed, 0.2); - setFeature(qglBloomEnabled, false); - setFeature(qglBloomThreshold, 0.9); - setFeature(qglBloomFactor, 1.); - setFeature(qglBloomRadius, 8); - setFeature(qglMotionBlurEnabled, false); - setFeature(qglMotionBlurFactor, 1.); - setFeature(qglMotionBlurSteps, 8); - setFeature(qglShadowsEnabled, false); - setFeature(qglShadowsMapSize, 512); - setFeature(qglShadowsSoftEnabled, true); - setFeature(qglReflectionsEnabled, false); - setFeature(qglReflectionsBlur, true); - setFeature(qglSSAOEnabled, false); - setFeature(qglSSAORadius, 5); - setFeature(qglDepthOfFieldEnabled, false); - setFeature(qglDepthOfFieldAutoFocusEnabled, true); - setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1); - setFeature(qglDepthOfFieldFocus, 1.); - setFeature(qglDepthOfFieldDiaphragm, 8.); - mouse_first = mouseSelect_ = hoverHalo_ = selectionHalo_ = true; - mouseRotate_ = true; - fogEnabled_ = is_init = grabMouse_ = shaders_bind = changed_ = false; - rmode = GLObjectBase::Fill; - sel_mode = QGLView::SingleSelection; -// sel_pen = QPen(Qt::black, 1, Qt::DashLine); -// sel_brush = QBrush(QColor(170, 100, 255, 120)); - camera()->setAim(QVector3D()); - camera()->setPos(QVector3D(2, 2, 2)); - camera()->setName("Camera"); - addObject(camera()); - emit cameraPosChanged(camera()->pos()); - //camera().aim_ = camera().pos_; - ktm_.restart(); -} - - -QGLView::~QGLView() { - stop(); - if (shader_select) delete shader_select; - if (shader_halo) delete shader_halo; - deleting_ = true; -} - - -void QGLView::stop() { - if (timer) killTimer(timer); - timer = 0; -} - - -void QGLView::start(float freq) { - stop(); - timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq)); -} - - -GLRendererBase * QGLView::renderer() { - return renderer_; -} - - -void QGLView::setRenderer(GLRendererBase * r, GLRendererBase ** prev) { - if (prev != nullptr) *prev = renderer_; - renderer_ = r; -} - - -void QGLView::addObject(GLObjectBase * o) { - objects_.addChild(o); - o->setView(this); - collectLights(); - QList cl = o->children(true); - cl << o; - foreach (GLObjectBase * i, cl) { - emit objectAdded(i); - } - if (is_init) { - o->init(); - } -} - - -int QGLView::objectsCount(bool all) { - if (!all) return objects_.childCount(); - int cnt = 0; - objectsCountInternal(&cnt, &objects_); - return cnt; -} - - -void QGLView::removeObject(GLObjectBase * o, bool inChildren) { - o->setView(nullptr); - if (inChildren) - removeObjectInternal(o, &objects_); - else - objects_.removeChild(o); - objectDeleted(o); -} - - -void QGLView::removeObject(GLObjectBase & o, bool inChildren) { - removeObject(&o, inChildren); -} - - -void QGLView::clearObjects(bool deleteAll) { - removeObject(camera_); - objects_.clearChildren(deleteAll); - addObject(camera()); - selectObject(nullptr); - hov_obj = nullptr; -} - - -QList QGLView::objects(bool all) { - return objects_.children(all); -} - - -int QGLView::lightsCount() const { - return lights_.size(); -} - - -void QGLView::removeLight(int index) { - removeObject(lights_.at(index)); - lights_.removeAt(index); -} - - -void QGLView::removeLight(Light * l) { - foreach (Light * i, lights_) - if (i == l) removeObject(i); - lights_.removeAll(l); -} - - -void QGLView::clearLights(bool deleteAll) { - if (deleteAll) - foreach (Light * i, lights_) delete i; - lights_.clear(); -} - - -void QGLView::addTexture(const QString & path) { - textures_manager->addTexture(path); -} - - -void QGLView::addAnimation(const QString & dir, const QString & name) { - textures_manager->addAnimation(dir, name); -} - - -Light * QGLView::light(int index) { - return lights_[index]; -} - - -Light * QGLView::light(const QString & name) { - foreach (Light * i, lights_) - if (i->name_ == name) return i; - return nullptr; -} - - -void QGLView::selectObject(GLObjectBase * o) { - if (o == sel_obj) return; - GLObjectBase * pso = sel_obj; - sel_obj = o; - emit selectionChanged(sel_obj, pso); -} - - -void QGLView::resizeEvent(QResizeEvent * e) { - renderLater(); -} - -void QGLView::timerEvent(QTimerEvent *) { - renderNow(); - if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return; - Qt::KeyboardModifiers km = QApplication::keyboardModifiers(); - foreach (int i, keys_) - emit keyEvent((Qt::Key)i, km); -} - - -void QGLView::render() { - if (!isVisible()) return; - resizeGL(width(), height()); - QRect g_rect(QPoint(), size()); - emit glBeforePaint(); - //qDebug() << "paintGL"; - //QMutexLocker ml_v(&v_mutex); - glEnable(GL_CULL_FACE); - //glDisable(GL_CULL_FACE); - camera()->apply(aspect); - //objects_.preparePos(camera()); - start_rp.cam_offset_matrix = camera()->offsetMatrix(); - start_rp.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); - start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); - //objects_.buildTransform(); - - /// Selection detect - //glClearFramebuffer(QColor(100, 0, 0, 0)); - if (mouseSelect_) { - glReleaseTextures(); - glEnableDepth(); - glDisable(GL_TEXTURE_1D); - glDisable(GL_TEXTURE_2D); - glDisable(GL_TEXTURE_CUBE_MAP); - glDisable(GL_MULTISAMPLE); - glDisable(GL_LIGHTING); - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - glDisable(GL_RESCALE_NORMAL); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - fbo_selection.bind(); - fbo_selection.setWriteBuffer(0); - glClearFramebuffer(QColor(0, 0, 0, 0)); - if (shaders_supported && shader_select->isLinked()) shader_select->bind(); - renderSelection(); - if (shaders_supported && shader_select->isLinked()) shader_select->release(); - uchar cgid[4] = {0, 0, 0, 0}; - uint iid = 0; - GLObjectBase * so = nullptr; - if (!g_rect.contains(lastPos)) { - if (hov_obj != nullptr) { - hov_obj = nullptr; - emit hoverChanged(nullptr, hov_obj); - } - } else { - glReadPixels(lastPos.x(), height() - lastPos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, cgid); - iid = uint(cgid[0] << 24) | uint(cgid[1] << 16) | uint(cgid[2] << 8) | cgid[3]; - so = ids.value(iid, nullptr); - //qDebug() <name() << cgid[3]; - } - if (selectionHalo_ && sel_obj) { - fbo_selection.setWriteBuffer(2); - renderHalo(sel_obj, qHash((quint64)sel_obj), selectionHaloColor_, selectionHaloFill_); - } - if (hoverHalo_ && hov_obj) { - fbo_selection.setWriteBuffer(1); - renderHalo(hov_obj, iid, hoverHaloColor_, hoverHaloFill_); - } - fbo_selection.release(); - glEnableDepth(); - /*glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY);*/ - } - - camera()->apply(aspect); - start_rp.cam_offset_matrix = camera()->offsetMatrix(); - cur_mvpm = start_rp.proj_matrix * start_rp.view_matrix * start_rp.cam_offset_matrix; - //objects_.preparePos(camera()); - - static GLRendererBase * prev_rend = nullptr; - glShadeModel(GL_SMOOTH); - if (prev_rend != renderer_) { - prev_rend = renderer_; - if (renderer_ != nullptr) { - renderer_->init(width(), height()); - renderer_->resize(width(), height()); - renderer_->reloadShaders(); - } - } - emit glBeginPaint(); - if (renderer_ != nullptr) { - renderer_->rp.prepare(); - renderer_->prepareScene(); - renderer_->renderScene(); - } - emit glPainting(); - glUseProgram(0); - if (selectionHalo_ || hoverHalo_) { - glReleaseTextures(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - //glClearFramebuffer(Qt::black, false); - - glActiveTexture(GL_TEXTURE0); - glEnable(GL_BLEND); - glDisable(GL_TEXTURE_CUBE_MAP); - glDisable(GL_LIGHTING); - glDisableDepth(); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - if (selectionHalo_ && sel_obj) { - glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(2)); - //qDebug() << "draw sel"; - glDrawQuad(); - } - if (hoverHalo_ && hov_obj) { - glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(1)); - //qDebug() << "draw hover"; - //glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg")); - glDrawQuad(); - } - } - - glResetAllTransforms(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glUseProgram(0); - - //glDisable(GL_BLEND); - //glDisable(GL_LIGHTING); - //glActiveTexture(GL_TEXTURE0); - //glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg")); - //glDrawQuad(); - - emit glEndPaint(); - - /*releaseShaders(); - glActiveTextureChannel(0); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glColor4f(0.3, 0.5, 0.8, 0.5); - glResetAllTransforms(); - glBegin(GL_QUADS); - glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f); - glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.); - glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f); - glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f); - glEnd();*/ - /* - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glDisable(GL_LIGHTING); - glActiveTextureChannel(0); - glBindTexture(GL_TEXTURE_2D, fbo->texture()); - glDisable(GL_DEPTH_TEST); - glBegin(GL_QUADS); - glColor3f(1.f, 1.f, 1.f); - glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f); - glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f); - glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f); - glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.); - glEnd(); - glEnable(GL_DEPTH_TEST);*/ - fps_tm += time.elapsed(); - time.restart(); - fps_cnt++; - if (fps_tm < 1000.) return; - fps_ = fps_cnt / fps_tm * 1000.; - fps_tm = 0.; - fps_cnt = 0; -} - - -void QGLView::initialize() { - //initializeOpenGLFunctions(); - glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glEnableDepth(); - glEnable(GL_CULL_FACE); - glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); - glActiveTexture(GL_TEXTURE0 + 3); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glEnable(GL_TEXTURE_GEN_R); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glActiveTexture(GL_TEXTURE0); - glShadeModel(GL_SMOOTH); - glCullFace(GL_BACK); - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT, GL_DIFFUSE); - - textures_manager->loadTextures(); - objects_.initInternal(); - checkCaps(); - - shader_select = new QOpenGLShaderProgram(context()); - shader_halo = new QOpenGLShaderProgram(context()); - reloadThisShaders(); - is_init = true; - //resizeGL(width(), height()); - need_init_ = false; - emit glInitializeDone(); -} - - -void QGLView::renderHalo(const GLObjectBase * obj, const uint iid, const QColor & color, const float & fill) { - if (!shaders_supported) return; - if (!shader_halo) return; - if (!shader_halo->isLinked()) return; - if (obj) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture()); - shader_halo->bind(); - shader_halo->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); - shader_halo->setUniformValue("t0", 0); - shader_halo->setUniformValue("dt", QVector2D(1.f / width(), 1.f / height())); - shader_halo->setUniformValue("selected", QVector4D(float((iid >> 24) & 0xFF) / 255.f, - float((iid >> 16) & 0xFF) / 255.f, - float((iid >> 8) & 0xFF) / 255.f, - float( iid & 0xFF) / 255.f)); - shader_halo->setUniformValue("color", color); - shader_halo->setUniformValue("fill", GLfloat(fill)); - //qDebug() << "render halo" << iid << shader_halo->log() << shader_halo->programId(); - glDisableDepth(); - //glClearFramebuffer(color); - glDrawQuad(shader_halo); - glDepthMask(GL_TRUE); - //glFlush(); - shader_halo->release(); - } else { - glClearFramebuffer(Qt::black, false); - } -} - - -void QGLView::renderSelection() { -// cid = 1; - ids.clear(); - if (shaders_supported) { - if (shader_select) { - if (shader_select->isLinked()) { - sh_id_loc = shader_select->uniformLocation("id"); - shader_select->setUniformValue("z_far", GLfloat(depthEnd())); - shader_select->setUniformValue("z_near", GLfloat(depthStart())); - } - } - } - //qDebug() << sh_id_loc; - start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); - glPushMatrix(); - renderSingleSelection(objects_); - glPopMatrix(); -} - - -void QGLView::renderSingleSelection(GLObjectBase & o) { - if (!o.isInit()) { - o.init(); - o.loadTextures(); - } - if (!o.visible_ || !o.select_) return; - QMatrix4x4 curview = start_rp.view_matrix * start_rp.cam_offset_matrix * o.itransform_; - uint id = qHash((quint64)&o); - ids.insert(id, &o); - glLineWidth(o.line_width > 0.f ? o.line_width : lineWidth_); - glPointSize(o.line_width > 0.f ? o.line_width : lineWidth_); - if (shaders_supported){ - if (shader_select) { - if (shader_select->isLinked()) { - setUniformMatrices(shader_select, start_rp.proj_matrix, curview); - shader_select->setUniformValue(sh_id_loc, QVector4D(float((id >> 24) & 0xFF) / 255.f, - float((id >> 16) & 0xFF) / 255.f, - float((id >> 8) & 0xFF) / 255.f, - float(id & 0xFF) / 255.f)); - } - } - } else { - setGLMatrix(curview); - glColor4f(float((id >> 24) & 0xFF) / 255.f, - float((id >> 16) & 0xFF) / 255.f, - float((id >> 8) & 0xFF) / 255.f, - float(id & 0xFF) / 255.f); - } - //qDebug() << o.name() << "assign to" << sh_id_loc << cid; - //glColor4f(float((cid >> 24) & 0xFF) / 255.f, float((cid >> 16) & 0xFF) / 255.f, float((cid >> 8) & 0xFF) / 255.f, float(cid & 0xFF) / 255.f); -// ++cid; - o.draw(nullptr, true); - foreach (GLObjectBase * i, o.children_) - renderSingleSelection(*i); -} - - -void QGLView::collectLights() { - lights_.clear(); - collectObjectLights(&objects_); -} - - -void QGLView::objectDeleted(GLObjectBase * o) { - if (deleting_) return; - //qDebug() << "del" << o; - if (sel_obj == o) selectObject(nullptr); - if (hov_obj == o) hov_obj = nullptr; - collectLights(); -} - - -void QGLView::collectObjectLights(GLObjectBase * o) { - if (o->type_ == GLObjectBase::glLight) { - lights_ << globject_cast(o); - o->view_ = this; - } - foreach (GLObjectBase * i, o->children()) - collectObjectLights(i); -} - - -void QGLView::objectsCountInternal(int * cnt, GLObjectBase * where) { - ++(*cnt); - foreach (GLObjectBase * i, where->children_) - objectsCountInternal(cnt, i); -} - - -void QGLView::removeObjectInternal(GLObjectBase * o, GLObjectBase * where) { - foreach (GLObjectBase * i, where->children_) { - if (o == i) - where->removeChild(i); - else - removeObjectInternal(o, i); - objectDeleted(i); - } -} - - -void QGLView::checkCaps() { - glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic); - //glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_chanels); - //qDebug() << max_texture_chanels; - //qDebug() << max_texture_chanels; - shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms(); -} - - -void QGLView::reloadThisShaders() { - if (!shaders_supported) return; - loadShaders(shader_select, "selection", "://shaders"); - loadShaders(shader_halo, "selection_halo", "://shaders"); - //loadShaders(shader_rope, "rope", "://shaders"); -} - -void QGLView::glReleaseTextures(int channels) { - for (int i = channels - 1; i >= 0; --i) { - glActiveTexture(GL_TEXTURE0 + i); - glBindTexture(GL_TEXTURE_2D, 0); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); - } -} - - -void QGLView::applyFog() { - GLfloat fog_col[4] = {float(fogColor_.redF()), float(fogColor_.greenF()), float(fogColor_.blueF()), .0f}; - if (fogEnabled_) { - glEnable(GL_FOG); - glFogf(GL_FOG_DENSITY, fogDensity_); - glFogf(GL_FOG_START, fogStart_); - glFogf(GL_FOG_END, fogEnd_); - glFogi(GL_FOG_MODE, fogMode_); - fog_col[0] = fogColor_.redF(); - fog_col[1] = fogColor_.greenF(); - fog_col[2] = fogColor_.blueF(); - glFogfv(GL_FOG_COLOR, fog_col); - } else glDisable(GL_FOG); -} - - -void QGLView::resizeGL(int width, int height) { - if (!is_init) return; - if (width <= 0 || height <= 0) return; - if (prev_size == QSize(width, height)) return; - prev_size = QSize(width, height); - aspect = float(width) / float(height); - if (renderer_) renderer_->resize(width, height); - mouse_first = true; - //qDebug() << "resize" << width << height; - fbo_selection.resize(width, height); - iaspect = (aspect == 0.f) ? 0. : 1 / aspect; - glViewport(0, 0, width, height); - emit glResize(width, height); -} - - -void QGLView::mouseReleaseEvent(QMouseEvent * e) { -// qDebug() << "mouseReleaseEvent" << e << isActive(); -// QGraphicsView::mouseReleaseEvent(e); - //setCursor(QCursor(Qt::ArrowCursor)); - selecting_ = false; - if (mouseSelect_ && e->button() == Qt::LeftButton) { - if ((lastPos - downPos).manhattanLength() < 8) { - if (sel_obj != hov_obj) - selectObject(hov_obj); - } - } - emit glMouseReleaseEvent(e); -} - - -void QGLView::mousePressEvent(QMouseEvent * e) { -// qDebug() << "mousePressEvent" << e << isActive(); -// QGraphicsView::mousePressEvent(e); -// mouseThis_ = (scene()->itemAt(mapToScene(e->pos()) , QTransform() ) == 0); - selecting_ = false; - if (!QRect(QPoint(), size()).contains(e->pos())) return; - /// TODO select by rect - //if (e->button() == sel_button && e->modifiers() == sel_mod) - // selecting_ = true; - lastPos = e->pos(); - downPos = lastPos; - //qDebug() << mouseThis_; - emit glMousePressEvent(e); -} - - -void QGLView::mouseMoveEvent(QMouseEvent * e) { -// qDebug() << "mouseMoveEvent" << e << isActive(); -// QGraphicsView::mouseMoveEvent(e); - //lastPos = e->pos(); - if (selecting_) { - return; - } -// if (!QRect(QPoint(), size()).contains(e->pos())) return; - //if (scene()->itemAt(mapToScene(e->pos())) != 0) return; - ///qDebug() << e->x() << e->y(); - QRect g_rect(QPoint(), size()); - if (mouseRotate_) { - float dx = e->x() - lastPos.x(); - float dy = e->y() - lastPos.y(); - if (e->buttons() & Qt::LeftButton) { - //camera().angle_z += dx / 4.; - //camera().angle_xy += dy / 4.; - if (cameraOrbit_) { - camera()->orbitZ(dx / 4.f); - camera()->orbitXY(dy / 4.f); - } else { - camera()->rotateZ(dx / 4.f); - camera()->rotateXY(dy / 4.f); - } - emit cameraPosChanged(camera()->pos()); - } else if (e->buttons() & Qt::RightButton) { - float ad = camera()->distance(); - camera()->moveLeft(dx / 1000.f * ad); - camera()->moveUp(dy / 1000.f * ad); - //camera().pos.setX(camera().pos.x() + camera().pos.z() * dx / 500.); - //camera().pos.setY(camera().pos.y() - camera().pos.z() * dy / 500.); - emit cameraPosChanged(camera()->pos()); - } - //lights[0]->pos_ = camera().pos(); - } - if (customMouseMove_) emit customMouseMoveEvent(e->pos(), lastPos, e->buttons()); - lastPos = e->pos(); - if (grabMouse_) { - //if (!isrunning) return; - QCursor::setPos(mapToGlobal(QRect(QPoint(), size()).center())); - static bool mouse_sec = false; - if (mouse_sec) { - mouse_sec = false; - return; - } - if (mouse_first) { - mouse_first = false; - mouse_sec = true; - //qDebug() << "first" << e->pos(); - return; - } - lastPos = g_rect.center(); - int dx = e->x() - lastPos.x(); - int dy = e->y() - lastPos.y(); - emit glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers())); - return; - } - emit glMouseMoveEvent(e); -} - - -void QGLView::wheelEvent(QWheelEvent * e) { - if (mouseRotate_) { - if (e->delta() > 0) camera()->flyCloser(0.1f); //camera().pos.setZ(camera().pos.z() - 0.1 * camera().pos.z()); - if (e->delta() < 0) camera()->flyFarer(0.1f); //camera().pos.setZ(camera().pos.z() + 0.1 * camera().pos.z()); - emit cameraPosChanged(camera()->pos()); - } - emit glWheelEvent(e); -} - - -void QGLView::leaveEvent(QEvent * ) { - lastPos = QPoint(-1, -1); - //qDebug() << lastPos; -} - - -void QGLView::keyPressEvent(QKeyEvent * e) { - emit glKeyPressEvent(e); - if (e->key() > 0) keys_.insert(e->key()); - if (e->key() == Qt::Key_F11) { - emit doubleClick(); - } -} - - -void QGLView::keyReleaseEvent(QKeyEvent * e) { - emit glKeyReleaseEvent(e); - keys_.remove(e->key()); -} - - -void QGLView::focusOutEvent(QFocusEvent *) { - keys_.clear(); -} - - -void QGLView::mouseDoubleClickEvent(QMouseEvent * e) { - if (e->buttons().testFlag(Qt::MidButton)) - emit doubleClick(); -} - - -QByteArray QGLView::saveCamera() { - ChunkStream cs; - const Camera * c = camera(); - cs.add(1, c->posX()); - cs.add(2, c->posY()); - cs.add(3, c->posZ()); - cs.add(4, c->aim().x()); - cs.add(5, c->aim().y()); - cs.add(6, c->aim().z()); - cs.add(7, c->angleZ()); - cs.add(8, c->angleXY()); - cs.add(9, c->angleRoll()); - cs.add(10, c->FOV()); - return cs.data(); -} - - -void QGLView::restoreCamera(const QByteArray &ba) { - if (ba.isEmpty()) return; - ChunkStream cs(ba); - QVector3D pos, aim, ang; - while (!cs.atEnd()) { - switch (cs.read()) { - case 1: pos.setX(cs.getData()); break; - case 2: pos.setY(cs.getData()); break; - case 3: pos.setZ(cs.getData()); break; - case 4: aim.setX(cs.getData()); break; - case 5: aim.setY(cs.getData()); break; - case 6: aim.setZ(cs.getData()); break; - case 7: ang.setZ(cs.getData()); break; - case 8: ang.setY(cs.getData()); break; - case 9: ang.setX(cs.getData()); break; - case 10: setFOV(cs.getData()); break; - default: break; - } - } - camera()->setPos(pos); - camera()->setAim(aim); - camera()->setAngles(ang); -} - - -QByteArray QGLView::saveFeatures() { - QByteArray ba; - QDataStream ds(&ba, QIODevice::WriteOnly); - ds << features_; - return ba; -} - - -void QGLView::restoreFeatures(const QByteArray & ba) { - QHash f; - QDataStream ds(ba); - ds >> f; - features_ = f; -} - +/* + QGLView + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include "qglview.h" + +#include +#include + + +QGLView::QGLView(): OpenGLWindow(), fbo_selection(3) { +// setFrameShape(QFrame::NoFrame); +// setViewportUpdateMode(FullViewportUpdate); +// setCacheMode(CacheNone); +// setMouseTracking(true); +// setFocusPolicy(Qt::WheelFocus); +// setScene(new QGraphicsScene()); +// setInteractive(true); + setIcon(QIcon("://icons/qglview.png")); + deleting_ = false; + timer = 0; + need_init_ = is_first_draw = true; + objects_.is_root = true; + objects_.view_ = this; + backColor_ = Qt::darkGray; + hoverHaloColor_ = QColor(195, 140, 255, 96); + selectionHaloColor_ = QColor(175, 255, 140); + ambientColor_ = QColor(10, 10, 10); + lastPos = QPoint(-1, -1); + lineWidth_ = 1.; + max_anisotropic = 1; + max_texture_chanels = 8; + cameraOrbit_ = lightEnabled_ = true; + shaders_supported = selecting_ = customMouseMove_ = false; + sel_button = Qt::LeftButton; + sel_mod = Qt::NoModifier; + renderer_ = nullptr; + fps_cnt = 0; + fps_tm = fps_ = 0.; + sel_obj = hov_obj = nullptr; + fogDensity_ = fogEnd_ = 1.; + fogStart_ = 0.; + fogMode_ = Exp; + hoverHaloFill_ = 0.333f; + selectionHaloFill_ = 0.5f; + //lmode = Simple; + shader_select = shader_halo = nullptr; + setFeature(qglMSAA, false); + setFeature(qglFXAA, false); + setFeature(qglLinearFiltering, true); + setFeature(qglAnisotropicLevel, 8); + setFeature(qglHDR, false); + setFeature(qglEyeAccomodationEnabled, false); + setFeature(qglEyeAccomodationTime, 16.); + setFeature(qglEyeAccomodationMaxSpeed, 0.2); + setFeature(qglBloomEnabled, false); + setFeature(qglBloomThreshold, 0.9); + setFeature(qglBloomFactor, 1.); + setFeature(qglBloomRadius, 8); + setFeature(qglMotionBlurEnabled, false); + setFeature(qglMotionBlurFactor, 1.); + setFeature(qglMotionBlurSteps, 8); + setFeature(qglShadowsEnabled, false); + setFeature(qglShadowsMapSize, 512); + setFeature(qglShadowsSoftEnabled, true); + setFeature(qglReflectionsEnabled, false); + setFeature(qglReflectionsBlur, true); + setFeature(qglSSAOEnabled, false); + setFeature(qglSSAORadius, 5); + setFeature(qglDepthOfFieldEnabled, false); + setFeature(qglDepthOfFieldAutoFocusEnabled, true); + setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1); + setFeature(qglDepthOfFieldFocus, 1.); + setFeature(qglDepthOfFieldDiaphragm, 8.); + mouse_first = mouseSelect_ = hoverHalo_ = selectionHalo_ = true; + mouseRotate_ = true; + fogEnabled_ = is_init = grabMouse_ = shaders_bind = changed_ = false; + rmode = GLObjectBase::Fill; + sel_mode = QGLView::SingleSelection; +// sel_pen = QPen(Qt::black, 1, Qt::DashLine); +// sel_brush = QBrush(QColor(170, 100, 255, 120)); + camera()->setAim(QVector3D()); + camera()->setPos(QVector3D(2, 2, 2)); + camera()->setName("Camera"); + addObject(camera()); + emit cameraPosChanged(camera()->pos()); + //camera().aim_ = camera().pos_; + ktm_.restart(); +} + + +QGLView::~QGLView() { + stop(); + if (shader_select) delete shader_select; + if (shader_halo) delete shader_halo; + deleting_ = true; +} + + +void QGLView::stop() { + if (timer) killTimer(timer); + timer = 0; +} + + +void QGLView::start(float freq) { + stop(); + timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq)); +} + + +GLRendererBase * QGLView::renderer() { + return renderer_; +} + + +void QGLView::setRenderer(GLRendererBase * r, GLRendererBase ** prev) { + if (prev != nullptr) *prev = renderer_; + renderer_ = r; +} + + +void QGLView::addObject(GLObjectBase * o) { + objects_.addChild(o); + o->setView(this); + collectLights(); + QList cl = o->children(true); + cl << o; + foreach (GLObjectBase * i, cl) { + emit objectAdded(i); + } + if (is_init) { + o->init(); + } +} + + +int QGLView::objectsCount(bool all) { + if (!all) return objects_.childCount(); + int cnt = 0; + objectsCountInternal(&cnt, &objects_); + return cnt; +} + + +void QGLView::removeObject(GLObjectBase * o, bool inChildren) { + o->setView(nullptr); + if (inChildren) + removeObjectInternal(o, &objects_); + else + objects_.removeChild(o); + objectDeleted(o); +} + + +void QGLView::removeObject(GLObjectBase & o, bool inChildren) { + removeObject(&o, inChildren); +} + + +void QGLView::clearObjects(bool deleteAll) { + removeObject(camera_); + objects_.clearChildren(deleteAll); + addObject(camera()); + selectObject(nullptr); + hov_obj = nullptr; +} + + +QList QGLView::objects(bool all) { + return objects_.children(all); +} + + +int QGLView::lightsCount() const { + return lights_.size(); +} + + +void QGLView::removeLight(int index) { + removeObject(lights_.at(index)); + lights_.removeAt(index); +} + + +void QGLView::removeLight(Light * l) { + foreach (Light * i, lights_) + if (i == l) removeObject(i); + lights_.removeAll(l); +} + + +void QGLView::clearLights(bool deleteAll) { + if (deleteAll) + foreach (Light * i, lights_) delete i; + lights_.clear(); +} + + +void QGLView::addTexture(const QString & path) { + textures_manager->addTexture(path); +} + + +void QGLView::addAnimation(const QString & dir, const QString & name) { + textures_manager->addAnimation(dir, name); +} + + +Light * QGLView::light(int index) { + return lights_[index]; +} + + +Light * QGLView::light(const QString & name) { + foreach (Light * i, lights_) + if (i->name_ == name) return i; + return nullptr; +} + + +void QGLView::selectObject(GLObjectBase * o) { + if (o == sel_obj) return; + GLObjectBase * pso = sel_obj; + sel_obj = o; + emit selectionChanged(sel_obj, pso); +} + + +void QGLView::resizeEvent(QResizeEvent * e) { + renderLater(); +} + +void QGLView::timerEvent(QTimerEvent *) { + renderNow(); + if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return; + Qt::KeyboardModifiers km = QApplication::keyboardModifiers(); + foreach (int i, keys_) + emit keyEvent((Qt::Key)i, km); +} + + +void QGLView::render() { + if (!isVisible()) return; + resizeGL(width(), height()); + QRect g_rect(QPoint(), size()); + emit glBeforePaint(); + //qDebug() << "paintGL"; + //QMutexLocker ml_v(&v_mutex); + glEnable(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); + camera()->apply(aspect); + //objects_.preparePos(camera()); + start_rp.cam_offset_matrix = camera()->offsetMatrix(); + start_rp.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); + start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + //objects_.buildTransform(); + + /// Selection detect + //glClearFramebuffer(QColor(100, 0, 0, 0)); + if (mouseSelect_) { + glReleaseTextures(); + glEnableDepth(); + glDisable(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_CUBE_MAP); + glDisable(GL_MULTISAMPLE); + glDisable(GL_LIGHTING); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_RESCALE_NORMAL); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + fbo_selection.bind(); + fbo_selection.setWriteBuffer(0); + glClearFramebuffer(QColor(0, 0, 0, 0)); + if (shaders_supported && shader_select->isLinked()) shader_select->bind(); + renderSelection(); + if (shaders_supported && shader_select->isLinked()) shader_select->release(); + uchar cgid[4] = {0, 0, 0, 0}; + uint iid = 0; + GLObjectBase * so = nullptr; + if (!g_rect.contains(lastPos)) { + if (hov_obj != nullptr) { + hov_obj = nullptr; + emit hoverChanged(nullptr, hov_obj); + } + } else { + glReadPixels(lastPos.x(), height() - lastPos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, cgid); + iid = uint(cgid[0] << 24) | uint(cgid[1] << 16) | uint(cgid[2] << 8) | cgid[3]; + so = ids.value(iid, nullptr); + //qDebug() <name() << cgid[3]; + } + if (selectionHalo_ && sel_obj) { + fbo_selection.setWriteBuffer(2); + renderHalo(sel_obj, qHash((quint64)sel_obj), selectionHaloColor_, selectionHaloFill_); + } + if (hoverHalo_ && hov_obj) { + fbo_selection.setWriteBuffer(1); + renderHalo(hov_obj, iid, hoverHaloColor_, hoverHaloFill_); + } + fbo_selection.release(); + glEnableDepth(); + /*glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY);*/ + } + + camera()->apply(aspect); + start_rp.cam_offset_matrix = camera()->offsetMatrix(); + cur_mvpm = start_rp.proj_matrix * start_rp.view_matrix * start_rp.cam_offset_matrix; + //objects_.preparePos(camera()); + + static GLRendererBase * prev_rend = nullptr; + glShadeModel(GL_SMOOTH); + if (prev_rend != renderer_) { + prev_rend = renderer_; + if (renderer_ != nullptr) { + renderer_->init(width(), height()); + renderer_->resize(width(), height()); + renderer_->reloadShaders(); + } + } + emit glBeginPaint(); + if (renderer_ != nullptr) { + renderer_->rp.prepare(); + renderer_->prepareScene(); + renderer_->renderScene(); + } + emit glPainting(); + glUseProgram(0); + if (selectionHalo_ || hoverHalo_) { + glReleaseTextures(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + //glClearFramebuffer(Qt::black, false); + + glActiveTexture(GL_TEXTURE0); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_CUBE_MAP); + glDisable(GL_LIGHTING); + glDisableDepth(); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + if (selectionHalo_ && sel_obj) { + glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(2)); + //qDebug() << "draw sel"; + glDrawQuad(); + } + if (hoverHalo_ && hov_obj) { + glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(1)); + //qDebug() << "draw hover"; + //glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg")); + glDrawQuad(); + } + } + + glResetAllTransforms(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glUseProgram(0); + + //glDisable(GL_BLEND); + //glDisable(GL_LIGHTING); + //glActiveTexture(GL_TEXTURE0); + //glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg")); + //glDrawQuad(); + + emit glEndPaint(); + + /*releaseShaders(); + glActiveTextureChannel(0); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor4f(0.3, 0.5, 0.8, 0.5); + glResetAllTransforms(); + glBegin(GL_QUADS); + glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f); + glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.); + glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f); + glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f); + glEnd();*/ + /* + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glDisable(GL_LIGHTING); + glActiveTextureChannel(0); + glBindTexture(GL_TEXTURE_2D, fbo->texture()); + glDisable(GL_DEPTH_TEST); + glBegin(GL_QUADS); + glColor3f(1.f, 1.f, 1.f); + glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f); + glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f); + glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f); + glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.); + glEnd(); + glEnable(GL_DEPTH_TEST);*/ + fps_tm += time.elapsed(); + time.restart(); + fps_cnt++; + if (fps_tm < 1000.) return; + fps_ = fps_cnt / fps_tm * 1000.; + fps_tm = 0.; + fps_cnt = 0; +} + + +void QGLView::initialize() { + //initializeOpenGLFunctions(); + glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glEnableDepth(); + glEnable(GL_CULL_FACE); + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); + glActiveTexture(GL_TEXTURE0 + 3); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glActiveTexture(GL_TEXTURE0); + glShadeModel(GL_SMOOTH); + glCullFace(GL_BACK); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + + textures_manager->loadTextures(); + objects_.initInternal(); + checkCaps(); + + shader_select = new QOpenGLShaderProgram(context()); + shader_halo = new QOpenGLShaderProgram(context()); + reloadThisShaders(); + is_init = true; + //resizeGL(width(), height()); + need_init_ = false; + emit glInitializeDone(); +} + + +void QGLView::renderHalo(const GLObjectBase * obj, const uint iid, const QColor & color, const float & fill) { + if (!shaders_supported) return; + if (!shader_halo) return; + if (!shader_halo->isLinked()) return; + if (obj) { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture()); + shader_halo->bind(); + shader_halo->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); + shader_halo->setUniformValue("t0", 0); + shader_halo->setUniformValue("dt", QVector2D(1.f / width(), 1.f / height())); + shader_halo->setUniformValue("selected", QVector4D(float((iid >> 24) & 0xFF) / 255.f, + float((iid >> 16) & 0xFF) / 255.f, + float((iid >> 8) & 0xFF) / 255.f, + float( iid & 0xFF) / 255.f)); + shader_halo->setUniformValue("color", color); + shader_halo->setUniformValue("fill", GLfloat(fill)); + //qDebug() << "render halo" << iid << shader_halo->log() << shader_halo->programId(); + glDisableDepth(); + //glClearFramebuffer(color); + glDrawQuad(shader_halo); + glDepthMask(GL_TRUE); + //glFlush(); + shader_halo->release(); + } else { + glClearFramebuffer(Qt::black, false); + } +} + + +void QGLView::renderSelection() { +// cid = 1; + ids.clear(); + if (shaders_supported) { + if (shader_select) { + if (shader_select->isLinked()) { + sh_id_loc = shader_select->uniformLocation("id"); + shader_select->setUniformValue("z_far", GLfloat(depthEnd())); + shader_select->setUniformValue("z_near", GLfloat(depthStart())); + } + } + } + //qDebug() << sh_id_loc; + start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + glPushMatrix(); + renderSingleSelection(objects_); + glPopMatrix(); +} + + +void QGLView::renderSingleSelection(GLObjectBase & o) { + if (!o.isInit()) { + o.init(); + o.loadTextures(); + } + if (!o.visible_ || !o.select_) return; + QMatrix4x4 curview = start_rp.view_matrix * start_rp.cam_offset_matrix * o.itransform_; + uint id = qHash((quint64)&o); + ids.insert(id, &o); + glLineWidth(o.line_width > 0.f ? o.line_width : lineWidth_); + glPointSize(o.line_width > 0.f ? o.line_width : lineWidth_); + if (shaders_supported){ + if (shader_select) { + if (shader_select->isLinked()) { + setUniformMatrices(shader_select, start_rp.proj_matrix, curview); + shader_select->setUniformValue(sh_id_loc, QVector4D(float((id >> 24) & 0xFF) / 255.f, + float((id >> 16) & 0xFF) / 255.f, + float((id >> 8) & 0xFF) / 255.f, + float(id & 0xFF) / 255.f)); + } + } + } else { + setGLMatrix(curview); + glColor4f(float((id >> 24) & 0xFF) / 255.f, + float((id >> 16) & 0xFF) / 255.f, + float((id >> 8) & 0xFF) / 255.f, + float(id & 0xFF) / 255.f); + } + //qDebug() << o.name() << "assign to" << sh_id_loc << cid; + //glColor4f(float((cid >> 24) & 0xFF) / 255.f, float((cid >> 16) & 0xFF) / 255.f, float((cid >> 8) & 0xFF) / 255.f, float(cid & 0xFF) / 255.f); +// ++cid; + o.draw(nullptr, true); + foreach (GLObjectBase * i, o.children_) + renderSingleSelection(*i); +} + + +void QGLView::collectLights() { + lights_.clear(); + collectObjectLights(&objects_); +} + + +void QGLView::objectDeleted(GLObjectBase * o) { + if (deleting_) return; + //qDebug() << "del" << o; + if (sel_obj == o) selectObject(nullptr); + if (hov_obj == o) hov_obj = nullptr; + collectLights(); +} + + +void QGLView::collectObjectLights(GLObjectBase * o) { + if (o->type_ == GLObjectBase::glLight) { + lights_ << globject_cast(o); + o->view_ = this; + } + foreach (GLObjectBase * i, o->children()) + collectObjectLights(i); +} + + +void QGLView::objectsCountInternal(int * cnt, GLObjectBase * where) { + ++(*cnt); + foreach (GLObjectBase * i, where->children_) + objectsCountInternal(cnt, i); +} + + +void QGLView::removeObjectInternal(GLObjectBase * o, GLObjectBase * where) { + foreach (GLObjectBase * i, where->children_) { + if (o == i) + where->removeChild(i); + else + removeObjectInternal(o, i); + objectDeleted(i); + } +} + + +void QGLView::checkCaps() { + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic); + //glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_chanels); + //qDebug() << max_texture_chanels; + //qDebug() << max_texture_chanels; + shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms(); +} + + +void QGLView::reloadThisShaders() { + if (!shaders_supported) return; + loadShaders(shader_select, "selection", "://shaders"); + loadShaders(shader_halo, "selection_halo", "://shaders"); + //loadShaders(shader_rope, "rope", "://shaders"); +} + +void QGLView::glReleaseTextures(int channels) { + for (int i = channels - 1; i >= 0; --i) { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + } +} + + +void QGLView::applyFog() { + GLfloat fog_col[4] = {float(fogColor_.redF()), float(fogColor_.greenF()), float(fogColor_.blueF()), .0f}; + if (fogEnabled_) { + glEnable(GL_FOG); + glFogf(GL_FOG_DENSITY, fogDensity_); + glFogf(GL_FOG_START, fogStart_); + glFogf(GL_FOG_END, fogEnd_); + glFogi(GL_FOG_MODE, fogMode_); + fog_col[0] = fogColor_.redF(); + fog_col[1] = fogColor_.greenF(); + fog_col[2] = fogColor_.blueF(); + glFogfv(GL_FOG_COLOR, fog_col); + } else glDisable(GL_FOG); +} + + +void QGLView::resizeGL(int width, int height) { + if (!is_init) return; + if (width <= 0 || height <= 0) return; + if (prev_size == QSize(width, height)) return; + prev_size = QSize(width, height); + aspect = float(width) / float(height); + if (renderer_) renderer_->resize(width, height); + mouse_first = true; + //qDebug() << "resize" << width << height; + fbo_selection.resize(width, height); + iaspect = (aspect == 0.f) ? 0. : 1 / aspect; + glViewport(0, 0, width, height); + emit glResize(width, height); +} + + +void QGLView::mouseReleaseEvent(QMouseEvent * e) { +// qDebug() << "mouseReleaseEvent" << e << isActive(); +// QGraphicsView::mouseReleaseEvent(e); + //setCursor(QCursor(Qt::ArrowCursor)); + selecting_ = false; + if (mouseSelect_ && e->button() == Qt::LeftButton) { + if ((lastPos - downPos).manhattanLength() < 8) { + if (sel_obj != hov_obj) + selectObject(hov_obj); + } + } + emit glMouseReleaseEvent(e); +} + + +void QGLView::mousePressEvent(QMouseEvent * e) { +// qDebug() << "mousePressEvent" << e << isActive(); +// QGraphicsView::mousePressEvent(e); +// mouseThis_ = (scene()->itemAt(mapToScene(e->pos()) , QTransform() ) == 0); + selecting_ = false; + if (!QRect(QPoint(), size()).contains(e->pos())) return; + /// TODO select by rect + //if (e->button() == sel_button && e->modifiers() == sel_mod) + // selecting_ = true; + lastPos = e->pos(); + downPos = lastPos; + //qDebug() << mouseThis_; + emit glMousePressEvent(e); +} + + +void QGLView::mouseMoveEvent(QMouseEvent * e) { +// qDebug() << "mouseMoveEvent" << e << isActive(); +// QGraphicsView::mouseMoveEvent(e); + //lastPos = e->pos(); + if (selecting_) { + return; + } +// if (!QRect(QPoint(), size()).contains(e->pos())) return; + //if (scene()->itemAt(mapToScene(e->pos())) != 0) return; + ///qDebug() << e->x() << e->y(); + QRect g_rect(QPoint(), size()); + if (mouseRotate_) { + float dx = e->x() - lastPos.x(); + float dy = e->y() - lastPos.y(); + if (e->buttons() & Qt::LeftButton) { + //camera().angle_z += dx / 4.; + //camera().angle_xy += dy / 4.; + if (cameraOrbit_) { + camera()->orbitZ(dx / 4.f); + camera()->orbitXY(dy / 4.f); + } else { + camera()->rotateZ(dx / 4.f); + camera()->rotateXY(dy / 4.f); + } + emit cameraPosChanged(camera()->pos()); + } else if (e->buttons() & Qt::RightButton) { + float ad = camera()->distance(); + camera()->moveLeft(dx / 1000.f * ad); + camera()->moveUp(dy / 1000.f * ad); + //camera().pos.setX(camera().pos.x() + camera().pos.z() * dx / 500.); + //camera().pos.setY(camera().pos.y() - camera().pos.z() * dy / 500.); + emit cameraPosChanged(camera()->pos()); + } + //lights[0]->pos_ = camera().pos(); + } + if (customMouseMove_) emit customMouseMoveEvent(e->pos(), lastPos, e->buttons()); + lastPos = e->pos(); + if (grabMouse_) { + //if (!isrunning) return; + QCursor::setPos(mapToGlobal(QRect(QPoint(), size()).center())); + static bool mouse_sec = false; + if (mouse_sec) { + mouse_sec = false; + return; + } + if (mouse_first) { + mouse_first = false; + mouse_sec = true; + //qDebug() << "first" << e->pos(); + return; + } + lastPos = g_rect.center(); + int dx = e->x() - lastPos.x(); + int dy = e->y() - lastPos.y(); + emit glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers())); + return; + } + emit glMouseMoveEvent(e); +} + + +void QGLView::wheelEvent(QWheelEvent * e) { + if (mouseRotate_) { + if (e->delta() > 0) camera()->flyCloser(0.1f); //camera().pos.setZ(camera().pos.z() - 0.1 * camera().pos.z()); + if (e->delta() < 0) camera()->flyFarer(0.1f); //camera().pos.setZ(camera().pos.z() + 0.1 * camera().pos.z()); + emit cameraPosChanged(camera()->pos()); + } + emit glWheelEvent(e); +} + + +void QGLView::leaveEvent(QEvent * ) { + lastPos = QPoint(-1, -1); + //qDebug() << lastPos; +} + + +void QGLView::keyPressEvent(QKeyEvent * e) { + emit glKeyPressEvent(e); + if (e->key() > 0) keys_.insert(e->key()); + if (e->key() == Qt::Key_F11) { + emit doubleClick(); + } +} + + +void QGLView::keyReleaseEvent(QKeyEvent * e) { + emit glKeyReleaseEvent(e); + keys_.remove(e->key()); +} + + +void QGLView::focusOutEvent(QFocusEvent *) { + keys_.clear(); +} + + +void QGLView::mouseDoubleClickEvent(QMouseEvent * e) { + if (e->buttons().testFlag(Qt::MidButton)) + emit doubleClick(); +} + + +QByteArray QGLView::saveCamera() { + ChunkStream cs; + const Camera * c = camera(); + cs.add(1, c->posX()); + cs.add(2, c->posY()); + cs.add(3, c->posZ()); + cs.add(4, c->aim().x()); + cs.add(5, c->aim().y()); + cs.add(6, c->aim().z()); + cs.add(7, c->angleZ()); + cs.add(8, c->angleXY()); + cs.add(9, c->angleRoll()); + cs.add(10, c->FOV()); + return cs.data(); +} + + +void QGLView::restoreCamera(const QByteArray &ba) { + if (ba.isEmpty()) return; + ChunkStream cs(ba); + QVector3D pos, aim, ang; + while (!cs.atEnd()) { + switch (cs.read()) { + case 1: pos.setX(cs.getData()); break; + case 2: pos.setY(cs.getData()); break; + case 3: pos.setZ(cs.getData()); break; + case 4: aim.setX(cs.getData()); break; + case 5: aim.setY(cs.getData()); break; + case 6: aim.setZ(cs.getData()); break; + case 7: ang.setZ(cs.getData()); break; + case 8: ang.setY(cs.getData()); break; + case 9: ang.setX(cs.getData()); break; + case 10: setFOV(cs.getData()); break; + default: break; + } + } + camera()->setPos(pos); + camera()->setAim(aim); + camera()->setAngles(ang); +} + + +QByteArray QGLView::saveFeatures() { + QByteArray ba; + QDataStream ds(&ba, QIODevice::WriteOnly); + ds << features_; + return ba; +} + + +void QGLView::restoreFeatures(const QByteArray & ba) { + QHash f; + QDataStream ds(ba); + ds >> f; + features_ = f; +} + diff --git a/qglview/qglview.h b/libs/qglview/qglview.h similarity index 97% rename from qglview/qglview.h rename to libs/qglview/qglview.h index c9ac9fb..dcb1d0e 100644 --- a/qglview/qglview.h +++ b/libs/qglview/qglview.h @@ -1,301 +1,301 @@ -/* - QGLView - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef QGLVIEW_H -#define QGLVIEW_H - -#include "openglwindow.h" -#include "glframebuffer.h" -#include "glprimitives.h" -#include "glparticles_system.h" -#include "glrendererbase.h" -#include - - -class QGLView: public OpenGLWindow, public QGLViewBase -{ - friend class GLRendererBase; - friend class GLObjectBase; - Q_OBJECT - Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) - Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth) - Q_PROPERTY (float FOV READ FOV WRITE setFOV) - Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart) - Q_PROPERTY (float depthEnd READ depthEnd WRITE setDepthEnd) - Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) - Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor) - Q_PROPERTY (float fogDensity READ fogDensity WRITE setFogDensity) - Q_PROPERTY (float fogStart READ fogStart WRITE setFogStart) - Q_PROPERTY (float fogEnd READ fogEnd WRITE setFogEnd) - Q_PROPERTY (FogMode fogMode READ fogMode WRITE setFogMode) - Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled) - Q_PROPERTY (int renderMode READ renderMode WRITE setRenderMode) - Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) - Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) - Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) - Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) - Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) - Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) - Q_PROPERTY (float hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) - Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) - Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) - Q_PROPERTY (float selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) - Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton) - Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier) - Q_PROPERTY (SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - -public: - QGLView(); - virtual ~QGLView(); - - enum FogMode {Linear = GL_LINEAR, Exp = GL_EXP, Exp2 = GL_EXP2}; - enum SelectionMode {NoSelection, SingleSelection, MultiSelection}; - enum Feature { - qglMSAA, - qglFXAA, - qglLinearFiltering, - qglAnisotropicLevel, - qglHDR, - qglEyeAccomodationEnabled, - qglEyeAccomodationTime, - qglEyeAccomodationMaxSpeed, - qglBloomEnabled, - qglBloomThreshold, - qglBloomFactor, - qglBloomRadius, - qglMotionBlurEnabled, - qglMotionBlurFactor, - qglMotionBlurSteps, - qglShadowsEnabled, - qglShadowsMapSize, - qglShadowsSoftEnabled, - qglReflectionsEnabled, - qglReflectionsBlur, - qglSSAOEnabled, - qglSSAORadius, - qglDepthOfFieldEnabled, - qglDepthOfFieldAutoFocusEnabled, - qglDepthOfFieldAutoFocusSpeed, - qglDepthOfFieldFocus, - qglDepthOfFieldDiaphragm - }; - - Q_ENUMS (FogMode) - Q_ENUMS (SelectionMode) - - void stop(); - void start(float freq = 60.); - - GLRendererBase * renderer(); - void setRenderer(GLRendererBase * r, GLRendererBase ** prev = nullptr); - - QColor backColor() const {return backColor_;} - float lineWidth() const {return lineWidth_;} - float FOV() const {return camera()->fov_;} - float depthStart() const {return camera()->depth_start;} - float depthEnd() const {return camera()->depth_end;} - float currentFPS() const {return fps_;} - int maxAnisotropicLevel() const {return max_anisotropic;} - - QColor ambientColor() const {return ambientColor_;} - QColor fogColor() const {return fogColor_;} - float fogDensity() const {return fogDensity_;} - float fogStart() const {return fogStart_;} - float fogEnd() const {return fogEnd_;} - FogMode fogMode() const {return fogMode_;} - bool isFogEnabled() const {return fogEnabled_;} - bool isLightEnabled() const {return lightEnabled_;} - bool isGrabMouseEnabled() const {return grabMouse_;} - bool isMouseRotateEnabled() const {return mouseRotate_;} - bool isMouseSelectionEnabled() const {return mouseSelect_;} - bool isCameraOrbit() const {return cameraOrbit_;} - bool isHoverHaloEnabled() const {return hoverHalo_;} - QColor hoverHaloColor() const {return hoverHaloColor_;} - float hoverHaloFillAlpha() const {return hoverHaloFill_;} - bool isSelectionHaloEnabled() const {return selectionHalo_;} - QColor selectionHaloColor() const {return selectionHaloColor_;} - float selectionHaloFillAlpha() const {return selectionHaloFill_;} - - QVariant feature(Feature f) const {return features_.value(int(f));} - QVariant setFeature(Feature f, const QVariant & value) {QVariant ret = features_.value(int(f)); features_[int(f)] = value; return ret;} - bool isFeatureEnabled(Feature f) const {return features_[int(f)].toBool();} - - int renderMode() const {return (int)rmode;} - void setRenderMode(int mode) {rmode = (GLObjectBase::RenderMode)mode;} - - void addObject(GLObjectBase * o); -// void addObject(GLObjectBase & o) {addObject(&o);} - int objectsCount(bool all = false); - void removeObject(GLObjectBase * o, bool inChildren = true); - void removeObject(GLObjectBase & o, bool inChildren = true); - void clearObjects(bool deleteAll = false); - QList objects(bool all = false); - - int lightsCount() const; - void removeLight(int index); - void removeLight(Light * l); - void clearLights(bool deleteAll = false); - QList lights() {return lights_;} - - void addTexture(const QString & path); - void addAnimation(const QString & dir, const QString & name); - - const GLObjectBase & rootObject() {return objects_;} - GLObjectBase * object(int index) {return objects_.child(index);} - GLObjectBase * object(const QString & name) {return objects_.child(name);} - Light * light(int index); - Light * light(const QString & name); - - SelectionMode selectionMode() const {return sel_mode;} - Qt::MouseButton selectionButton() const {return sel_button;} - Qt::KeyboardModifier selectionModifier() const {return sel_mod;} - - void setSelectionMode(SelectionMode v) {sel_mode = v;} - void setSelectionButton(Qt::MouseButton v) {sel_button = v;} - void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;} - void selectObject(GLObjectBase * o); - GLObjectBase * selectedObject() const {return sel_obj;} - - void glReleaseTextures(int channels = 8); - QByteArray saveCamera(); - void restoreCamera(const QByteArray & ba); - QByteArray saveFeatures(); - void restoreFeatures(const QByteArray & ba); - - - GLfloat aspect, iaspect; - QMatrix4x4 cur_mvpm; - -protected: - void render(); - void resizeEvent(QResizeEvent * e); - - void timerEvent(QTimerEvent * ); - void initialize(); - void resizeGL(int width, int height); - void mousePressEvent(QMouseEvent * e); - void mouseMoveEvent(QMouseEvent * e); - void mouseReleaseEvent(QMouseEvent * e); - void wheelEvent(QWheelEvent * e); - void leaveEvent(QEvent * ); - void mouseDoubleClickEvent(QMouseEvent * e); - - void keyPressEvent(QKeyEvent * e); - void keyReleaseEvent(QKeyEvent * e); - void focusOutEvent(QFocusEvent *); - - void applyFog(); - void renderSelection(); - - void checkCaps(); - void collectLights(); - -private: - void objectDeleted(GLObjectBase * o); - void collectObjectLights(GLObjectBase * o); - void objectsCountInternal(int * cnt, GLObjectBase * where); - void removeObjectInternal(GLObjectBase * o, GLObjectBase * where); - void renderSingleSelection(GLObjectBase & o); - //void renderSingleShadow(GLObjectBase & o); - void renderHalo(const GLObjectBase * obj, const uint iid, const QColor & color, const float & fill); - void reloadThisShaders(); - void processKeys(); - bool setupViewport(); - - QPoint lastPos, downPos; - GLObjectBase objects_; - QList lights_; -// uint cid; - QHash ids; - QSet keys_; - FogMode fogMode_; - QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_; - QTime time, ktm_; - GLint max_anisotropic, max_texture_chanels; - GLObjectBase::RenderMode rmode; - GLObjectBase * sel_obj, * hov_obj; - GLFramebuffer fbo_selection; - QOpenGLShaderProgram * shader_select, * shader_halo; - GLRendererBase * renderer_; - SelectionMode sel_mode; - Qt::MouseButton sel_button; - Qt::KeyboardModifier sel_mod; - GLRendererBase::RenderingParameters start_rp; - QHash features_; - QSize prev_size; - float lineWidth_; - float fogDensity_, fogStart_, fogEnd_, fps_, fps_tm, hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor; - int timer, fps_cnt, sh_id_loc, deleting_; - bool is_first_draw, is_init, fogEnabled_, lightEnabled_, grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_; - bool shaders_supported, changed_, cameraOrbit_, need_init_; - bool hoverHalo_, selectionHalo_, shaders_bind, selecting_; - -public slots: - void setBackColor(const QColor & arg) {backColor_ = arg;} - void setLineWidth(const float & arg) {lineWidth_ = arg;} - void setFOV(const float & arg) {camera()->fov_ = arg;} - void setDepthStart(const float & arg) {camera()->depth_start = arg;} - void setDepthEnd(const float & arg) {camera()->depth_end = arg;} - void setAmbientColor(const QColor & arg) {ambientColor_ = arg;} - void setFogColor(const QColor & arg) {fogColor_ = arg;} - void setFogDensity(const float & arg) {fogDensity_ = arg;} - void setFogStart(const float & arg) {fogStart_ = arg;} - void setFogEnd(const float & arg) {fogEnd_ = arg;} - void setFogMode(const FogMode & arg) {fogMode_ = arg;} - void setFogEnabled(const bool & arg) {fogEnabled_ = arg;} - void setLightEnabled(const bool & arg) {lightEnabled_ = arg;} - void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;} - void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;} - void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;} - void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;} - void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;} - void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;} - void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;} - void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;} - void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;} - void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;} - void setSelectionHaloFillAlpha(const float & arg) {selectionHaloFill_ = arg;} - - void reloadShaders() {if (renderer_ != nullptr) renderer_->reloadShaders(); reloadThisShaders();} - void deselect() {sel_obj = nullptr;} - -signals: - void glBeforePaint(); - void glBeginPaint(); - void glPainting(); - void glEndPaint(); - void glKeyPressEvent(QKeyEvent * e); - void glKeyReleaseEvent(QKeyEvent * e); - void glMousePressEvent(QMouseEvent * e); - void glMouseMoveEvent(QMouseEvent * e); - void glMouseReleaseEvent(QMouseEvent * e); - void glWheelEvent(QWheelEvent * e); - void glResize(int, int); - void glInitializeDone(); - void cameraPosChanged(QVector3D pos); - void keyEvent(Qt::Key key, Qt::KeyboardModifiers mod); - void customMouseMoveEvent(QPoint curpos, QPoint lastpos, Qt::MouseButtons buttons); - - void hoverChanged(GLObjectBase * cur, GLObjectBase * prev); - void selectionChanged(GLObjectBase * cur, GLObjectBase * prev); - void objectAdded(GLObjectBase * ); - void doubleClick(); - -}; - -#endif // QGLVIEW_H +/* + QGLView + Ivan Pelipenko peri4ko@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#ifndef QGLVIEW_H +#define QGLVIEW_H + +#include "openglwindow.h" +#include "glframebuffer.h" +#include "glprimitives.h" +#include "glparticles_system.h" +#include "glrendererbase.h" +#include + + +class QGLView: public OpenGLWindow, public QGLViewBase +{ + friend class GLRendererBase; + friend class GLObjectBase; + Q_OBJECT + Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) + Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth) + Q_PROPERTY (float FOV READ FOV WRITE setFOV) + Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart) + Q_PROPERTY (float depthEnd READ depthEnd WRITE setDepthEnd) + Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) + Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor) + Q_PROPERTY (float fogDensity READ fogDensity WRITE setFogDensity) + Q_PROPERTY (float fogStart READ fogStart WRITE setFogStart) + Q_PROPERTY (float fogEnd READ fogEnd WRITE setFogEnd) + Q_PROPERTY (FogMode fogMode READ fogMode WRITE setFogMode) + Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled) + Q_PROPERTY (int renderMode READ renderMode WRITE setRenderMode) + Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) + Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) + Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) + Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) + Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) + Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) + Q_PROPERTY (float hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) + Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) + Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) + Q_PROPERTY (float selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) + Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton) + Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier) + Q_PROPERTY (SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + +public: + QGLView(); + virtual ~QGLView(); + + enum FogMode {Linear = GL_LINEAR, Exp = GL_EXP, Exp2 = GL_EXP2}; + enum SelectionMode {NoSelection, SingleSelection, MultiSelection}; + enum Feature { + qglMSAA, + qglFXAA, + qglLinearFiltering, + qglAnisotropicLevel, + qglHDR, + qglEyeAccomodationEnabled, + qglEyeAccomodationTime, + qglEyeAccomodationMaxSpeed, + qglBloomEnabled, + qglBloomThreshold, + qglBloomFactor, + qglBloomRadius, + qglMotionBlurEnabled, + qglMotionBlurFactor, + qglMotionBlurSteps, + qglShadowsEnabled, + qglShadowsMapSize, + qglShadowsSoftEnabled, + qglReflectionsEnabled, + qglReflectionsBlur, + qglSSAOEnabled, + qglSSAORadius, + qglDepthOfFieldEnabled, + qglDepthOfFieldAutoFocusEnabled, + qglDepthOfFieldAutoFocusSpeed, + qglDepthOfFieldFocus, + qglDepthOfFieldDiaphragm + }; + + Q_ENUMS (FogMode) + Q_ENUMS (SelectionMode) + + void stop(); + void start(float freq = 60.); + + GLRendererBase * renderer(); + void setRenderer(GLRendererBase * r, GLRendererBase ** prev = nullptr); + + QColor backColor() const {return backColor_;} + float lineWidth() const {return lineWidth_;} + float FOV() const {return camera()->fov_;} + float depthStart() const {return camera()->depth_start;} + float depthEnd() const {return camera()->depth_end;} + float currentFPS() const {return fps_;} + int maxAnisotropicLevel() const {return max_anisotropic;} + + QColor ambientColor() const {return ambientColor_;} + QColor fogColor() const {return fogColor_;} + float fogDensity() const {return fogDensity_;} + float fogStart() const {return fogStart_;} + float fogEnd() const {return fogEnd_;} + FogMode fogMode() const {return fogMode_;} + bool isFogEnabled() const {return fogEnabled_;} + bool isLightEnabled() const {return lightEnabled_;} + bool isGrabMouseEnabled() const {return grabMouse_;} + bool isMouseRotateEnabled() const {return mouseRotate_;} + bool isMouseSelectionEnabled() const {return mouseSelect_;} + bool isCameraOrbit() const {return cameraOrbit_;} + bool isHoverHaloEnabled() const {return hoverHalo_;} + QColor hoverHaloColor() const {return hoverHaloColor_;} + float hoverHaloFillAlpha() const {return hoverHaloFill_;} + bool isSelectionHaloEnabled() const {return selectionHalo_;} + QColor selectionHaloColor() const {return selectionHaloColor_;} + float selectionHaloFillAlpha() const {return selectionHaloFill_;} + + QVariant feature(Feature f) const {return features_.value(int(f));} + QVariant setFeature(Feature f, const QVariant & value) {QVariant ret = features_.value(int(f)); features_[int(f)] = value; return ret;} + bool isFeatureEnabled(Feature f) const {return features_[int(f)].toBool();} + + int renderMode() const {return (int)rmode;} + void setRenderMode(int mode) {rmode = (GLObjectBase::RenderMode)mode;} + + void addObject(GLObjectBase * o); +// void addObject(GLObjectBase & o) {addObject(&o);} + int objectsCount(bool all = false); + void removeObject(GLObjectBase * o, bool inChildren = true); + void removeObject(GLObjectBase & o, bool inChildren = true); + void clearObjects(bool deleteAll = false); + QList objects(bool all = false); + + int lightsCount() const; + void removeLight(int index); + void removeLight(Light * l); + void clearLights(bool deleteAll = false); + QList lights() {return lights_;} + + void addTexture(const QString & path); + void addAnimation(const QString & dir, const QString & name); + + const GLObjectBase & rootObject() {return objects_;} + GLObjectBase * object(int index) {return objects_.child(index);} + GLObjectBase * object(const QString & name) {return objects_.child(name);} + Light * light(int index); + Light * light(const QString & name); + + SelectionMode selectionMode() const {return sel_mode;} + Qt::MouseButton selectionButton() const {return sel_button;} + Qt::KeyboardModifier selectionModifier() const {return sel_mod;} + + void setSelectionMode(SelectionMode v) {sel_mode = v;} + void setSelectionButton(Qt::MouseButton v) {sel_button = v;} + void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;} + void selectObject(GLObjectBase * o); + GLObjectBase * selectedObject() const {return sel_obj;} + + void glReleaseTextures(int channels = 8); + QByteArray saveCamera(); + void restoreCamera(const QByteArray & ba); + QByteArray saveFeatures(); + void restoreFeatures(const QByteArray & ba); + + + GLfloat aspect, iaspect; + QMatrix4x4 cur_mvpm; + +protected: + void render(); + void resizeEvent(QResizeEvent * e); + + void timerEvent(QTimerEvent * ); + void initialize(); + void resizeGL(int width, int height); + void mousePressEvent(QMouseEvent * e); + void mouseMoveEvent(QMouseEvent * e); + void mouseReleaseEvent(QMouseEvent * e); + void wheelEvent(QWheelEvent * e); + void leaveEvent(QEvent * ); + void mouseDoubleClickEvent(QMouseEvent * e); + + void keyPressEvent(QKeyEvent * e); + void keyReleaseEvent(QKeyEvent * e); + void focusOutEvent(QFocusEvent *); + + void applyFog(); + void renderSelection(); + + void checkCaps(); + void collectLights(); + +private: + void objectDeleted(GLObjectBase * o); + void collectObjectLights(GLObjectBase * o); + void objectsCountInternal(int * cnt, GLObjectBase * where); + void removeObjectInternal(GLObjectBase * o, GLObjectBase * where); + void renderSingleSelection(GLObjectBase & o); + //void renderSingleShadow(GLObjectBase & o); + void renderHalo(const GLObjectBase * obj, const uint iid, const QColor & color, const float & fill); + void reloadThisShaders(); + void processKeys(); + bool setupViewport(); + + QPoint lastPos, downPos; + GLObjectBase objects_; + QList lights_; +// uint cid; + QHash ids; + QSet keys_; + FogMode fogMode_; + QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_; + QTime time, ktm_; + GLint max_anisotropic, max_texture_chanels; + GLObjectBase::RenderMode rmode; + GLObjectBase * sel_obj, * hov_obj; + GLFramebuffer fbo_selection; + QOpenGLShaderProgram * shader_select, * shader_halo; + GLRendererBase * renderer_; + SelectionMode sel_mode; + Qt::MouseButton sel_button; + Qt::KeyboardModifier sel_mod; + GLRendererBase::RenderingParameters start_rp; + QHash features_; + QSize prev_size; + float lineWidth_; + float fogDensity_, fogStart_, fogEnd_, fps_, fps_tm, hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor; + int timer, fps_cnt, sh_id_loc, deleting_; + bool is_first_draw, is_init, fogEnabled_, lightEnabled_, grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_; + bool shaders_supported, changed_, cameraOrbit_, need_init_; + bool hoverHalo_, selectionHalo_, shaders_bind, selecting_; + +public slots: + void setBackColor(const QColor & arg) {backColor_ = arg;} + void setLineWidth(const float & arg) {lineWidth_ = arg;} + void setFOV(const float & arg) {camera()->fov_ = arg;} + void setDepthStart(const float & arg) {camera()->depth_start = arg;} + void setDepthEnd(const float & arg) {camera()->depth_end = arg;} + void setAmbientColor(const QColor & arg) {ambientColor_ = arg;} + void setFogColor(const QColor & arg) {fogColor_ = arg;} + void setFogDensity(const float & arg) {fogDensity_ = arg;} + void setFogStart(const float & arg) {fogStart_ = arg;} + void setFogEnd(const float & arg) {fogEnd_ = arg;} + void setFogMode(const FogMode & arg) {fogMode_ = arg;} + void setFogEnabled(const bool & arg) {fogEnabled_ = arg;} + void setLightEnabled(const bool & arg) {lightEnabled_ = arg;} + void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;} + void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;} + void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;} + void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;} + void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;} + void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;} + void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;} + void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;} + void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;} + void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;} + void setSelectionHaloFillAlpha(const float & arg) {selectionHaloFill_ = arg;} + + void reloadShaders() {if (renderer_ != nullptr) renderer_->reloadShaders(); reloadThisShaders();} + void deselect() {sel_obj = nullptr;} + +signals: + void glBeforePaint(); + void glBeginPaint(); + void glPainting(); + void glEndPaint(); + void glKeyPressEvent(QKeyEvent * e); + void glKeyReleaseEvent(QKeyEvent * e); + void glMousePressEvent(QMouseEvent * e); + void glMouseMoveEvent(QMouseEvent * e); + void glMouseReleaseEvent(QMouseEvent * e); + void glWheelEvent(QWheelEvent * e); + void glResize(int, int); + void glInitializeDone(); + void cameraPosChanged(QVector3D pos); + void keyEvent(Qt::Key key, Qt::KeyboardModifiers mod); + void customMouseMoveEvent(QPoint curpos, QPoint lastpos, Qt::MouseButtons buttons); + + void hoverChanged(GLObjectBase * cur, GLObjectBase * prev); + void selectionChanged(GLObjectBase * cur, GLObjectBase * prev); + void objectAdded(GLObjectBase * ); + void doubleClick(); + +}; + +#endif // QGLVIEW_H diff --git a/qglview/qglview.qrc b/libs/qglview/qglview.qrc similarity index 100% rename from qglview/qglview.qrc rename to libs/qglview/qglview.qrc diff --git a/qglview/qglview_test/main.cpp b/libs/qglview/qglview_test/main.cpp similarity index 100% rename from qglview/qglview_test/main.cpp rename to libs/qglview/qglview_test/main.cpp diff --git a/qglview/qglview_test/qglview_window.cpp b/libs/qglview/qglview_test/qglview_window.cpp similarity index 100% rename from qglview/qglview_test/qglview_window.cpp rename to libs/qglview/qglview_test/qglview_window.cpp diff --git a/qglview/qglview_test/qglview_window.h b/libs/qglview/qglview_test/qglview_window.h similarity index 100% rename from qglview/qglview_test/qglview_window.h rename to libs/qglview/qglview_test/qglview_window.h diff --git a/qglview/qglview_test/qglview_window.ui b/libs/qglview/qglview_test/qglview_window.ui similarity index 100% rename from qglview/qglview_test/qglview_window.ui rename to libs/qglview/qglview_test/qglview_window.ui diff --git a/qglview/renderer_deferred_shading.cpp b/libs/qglview/renderer_deferred_shading.cpp similarity index 100% rename from qglview/renderer_deferred_shading.cpp rename to libs/qglview/renderer_deferred_shading.cpp diff --git a/qglview/renderer_deferred_shading.h b/libs/qglview/renderer_deferred_shading.h similarity index 100% rename from qglview/renderer_deferred_shading.h rename to libs/qglview/renderer_deferred_shading.h diff --git a/qglview/renderer_simple.cpp b/libs/qglview/renderer_simple.cpp similarity index 100% rename from qglview/renderer_simple.cpp rename to libs/qglview/renderer_simple.cpp diff --git a/qglview/renderer_simple.h b/libs/qglview/renderer_simple.h similarity index 100% rename from qglview/renderer_simple.h rename to libs/qglview/renderer_simple.h diff --git a/qglview/shaders/FXAA.frag b/libs/qglview/shaders/FXAA.frag similarity index 100% rename from qglview/shaders/FXAA.frag rename to libs/qglview/shaders/FXAA.frag diff --git a/qglview/shaders/FXAA.vert b/libs/qglview/shaders/FXAA.vert similarity index 100% rename from qglview/shaders/FXAA.vert rename to libs/qglview/shaders/FXAA.vert diff --git a/qglview/shaders/bloom_0.frag b/libs/qglview/shaders/bloom_0.frag similarity index 100% rename from qglview/shaders/bloom_0.frag rename to libs/qglview/shaders/bloom_0.frag diff --git a/qglview/shaders/bloom_1.frag b/libs/qglview/shaders/bloom_1.frag similarity index 100% rename from qglview/shaders/bloom_1.frag rename to libs/qglview/shaders/bloom_1.frag diff --git a/qglview/shaders/bloom_pass_0.frag b/libs/qglview/shaders/bloom_pass_0.frag similarity index 100% rename from qglview/shaders/bloom_pass_0.frag rename to libs/qglview/shaders/bloom_pass_0.frag diff --git a/qglview/shaders/bloom_pass_0.vert b/libs/qglview/shaders/bloom_pass_0.vert similarity index 100% rename from qglview/shaders/bloom_pass_0.vert rename to libs/qglview/shaders/bloom_pass_0.vert diff --git a/qglview/shaders/bloom_pass_1.frag b/libs/qglview/shaders/bloom_pass_1.frag similarity index 100% rename from qglview/shaders/bloom_pass_1.frag rename to libs/qglview/shaders/bloom_pass_1.frag diff --git a/qglview/shaders/bloom_pass_1.vert b/libs/qglview/shaders/bloom_pass_1.vert similarity index 100% rename from qglview/shaders/bloom_pass_1.vert rename to libs/qglview/shaders/bloom_pass_1.vert diff --git a/qglview/shaders/dof.frag b/libs/qglview/shaders/dof.frag similarity index 100% rename from qglview/shaders/dof.frag rename to libs/qglview/shaders/dof.frag diff --git a/qglview/shaders/dof.vert b/libs/qglview/shaders/dof.vert similarity index 100% rename from qglview/shaders/dof.vert rename to libs/qglview/shaders/dof.vert diff --git a/qglview/shaders/downscale.frag b/libs/qglview/shaders/downscale.frag similarity index 100% rename from qglview/shaders/downscale.frag rename to libs/qglview/shaders/downscale.frag diff --git a/qglview/shaders/downscale.vert b/libs/qglview/shaders/downscale.vert similarity index 100% rename from qglview/shaders/downscale.vert rename to libs/qglview/shaders/downscale.vert diff --git a/qglview/shaders/dsl_pass_0.frag b/libs/qglview/shaders/dsl_pass_0.frag similarity index 100% rename from qglview/shaders/dsl_pass_0.frag rename to libs/qglview/shaders/dsl_pass_0.frag diff --git a/qglview/shaders/dsl_pass_0.vert b/libs/qglview/shaders/dsl_pass_0.vert similarity index 100% rename from qglview/shaders/dsl_pass_0.vert rename to libs/qglview/shaders/dsl_pass_0.vert diff --git a/qglview/shaders/dsl_pass_1.frag b/libs/qglview/shaders/dsl_pass_1.frag similarity index 100% rename from qglview/shaders/dsl_pass_1.frag rename to libs/qglview/shaders/dsl_pass_1.frag diff --git a/qglview/shaders/dsl_pass_1.vert b/libs/qglview/shaders/dsl_pass_1.vert similarity index 100% rename from qglview/shaders/dsl_pass_1.vert rename to libs/qglview/shaders/dsl_pass_1.vert diff --git a/qglview/shaders/dsl_pass_2.frag b/libs/qglview/shaders/dsl_pass_2.frag similarity index 100% rename from qglview/shaders/dsl_pass_2.frag rename to libs/qglview/shaders/dsl_pass_2.frag diff --git a/qglview/shaders/dsl_pass_2.vert b/libs/qglview/shaders/dsl_pass_2.vert similarity index 100% rename from qglview/shaders/dsl_pass_2.vert rename to libs/qglview/shaders/dsl_pass_2.vert diff --git a/qglview/shaders/fbo_add.frag b/libs/qglview/shaders/fbo_add.frag similarity index 100% rename from qglview/shaders/fbo_add.frag rename to libs/qglview/shaders/fbo_add.frag diff --git a/qglview/shaders/fbo_add.vert b/libs/qglview/shaders/fbo_add.vert similarity index 100% rename from qglview/shaders/fbo_add.vert rename to libs/qglview/shaders/fbo_add.vert diff --git a/qglengine/shaders/fxaa_v3.h b/libs/qglview/shaders/fxaa_v3.h similarity index 100% rename from qglengine/shaders/fxaa_v3.h rename to libs/qglview/shaders/fxaa_v3.h diff --git a/qglview/shaders/hdr.frag b/libs/qglview/shaders/hdr.frag similarity index 100% rename from qglview/shaders/hdr.frag rename to libs/qglview/shaders/hdr.frag diff --git a/qglview/shaders/hdr.vert b/libs/qglview/shaders/hdr.vert similarity index 100% rename from qglview/shaders/hdr.vert rename to libs/qglview/shaders/hdr.vert diff --git a/qglview/shaders/hdr_scale_0.frag b/libs/qglview/shaders/hdr_scale_0.frag similarity index 100% rename from qglview/shaders/hdr_scale_0.frag rename to libs/qglview/shaders/hdr_scale_0.frag diff --git a/qglview/shaders/hdr_scale_1.frag b/libs/qglview/shaders/hdr_scale_1.frag similarity index 100% rename from qglview/shaders/hdr_scale_1.frag rename to libs/qglview/shaders/hdr_scale_1.frag diff --git a/qglview/shaders/light_models.frag b/libs/qglview/shaders/light_models.frag similarity index 100% rename from qglview/shaders/light_models.frag rename to libs/qglview/shaders/light_models.frag diff --git a/qglview/shaders/motion_blur.frag b/libs/qglview/shaders/motion_blur.frag similarity index 100% rename from qglview/shaders/motion_blur.frag rename to libs/qglview/shaders/motion_blur.frag diff --git a/qglview/shaders/motion_blur.vert b/libs/qglview/shaders/motion_blur.vert similarity index 100% rename from qglview/shaders/motion_blur.vert rename to libs/qglview/shaders/motion_blur.vert diff --git a/qglview/shaders/post.frag b/libs/qglview/shaders/post.frag similarity index 100% rename from qglview/shaders/post.frag rename to libs/qglview/shaders/post.frag diff --git a/qglview/shaders/ppl.frag b/libs/qglview/shaders/ppl.frag similarity index 100% rename from qglview/shaders/ppl.frag rename to libs/qglview/shaders/ppl.frag diff --git a/qglview/shaders/ppl.vert b/libs/qglview/shaders/ppl.vert similarity index 100% rename from qglview/shaders/ppl.vert rename to libs/qglview/shaders/ppl.vert diff --git a/qglview/shaders/selection.frag b/libs/qglview/shaders/selection.frag similarity index 100% rename from qglview/shaders/selection.frag rename to libs/qglview/shaders/selection.frag diff --git a/qglview/shaders/selection.vert b/libs/qglview/shaders/selection.vert similarity index 100% rename from qglview/shaders/selection.vert rename to libs/qglview/shaders/selection.vert diff --git a/qglview/shaders/selection_halo.frag b/libs/qglview/shaders/selection_halo.frag similarity index 100% rename from qglview/shaders/selection_halo.frag rename to libs/qglview/shaders/selection_halo.frag diff --git a/qglview/shaders/selection_halo.vert b/libs/qglview/shaders/selection_halo.vert similarity index 100% rename from qglview/shaders/selection_halo.vert rename to libs/qglview/shaders/selection_halo.vert diff --git a/qglview/shaders/shadow.frag b/libs/qglview/shaders/shadow.frag similarity index 100% rename from qglview/shaders/shadow.frag rename to libs/qglview/shaders/shadow.frag diff --git a/qglview/shaders/shadow.vert b/libs/qglview/shaders/shadow.vert similarity index 100% rename from qglview/shaders/shadow.vert rename to libs/qglview/shaders/shadow.vert diff --git a/qglview/shaders/ssao_blur.frag b/libs/qglview/shaders/ssao_blur.frag similarity index 100% rename from qglview/shaders/ssao_blur.frag rename to libs/qglview/shaders/ssao_blur.frag diff --git a/qglview/shaders/ssao_blur.vert b/libs/qglview/shaders/ssao_blur.vert similarity index 100% rename from qglview/shaders/ssao_blur.vert rename to libs/qglview/shaders/ssao_blur.vert diff --git a/qglview/shaders/ssao_merge.frag b/libs/qglview/shaders/ssao_merge.frag similarity index 100% rename from qglview/shaders/ssao_merge.frag rename to libs/qglview/shaders/ssao_merge.frag diff --git a/qglview/shaders/ssao_merge.vert b/libs/qglview/shaders/ssao_merge.vert similarity index 100% rename from qglview/shaders/ssao_merge.vert rename to libs/qglview/shaders/ssao_merge.vert diff --git a/qglview/shaders/ssr.frag b/libs/qglview/shaders/ssr.frag similarity index 100% rename from qglview/shaders/ssr.frag rename to libs/qglview/shaders/ssr.frag diff --git a/qglview/shaders/ssr.vert b/libs/qglview/shaders/ssr.vert similarity index 100% rename from qglview/shaders/ssr.vert rename to libs/qglview/shaders/ssr.vert diff --git a/qglview/shaders/ssr_blur.frag b/libs/qglview/shaders/ssr_blur.frag similarity index 100% rename from qglview/shaders/ssr_blur.frag rename to libs/qglview/shaders/ssr_blur.frag diff --git a/qglview/shaders/ssr_blur.vert b/libs/qglview/shaders/ssr_blur.vert similarity index 100% rename from qglview/shaders/ssr_blur.vert rename to libs/qglview/shaders/ssr_blur.vert diff --git a/qglview/shaders/ssr_merge.frag b/libs/qglview/shaders/ssr_merge.frag similarity index 100% rename from qglview/shaders/ssr_merge.frag rename to libs/qglview/shaders/ssr_merge.frag diff --git a/qglview/shaders/ssr_merge.vert b/libs/qglview/shaders/ssr_merge.vert similarity index 100% rename from qglview/shaders/ssr_merge.vert rename to libs/qglview/shaders/ssr_merge.vert diff --git a/qad/libs/sql_table/CMakeLists.txt b/libs/sql_table/CMakeLists.txt similarity index 100% rename from qad/libs/sql_table/CMakeLists.txt rename to libs/sql_table/CMakeLists.txt diff --git a/qad/libs/sql_table/lang/qad_sql_table_en.ts b/libs/sql_table/lang/qad_sql_table_en.ts similarity index 100% rename from qad/libs/sql_table/lang/qad_sql_table_en.ts rename to libs/sql_table/lang/qad_sql_table_en.ts diff --git a/qad/libs/sql_table/lang/qad_sql_table_ru.ts b/libs/sql_table/lang/qad_sql_table_ru.ts similarity index 100% rename from qad/libs/sql_table/lang/qad_sql_table_ru.ts rename to libs/sql_table/lang/qad_sql_table_ru.ts diff --git a/qad/libs/sql_table/lang/update.bat b/libs/sql_table/lang/update.bat similarity index 100% rename from qad/libs/sql_table/lang/update.bat rename to libs/sql_table/lang/update.bat diff --git a/qad/libs/sql_table/plugin/CMakeLists.txt b/libs/sql_table/plugin/CMakeLists.txt similarity index 100% rename from qad/libs/sql_table/plugin/CMakeLists.txt rename to libs/sql_table/plugin/CMakeLists.txt diff --git a/qad/libs/sql_table/plugin/qad_sql_table.cpp b/libs/sql_table/plugin/qad_sql_table.cpp similarity index 100% rename from qad/libs/sql_table/plugin/qad_sql_table.cpp rename to libs/sql_table/plugin/qad_sql_table.cpp diff --git a/qad/libs/sql_table/plugin/qad_sql_table.h b/libs/sql_table/plugin/qad_sql_table.h similarity index 100% rename from qad/libs/sql_table/plugin/qad_sql_table.h rename to libs/sql_table/plugin/qad_sql_table.h diff --git a/qad/libs/sql_table/plugin/sql_record_plugin.cpp b/libs/sql_table/plugin/sql_record_plugin.cpp similarity index 100% rename from qad/libs/sql_table/plugin/sql_record_plugin.cpp rename to libs/sql_table/plugin/sql_record_plugin.cpp diff --git a/qad/libs/sql_table/plugin/sql_record_plugin.h b/libs/sql_table/plugin/sql_record_plugin.h similarity index 100% rename from qad/libs/sql_table/plugin/sql_record_plugin.h rename to libs/sql_table/plugin/sql_record_plugin.h diff --git a/qad/libs/sql_table/plugin/sql_table_plugin.cpp b/libs/sql_table/plugin/sql_table_plugin.cpp similarity index 100% rename from qad/libs/sql_table/plugin/sql_table_plugin.cpp rename to libs/sql_table/plugin/sql_table_plugin.cpp diff --git a/qad/libs/sql_table/plugin/sql_table_plugin.h b/libs/sql_table/plugin/sql_table_plugin.h similarity index 100% rename from qad/libs/sql_table/plugin/sql_table_plugin.h rename to libs/sql_table/plugin/sql_table_plugin.h diff --git a/qad/libs/sql_table/qad_sql_table.qrc b/libs/sql_table/qad_sql_table.qrc similarity index 100% rename from qad/libs/sql_table/qad_sql_table.qrc rename to libs/sql_table/qad_sql_table.qrc diff --git a/qad/libs/sql_table/sql_record_widget.cpp b/libs/sql_table/sql_record_widget.cpp similarity index 100% rename from qad/libs/sql_table/sql_record_widget.cpp rename to libs/sql_table/sql_record_widget.cpp diff --git a/qad/libs/sql_table/sql_record_widget.h b/libs/sql_table/sql_record_widget.h similarity index 100% rename from qad/libs/sql_table/sql_record_widget.h rename to libs/sql_table/sql_record_widget.h diff --git a/qad/libs/sql_table/sql_table_widget.cpp b/libs/sql_table/sql_table_widget.cpp similarity index 100% rename from qad/libs/sql_table/sql_table_widget.cpp rename to libs/sql_table/sql_table_widget.cpp diff --git a/qad/libs/sql_table/sql_table_widget.h b/libs/sql_table/sql_table_widget.h similarity index 100% rename from qad/libs/sql_table/sql_table_widget.h rename to libs/sql_table/sql_table_widget.h diff --git a/qad/libs/sql_table/sql_table_widget.ui b/libs/sql_table/sql_table_widget.ui similarity index 100% rename from qad/libs/sql_table/sql_table_widget.ui rename to libs/sql_table/sql_table_widget.ui diff --git a/qad/libs/touch_widgets/CMakeLists.txt b/libs/touch_widgets/CMakeLists.txt similarity index 100% rename from qad/libs/touch_widgets/CMakeLists.txt rename to libs/touch_widgets/CMakeLists.txt diff --git a/qad/libs/touch_widgets/plugin/CMakeLists.txt b/libs/touch_widgets/plugin/CMakeLists.txt similarity index 100% rename from qad/libs/touch_widgets/plugin/CMakeLists.txt rename to libs/touch_widgets/plugin/CMakeLists.txt diff --git a/qad/libs/touch_widgets/plugin/qad_touch_widgets.cpp b/libs/touch_widgets/plugin/qad_touch_widgets.cpp similarity index 100% rename from qad/libs/touch_widgets/plugin/qad_touch_widgets.cpp rename to libs/touch_widgets/plugin/qad_touch_widgets.cpp diff --git a/qad/libs/touch_widgets/plugin/qad_touch_widgets.h b/libs/touch_widgets/plugin/qad_touch_widgets.h similarity index 100% rename from qad/libs/touch_widgets/plugin/qad_touch_widgets.h rename to libs/touch_widgets/plugin/qad_touch_widgets.h diff --git a/qad/libs/touch_widgets/plugin/touchbuttframeplugin.cpp b/libs/touch_widgets/plugin/touchbuttframeplugin.cpp similarity index 100% rename from qad/libs/touch_widgets/plugin/touchbuttframeplugin.cpp rename to libs/touch_widgets/plugin/touchbuttframeplugin.cpp diff --git a/qad/libs/touch_widgets/plugin/touchbuttframeplugin.h b/libs/touch_widgets/plugin/touchbuttframeplugin.h similarity index 100% rename from qad/libs/touch_widgets/plugin/touchbuttframeplugin.h rename to libs/touch_widgets/plugin/touchbuttframeplugin.h diff --git a/qad/libs/touch_widgets/plugin/touchbuttonplugin.cpp b/libs/touch_widgets/plugin/touchbuttonplugin.cpp similarity index 100% rename from qad/libs/touch_widgets/plugin/touchbuttonplugin.cpp rename to libs/touch_widgets/plugin/touchbuttonplugin.cpp diff --git a/qad/libs/touch_widgets/plugin/touchbuttonplugin.h b/libs/touch_widgets/plugin/touchbuttonplugin.h similarity index 100% rename from qad/libs/touch_widgets/plugin/touchbuttonplugin.h rename to libs/touch_widgets/plugin/touchbuttonplugin.h diff --git a/qad/libs/touch_widgets/plugin/touchsliderplugin.cpp b/libs/touch_widgets/plugin/touchsliderplugin.cpp similarity index 100% rename from qad/libs/touch_widgets/plugin/touchsliderplugin.cpp rename to libs/touch_widgets/plugin/touchsliderplugin.cpp diff --git a/qad/libs/touch_widgets/plugin/touchsliderplugin.h b/libs/touch_widgets/plugin/touchsliderplugin.h similarity index 100% rename from qad/libs/touch_widgets/plugin/touchsliderplugin.h rename to libs/touch_widgets/plugin/touchsliderplugin.h diff --git a/qad/libs/touch_widgets/touch_bar.h b/libs/touch_widgets/touch_bar.h similarity index 100% rename from qad/libs/touch_widgets/touch_bar.h rename to libs/touch_widgets/touch_bar.h diff --git a/qad/libs/touch_widgets/touch_widgets.qrc b/libs/touch_widgets/touch_widgets.qrc similarity index 100% rename from qad/libs/touch_widgets/touch_widgets.qrc rename to libs/touch_widgets/touch_widgets.qrc diff --git a/qad/libs/touch_widgets/touchbuttframe.cpp b/libs/touch_widgets/touchbuttframe.cpp similarity index 100% rename from qad/libs/touch_widgets/touchbuttframe.cpp rename to libs/touch_widgets/touchbuttframe.cpp diff --git a/qad/libs/touch_widgets/touchbuttframe.h b/libs/touch_widgets/touchbuttframe.h similarity index 100% rename from qad/libs/touch_widgets/touchbuttframe.h rename to libs/touch_widgets/touchbuttframe.h diff --git a/qad/libs/touch_widgets/touchbutton.cpp b/libs/touch_widgets/touchbutton.cpp similarity index 100% rename from qad/libs/touch_widgets/touchbutton.cpp rename to libs/touch_widgets/touchbutton.cpp diff --git a/qad/libs/touch_widgets/touchbutton.h b/libs/touch_widgets/touchbutton.h similarity index 100% rename from qad/libs/touch_widgets/touchbutton.h rename to libs/touch_widgets/touchbutton.h diff --git a/qad/libs/touch_widgets/touchslider.cpp b/libs/touch_widgets/touchslider.cpp similarity index 100% rename from qad/libs/touch_widgets/touchslider.cpp rename to libs/touch_widgets/touchslider.cpp diff --git a/qad/libs/touch_widgets/touchslider.h b/libs/touch_widgets/touchslider.h similarity index 100% rename from qad/libs/touch_widgets/touchslider.h rename to libs/touch_widgets/touchslider.h diff --git a/qad/libs/touch_widgets/touchslider.ui b/libs/touch_widgets/touchslider.ui similarity index 100% rename from qad/libs/touch_widgets/touchslider.ui rename to libs/touch_widgets/touchslider.ui diff --git a/qad/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt similarity index 100% rename from qad/libs/utils/CMakeLists.txt rename to libs/utils/CMakeLists.txt diff --git a/qad/libs/utils/chunkstream.cpp b/libs/utils/chunkstream.cpp similarity index 100% rename from qad/libs/utils/chunkstream.cpp rename to libs/utils/chunkstream.cpp diff --git a/qad/libs/utils/chunkstream.h b/libs/utils/chunkstream.h similarity index 100% rename from qad/libs/utils/chunkstream.h rename to libs/utils/chunkstream.h diff --git a/qad/libs/utils/plugin/CMakeLists.txt b/libs/utils/plugin/CMakeLists.txt similarity index 100% rename from qad/libs/utils/plugin/CMakeLists.txt rename to libs/utils/plugin/CMakeLists.txt diff --git a/qad/libs/utils/plugin/qad_utils.cpp b/libs/utils/plugin/qad_utils.cpp similarity index 100% rename from qad/libs/utils/plugin/qad_utils.cpp rename to libs/utils/plugin/qad_utils.cpp diff --git a/qad/libs/utils/plugin/qad_utils.h b/libs/utils/plugin/qad_utils.h similarity index 100% rename from qad/libs/utils/plugin/qad_utils.h rename to libs/utils/plugin/qad_utils.h diff --git a/qad/libs/utils/propertystorage.cpp b/libs/utils/propertystorage.cpp similarity index 100% rename from qad/libs/utils/propertystorage.cpp rename to libs/utils/propertystorage.cpp diff --git a/qad/libs/utils/propertystorage.h b/libs/utils/propertystorage.h similarity index 100% rename from qad/libs/utils/propertystorage.h rename to libs/utils/propertystorage.h diff --git a/qad/libs/utils/qad_locations.cpp b/libs/utils/qad_locations.cpp similarity index 100% rename from qad/libs/utils/qad_locations.cpp rename to libs/utils/qad_locations.cpp diff --git a/qad/libs/utils/qad_locations.h b/libs/utils/qad_locations.h similarity index 100% rename from qad/libs/utils/qad_locations.h rename to libs/utils/qad_locations.h diff --git a/qad/libs/utils/qad_types.cpp b/libs/utils/qad_types.cpp similarity index 100% rename from qad/libs/utils/qad_types.cpp rename to libs/utils/qad_types.cpp diff --git a/qad/libs/utils/qad_types.h b/libs/utils/qad_types.h similarity index 100% rename from qad/libs/utils/qad_types.h rename to libs/utils/qad_types.h diff --git a/qad/libs/utils/qad_utils.qrc b/libs/utils/qad_utils.qrc similarity index 100% rename from qad/libs/utils/qad_utils.qrc rename to libs/utils/qad_utils.qrc diff --git a/qad/libs/utils/qpiconfig.cpp b/libs/utils/qpiconfig.cpp similarity index 100% rename from qad/libs/utils/qpiconfig.cpp rename to libs/utils/qpiconfig.cpp diff --git a/qad/libs/utils/qpiconfig.h b/libs/utils/qpiconfig.h similarity index 100% rename from qad/libs/utils/qpiconfig.h rename to libs/utils/qpiconfig.h diff --git a/qad/libs/utils/qpievaluator.cpp b/libs/utils/qpievaluator.cpp similarity index 100% rename from qad/libs/utils/qpievaluator.cpp rename to libs/utils/qpievaluator.cpp diff --git a/qad/libs/utils/qpievaluator.h b/libs/utils/qpievaluator.h similarity index 100% rename from qad/libs/utils/qpievaluator.h rename to libs/utils/qpievaluator.h diff --git a/qad/libs/widgets/CMakeLists.txt b/libs/widgets/CMakeLists.txt similarity index 100% rename from qad/libs/widgets/CMakeLists.txt rename to libs/widgets/CMakeLists.txt diff --git a/qad/libs/widgets/chardialog.cpp b/libs/widgets/chardialog.cpp similarity index 100% rename from qad/libs/widgets/chardialog.cpp rename to libs/widgets/chardialog.cpp diff --git a/qad/libs/widgets/chardialog.h b/libs/widgets/chardialog.h similarity index 100% rename from qad/libs/widgets/chardialog.h rename to libs/widgets/chardialog.h diff --git a/qad/libs/widgets/chardialog.ui b/libs/widgets/chardialog.ui similarity index 100% rename from qad/libs/widgets/chardialog.ui rename to libs/widgets/chardialog.ui diff --git a/qad/libs/widgets/clineedit.cpp b/libs/widgets/clineedit.cpp similarity index 100% rename from qad/libs/widgets/clineedit.cpp rename to libs/widgets/clineedit.cpp diff --git a/qad/libs/widgets/clineedit.h b/libs/widgets/clineedit.h similarity index 100% rename from qad/libs/widgets/clineedit.h rename to libs/widgets/clineedit.h diff --git a/qad/libs/widgets/colorbutton.cpp b/libs/widgets/colorbutton.cpp similarity index 100% rename from qad/libs/widgets/colorbutton.cpp rename to libs/widgets/colorbutton.cpp diff --git a/qad/libs/widgets/colorbutton.h b/libs/widgets/colorbutton.h similarity index 100% rename from qad/libs/widgets/colorbutton.h rename to libs/widgets/colorbutton.h diff --git a/qad/libs/widgets/ecombobox.cpp b/libs/widgets/ecombobox.cpp similarity index 100% rename from qad/libs/widgets/ecombobox.cpp rename to libs/widgets/ecombobox.cpp diff --git a/qad/libs/widgets/ecombobox.h b/libs/widgets/ecombobox.h similarity index 100% rename from qad/libs/widgets/ecombobox.h rename to libs/widgets/ecombobox.h diff --git a/qad/libs/widgets/evalspinbox.cpp b/libs/widgets/evalspinbox.cpp similarity index 100% rename from qad/libs/widgets/evalspinbox.cpp rename to libs/widgets/evalspinbox.cpp diff --git a/qad/libs/widgets/evalspinbox.h b/libs/widgets/evalspinbox.h similarity index 100% rename from qad/libs/widgets/evalspinbox.h rename to libs/widgets/evalspinbox.h diff --git a/qad/libs/widgets/iconedlabel.cpp b/libs/widgets/iconedlabel.cpp similarity index 100% rename from qad/libs/widgets/iconedlabel.cpp rename to libs/widgets/iconedlabel.cpp diff --git a/qad/libs/widgets/iconedlabel.h b/libs/widgets/iconedlabel.h similarity index 100% rename from qad/libs/widgets/iconedlabel.h rename to libs/widgets/iconedlabel.h diff --git a/qad/libs/widgets/image_view.cpp b/libs/widgets/image_view.cpp similarity index 100% rename from qad/libs/widgets/image_view.cpp rename to libs/widgets/image_view.cpp diff --git a/qad/libs/widgets/image_view.h b/libs/widgets/image_view.h similarity index 100% rename from qad/libs/widgets/image_view.h rename to libs/widgets/image_view.h diff --git a/qad/libs/widgets/lang/qad_widgets_en.ts b/libs/widgets/lang/qad_widgets_en.ts similarity index 100% rename from qad/libs/widgets/lang/qad_widgets_en.ts rename to libs/widgets/lang/qad_widgets_en.ts diff --git a/qad/libs/widgets/lang/qad_widgets_ru.ts b/libs/widgets/lang/qad_widgets_ru.ts similarity index 100% rename from qad/libs/widgets/lang/qad_widgets_ru.ts rename to libs/widgets/lang/qad_widgets_ru.ts diff --git a/qad/libs/widgets/lang/update.bat b/libs/widgets/lang/update.bat similarity index 100% rename from qad/libs/widgets/lang/update.bat rename to libs/widgets/lang/update.bat diff --git a/qad/libs/widgets/mathmatrixedit.cpp b/libs/widgets/mathmatrixedit.cpp similarity index 100% rename from qad/libs/widgets/mathmatrixedit.cpp rename to libs/widgets/mathmatrixedit.cpp diff --git a/qad/libs/widgets/mathmatrixedit.h b/libs/widgets/mathmatrixedit.h similarity index 100% rename from qad/libs/widgets/mathmatrixedit.h rename to libs/widgets/mathmatrixedit.h diff --git a/qad/libs/widgets/mathvectoredit.cpp b/libs/widgets/mathvectoredit.cpp similarity index 100% rename from qad/libs/widgets/mathvectoredit.cpp rename to libs/widgets/mathvectoredit.cpp diff --git a/qad/libs/widgets/mathvectoredit.h b/libs/widgets/mathvectoredit.h similarity index 100% rename from qad/libs/widgets/mathvectoredit.h rename to libs/widgets/mathvectoredit.h diff --git a/qad/libs/widgets/matrixedit.cpp b/libs/widgets/matrixedit.cpp similarity index 100% rename from qad/libs/widgets/matrixedit.cpp rename to libs/widgets/matrixedit.cpp diff --git a/qad/libs/widgets/matrixedit.h b/libs/widgets/matrixedit.h similarity index 100% rename from qad/libs/widgets/matrixedit.h rename to libs/widgets/matrixedit.h diff --git a/qad/libs/widgets/matrixedit.ui b/libs/widgets/matrixedit.ui similarity index 100% rename from qad/libs/widgets/matrixedit.ui rename to libs/widgets/matrixedit.ui diff --git a/qad/libs/widgets/plugin/CMakeLists.txt b/libs/widgets/plugin/CMakeLists.txt similarity index 100% rename from qad/libs/widgets/plugin/CMakeLists.txt rename to libs/widgets/plugin/CMakeLists.txt diff --git a/qad/libs/widgets/plugin/chardialogplugin.cpp b/libs/widgets/plugin/chardialogplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/chardialogplugin.cpp rename to libs/widgets/plugin/chardialogplugin.cpp diff --git a/qad/libs/widgets/plugin/chardialogplugin.h b/libs/widgets/plugin/chardialogplugin.h similarity index 100% rename from qad/libs/widgets/plugin/chardialogplugin.h rename to libs/widgets/plugin/chardialogplugin.h diff --git a/qad/libs/widgets/plugin/clineeditplugin.cpp b/libs/widgets/plugin/clineeditplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/clineeditplugin.cpp rename to libs/widgets/plugin/clineeditplugin.cpp diff --git a/qad/libs/widgets/plugin/clineeditplugin.h b/libs/widgets/plugin/clineeditplugin.h similarity index 100% rename from qad/libs/widgets/plugin/clineeditplugin.h rename to libs/widgets/plugin/clineeditplugin.h diff --git a/qad/libs/widgets/plugin/colorbuttonplugin.cpp b/libs/widgets/plugin/colorbuttonplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/colorbuttonplugin.cpp rename to libs/widgets/plugin/colorbuttonplugin.cpp diff --git a/qad/libs/widgets/plugin/colorbuttonplugin.h b/libs/widgets/plugin/colorbuttonplugin.h similarity index 100% rename from qad/libs/widgets/plugin/colorbuttonplugin.h rename to libs/widgets/plugin/colorbuttonplugin.h diff --git a/qad/libs/widgets/plugin/ecomboboxplugin.cpp b/libs/widgets/plugin/ecomboboxplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/ecomboboxplugin.cpp rename to libs/widgets/plugin/ecomboboxplugin.cpp diff --git a/qad/libs/widgets/plugin/ecomboboxplugin.h b/libs/widgets/plugin/ecomboboxplugin.h similarity index 100% rename from qad/libs/widgets/plugin/ecomboboxplugin.h rename to libs/widgets/plugin/ecomboboxplugin.h diff --git a/qad/libs/widgets/plugin/evalspinboxplugin.cpp b/libs/widgets/plugin/evalspinboxplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/evalspinboxplugin.cpp rename to libs/widgets/plugin/evalspinboxplugin.cpp diff --git a/qad/libs/widgets/plugin/evalspinboxplugin.h b/libs/widgets/plugin/evalspinboxplugin.h similarity index 100% rename from qad/libs/widgets/plugin/evalspinboxplugin.h rename to libs/widgets/plugin/evalspinboxplugin.h diff --git a/qad/libs/widgets/plugin/iconedlabelplugin.h b/libs/widgets/plugin/iconedlabelplugin.h similarity index 100% rename from qad/libs/widgets/plugin/iconedlabelplugin.h rename to libs/widgets/plugin/iconedlabelplugin.h diff --git a/qad/libs/widgets/plugin/imageviewplugin.cpp b/libs/widgets/plugin/imageviewplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/imageviewplugin.cpp rename to libs/widgets/plugin/imageviewplugin.cpp diff --git a/qad/libs/widgets/plugin/imageviewplugin.h b/libs/widgets/plugin/imageviewplugin.h similarity index 100% rename from qad/libs/widgets/plugin/imageviewplugin.h rename to libs/widgets/plugin/imageviewplugin.h diff --git a/qad/libs/widgets/plugin/lconedlabelplugin.cpp b/libs/widgets/plugin/lconedlabelplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/lconedlabelplugin.cpp rename to libs/widgets/plugin/lconedlabelplugin.cpp diff --git a/qad/libs/widgets/plugin/qad_widgets.cpp b/libs/widgets/plugin/qad_widgets.cpp similarity index 100% rename from qad/libs/widgets/plugin/qad_widgets.cpp rename to libs/widgets/plugin/qad_widgets.cpp diff --git a/qad/libs/widgets/plugin/qad_widgets.h b/libs/widgets/plugin/qad_widgets.h similarity index 100% rename from qad/libs/widgets/plugin/qad_widgets.h rename to libs/widgets/plugin/qad_widgets.h diff --git a/qad/libs/widgets/plugin/qcodeeditplugin.cpp b/libs/widgets/plugin/qcodeeditplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/qcodeeditplugin.cpp rename to libs/widgets/plugin/qcodeeditplugin.cpp diff --git a/qad/libs/widgets/plugin/qcodeeditplugin.h b/libs/widgets/plugin/qcodeeditplugin.h similarity index 100% rename from qad/libs/widgets/plugin/qcodeeditplugin.h rename to libs/widgets/plugin/qcodeeditplugin.h diff --git a/qad/libs/widgets/plugin/qipeditplugin.cpp b/libs/widgets/plugin/qipeditplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/qipeditplugin.cpp rename to libs/widgets/plugin/qipeditplugin.cpp diff --git a/qad/libs/widgets/plugin/qipeditplugin.h b/libs/widgets/plugin/qipeditplugin.h similarity index 100% rename from qad/libs/widgets/plugin/qipeditplugin.h rename to libs/widgets/plugin/qipeditplugin.h diff --git a/qad/libs/widgets/plugin/qpiconfigplugin.cpp b/libs/widgets/plugin/qpiconfigplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/qpiconfigplugin.cpp rename to libs/widgets/plugin/qpiconfigplugin.cpp diff --git a/qad/libs/widgets/plugin/qpiconfigplugin.h b/libs/widgets/plugin/qpiconfigplugin.h similarity index 100% rename from qad/libs/widgets/plugin/qpiconfigplugin.h rename to libs/widgets/plugin/qpiconfigplugin.h diff --git a/qad/libs/widgets/plugin/qpiconsoleplugin.cpp b/libs/widgets/plugin/qpiconsoleplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/qpiconsoleplugin.cpp rename to libs/widgets/plugin/qpiconsoleplugin.cpp diff --git a/qad/libs/widgets/plugin/qpiconsoleplugin.h b/libs/widgets/plugin/qpiconsoleplugin.h similarity index 100% rename from qad/libs/widgets/plugin/qpiconsoleplugin.h rename to libs/widgets/plugin/qpiconsoleplugin.h diff --git a/qad/libs/widgets/plugin/qpointeditplugin.cpp b/libs/widgets/plugin/qpointeditplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/qpointeditplugin.cpp rename to libs/widgets/plugin/qpointeditplugin.cpp diff --git a/qad/libs/widgets/plugin/qpointeditplugin.h b/libs/widgets/plugin/qpointeditplugin.h similarity index 100% rename from qad/libs/widgets/plugin/qpointeditplugin.h rename to libs/widgets/plugin/qpointeditplugin.h diff --git a/qad/libs/widgets/plugin/qrecteditplugin.cpp b/libs/widgets/plugin/qrecteditplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/qrecteditplugin.cpp rename to libs/widgets/plugin/qrecteditplugin.cpp diff --git a/qad/libs/widgets/plugin/qrecteditplugin.h b/libs/widgets/plugin/qrecteditplugin.h similarity index 100% rename from qad/libs/widgets/plugin/qrecteditplugin.h rename to libs/widgets/plugin/qrecteditplugin.h diff --git a/qad/libs/widgets/plugin/qvarianteditplugin.cpp b/libs/widgets/plugin/qvarianteditplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/qvarianteditplugin.cpp rename to libs/widgets/plugin/qvarianteditplugin.cpp diff --git a/qad/libs/widgets/plugin/qvarianteditplugin.h b/libs/widgets/plugin/qvarianteditplugin.h similarity index 100% rename from qad/libs/widgets/plugin/qvarianteditplugin.h rename to libs/widgets/plugin/qvarianteditplugin.h diff --git a/qad/libs/widgets/plugin/scroll_spin_boxplugin.cpp b/libs/widgets/plugin/scroll_spin_boxplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/scroll_spin_boxplugin.cpp rename to libs/widgets/plugin/scroll_spin_boxplugin.cpp diff --git a/qad/libs/widgets/plugin/scroll_spin_boxplugin.h b/libs/widgets/plugin/scroll_spin_boxplugin.h similarity index 100% rename from qad/libs/widgets/plugin/scroll_spin_boxplugin.h rename to libs/widgets/plugin/scroll_spin_boxplugin.h diff --git a/qad/libs/widgets/plugin/shortcutsplugin.cpp b/libs/widgets/plugin/shortcutsplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/shortcutsplugin.cpp rename to libs/widgets/plugin/shortcutsplugin.cpp diff --git a/qad/libs/widgets/plugin/shortcutsplugin.h b/libs/widgets/plugin/shortcutsplugin.h similarity index 100% rename from qad/libs/widgets/plugin/shortcutsplugin.h rename to libs/widgets/plugin/shortcutsplugin.h diff --git a/qad/libs/widgets/plugin/spinsliderplugin.cpp b/libs/widgets/plugin/spinsliderplugin.cpp similarity index 100% rename from qad/libs/widgets/plugin/spinsliderplugin.cpp rename to libs/widgets/plugin/spinsliderplugin.cpp diff --git a/qad/libs/widgets/plugin/spinsliderplugin.h b/libs/widgets/plugin/spinsliderplugin.h similarity index 100% rename from qad/libs/widgets/plugin/spinsliderplugin.h rename to libs/widgets/plugin/spinsliderplugin.h diff --git a/qad/libs/widgets/propertystorage_editor.cpp b/libs/widgets/propertystorage_editor.cpp similarity index 100% rename from qad/libs/widgets/propertystorage_editor.cpp rename to libs/widgets/propertystorage_editor.cpp diff --git a/qad/libs/widgets/propertystorage_editor.h b/libs/widgets/propertystorage_editor.h similarity index 100% rename from qad/libs/widgets/propertystorage_editor.h rename to libs/widgets/propertystorage_editor.h diff --git a/qad/libs/widgets/qad_widgets.qrc b/libs/widgets/qad_widgets.qrc similarity index 100% rename from qad/libs/widgets/qad_widgets.qrc rename to libs/widgets/qad_widgets.qrc diff --git a/qad/libs/widgets/qcodeedit.cpp b/libs/widgets/qcodeedit.cpp similarity index 100% rename from qad/libs/widgets/qcodeedit.cpp rename to libs/widgets/qcodeedit.cpp diff --git a/qad/libs/widgets/qcodeedit.h b/libs/widgets/qcodeedit.h similarity index 100% rename from qad/libs/widgets/qcodeedit.h rename to libs/widgets/qcodeedit.h diff --git a/qad/libs/widgets/qcodeedit.ui b/libs/widgets/qcodeedit.ui similarity index 100% rename from qad/libs/widgets/qcodeedit.ui rename to libs/widgets/qcodeedit.ui diff --git a/qad/libs/widgets/qipedit.cpp b/libs/widgets/qipedit.cpp similarity index 100% rename from qad/libs/widgets/qipedit.cpp rename to libs/widgets/qipedit.cpp diff --git a/qad/libs/widgets/qipedit.h b/libs/widgets/qipedit.h similarity index 100% rename from qad/libs/widgets/qipedit.h rename to libs/widgets/qipedit.h diff --git a/qad/libs/widgets/qpiconfignewdialog.cpp b/libs/widgets/qpiconfignewdialog.cpp similarity index 100% rename from qad/libs/widgets/qpiconfignewdialog.cpp rename to libs/widgets/qpiconfignewdialog.cpp diff --git a/qad/libs/widgets/qpiconfignewdialog.h b/libs/widgets/qpiconfignewdialog.h similarity index 100% rename from qad/libs/widgets/qpiconfignewdialog.h rename to libs/widgets/qpiconfignewdialog.h diff --git a/qad/libs/widgets/qpiconfignewdialog.ui b/libs/widgets/qpiconfignewdialog.ui similarity index 100% rename from qad/libs/widgets/qpiconfignewdialog.ui rename to libs/widgets/qpiconfignewdialog.ui diff --git a/qad/libs/widgets/qpiconfigvaluewidget.cpp b/libs/widgets/qpiconfigvaluewidget.cpp similarity index 100% rename from qad/libs/widgets/qpiconfigvaluewidget.cpp rename to libs/widgets/qpiconfigvaluewidget.cpp diff --git a/qad/libs/widgets/qpiconfigvaluewidget.h b/libs/widgets/qpiconfigvaluewidget.h similarity index 100% rename from qad/libs/widgets/qpiconfigvaluewidget.h rename to libs/widgets/qpiconfigvaluewidget.h diff --git a/qad/libs/widgets/qpiconfigwidget.cpp b/libs/widgets/qpiconfigwidget.cpp similarity index 100% rename from qad/libs/widgets/qpiconfigwidget.cpp rename to libs/widgets/qpiconfigwidget.cpp diff --git a/qad/libs/widgets/qpiconfigwidget.h b/libs/widgets/qpiconfigwidget.h similarity index 100% rename from qad/libs/widgets/qpiconfigwidget.h rename to libs/widgets/qpiconfigwidget.h diff --git a/qad/libs/widgets/qpiconsole.cpp b/libs/widgets/qpiconsole.cpp similarity index 100% rename from qad/libs/widgets/qpiconsole.cpp rename to libs/widgets/qpiconsole.cpp diff --git a/qad/libs/widgets/qpiconsole.h b/libs/widgets/qpiconsole.h similarity index 100% rename from qad/libs/widgets/qpiconsole.h rename to libs/widgets/qpiconsole.h diff --git a/qad/libs/widgets/qpointedit.cpp b/libs/widgets/qpointedit.cpp similarity index 100% rename from qad/libs/widgets/qpointedit.cpp rename to libs/widgets/qpointedit.cpp diff --git a/qad/libs/widgets/qpointedit.h b/libs/widgets/qpointedit.h similarity index 100% rename from qad/libs/widgets/qpointedit.h rename to libs/widgets/qpointedit.h diff --git a/qad/libs/widgets/qrectedit.cpp b/libs/widgets/qrectedit.cpp similarity index 100% rename from qad/libs/widgets/qrectedit.cpp rename to libs/widgets/qrectedit.cpp diff --git a/qad/libs/widgets/qrectedit.h b/libs/widgets/qrectedit.h similarity index 100% rename from qad/libs/widgets/qrectedit.h rename to libs/widgets/qrectedit.h diff --git a/qad/libs/widgets/qvariantedit.cpp b/libs/widgets/qvariantedit.cpp similarity index 100% rename from qad/libs/widgets/qvariantedit.cpp rename to libs/widgets/qvariantedit.cpp diff --git a/qad/libs/widgets/qvariantedit.h b/libs/widgets/qvariantedit.h similarity index 100% rename from qad/libs/widgets/qvariantedit.h rename to libs/widgets/qvariantedit.h diff --git a/qad/libs/widgets/qvariantedit_custom.cpp b/libs/widgets/qvariantedit_custom.cpp similarity index 100% rename from qad/libs/widgets/qvariantedit_custom.cpp rename to libs/widgets/qvariantedit_custom.cpp diff --git a/qad/libs/widgets/qvariantedit_custom.h b/libs/widgets/qvariantedit_custom.h similarity index 100% rename from qad/libs/widgets/qvariantedit_custom.h rename to libs/widgets/qvariantedit_custom.h diff --git a/qad/libs/widgets/scroll_spin_box.cpp b/libs/widgets/scroll_spin_box.cpp similarity index 100% rename from qad/libs/widgets/scroll_spin_box.cpp rename to libs/widgets/scroll_spin_box.cpp diff --git a/qad/libs/widgets/scroll_spin_box.h b/libs/widgets/scroll_spin_box.h similarity index 100% rename from qad/libs/widgets/scroll_spin_box.h rename to libs/widgets/scroll_spin_box.h diff --git a/qad/libs/widgets/scroll_spin_box.ui b/libs/widgets/scroll_spin_box.ui similarity index 100% rename from qad/libs/widgets/scroll_spin_box.ui rename to libs/widgets/scroll_spin_box.ui diff --git a/qad/libs/widgets/session_manager.cpp b/libs/widgets/session_manager.cpp similarity index 100% rename from qad/libs/widgets/session_manager.cpp rename to libs/widgets/session_manager.cpp diff --git a/qad/libs/widgets/session_manager.h b/libs/widgets/session_manager.h similarity index 100% rename from qad/libs/widgets/session_manager.h rename to libs/widgets/session_manager.h diff --git a/qad/libs/widgets/shortcuts.cpp b/libs/widgets/shortcuts.cpp similarity index 100% rename from qad/libs/widgets/shortcuts.cpp rename to libs/widgets/shortcuts.cpp diff --git a/qad/libs/widgets/shortcuts.h b/libs/widgets/shortcuts.h similarity index 100% rename from qad/libs/widgets/shortcuts.h rename to libs/widgets/shortcuts.h diff --git a/qad/libs/widgets/spinslider.cpp b/libs/widgets/spinslider.cpp similarity index 100% rename from qad/libs/widgets/spinslider.cpp rename to libs/widgets/spinslider.cpp diff --git a/qad/libs/widgets/spinslider.h b/libs/widgets/spinslider.h similarity index 100% rename from qad/libs/widgets/spinslider.h rename to libs/widgets/spinslider.h diff --git a/logo.png b/logo.png index e08b36a7bd5d92b148d581a713d99f72979dcf35..7ca8e3ce4e342c46f81da0b53fff08b58e83b441 100644 GIT binary patch literal 23645 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 literal 13843 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 VA4M$F<+T6+002ovPDHLkV1iYT0IC20 diff --git a/make_libs.bat b/make_libs.bat deleted file mode 100644 index d530e09..0000000 --- a/make_libs.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -set ARCH=%~1 -set PATH=%SDK_MINGW_DIR%%ARCH%\bin;%SDK_QT4_DIR%%ARCH%\bin;%SDK_CMAKE_DIR%\bin -if defined SDK_QT5_DIR set Qt5_DIR=%SDK_QT5_DIR%%ARCH% -mkdir ..\libs_build_win%ARCH% -cd ../libs_build_win%ARCH% && cmake_mgw -Wno-dev -DQGLVIEW=1 -DQGLENGINE=1 -DQT4=0 ../libs && make install -j4 && cd ../libs && pause diff --git a/make_libs.sh b/make_libs.sh deleted file mode 100755 index ec03987..0000000 --- a/make_libs.sh +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/bash -cd .. -mkdir libs_build_linux -cd libs_build_linux -cmake ../libs -make install $@ diff --git a/make_libs32.bat b/make_libs32.bat deleted file mode 100644 index c1103ef..0000000 --- a/make_libs32.bat +++ /dev/null @@ -1 +0,0 @@ -make_libs.bat 32 \ No newline at end of file diff --git a/make_libs64.bat b/make_libs64.bat deleted file mode 100644 index f12abc1..0000000 --- a/make_libs64.bat +++ /dev/null @@ -1 +0,0 @@ -make_libs.bat 64 \ No newline at end of file diff --git a/make_libs_all.bat b/make_libs_all.bat deleted file mode 100644 index b6bd18b..0000000 --- a/make_libs_all.bat +++ /dev/null @@ -1,2 +0,0 @@ -start cmd /C make_libs32.bat -start cmd /C make_libs64.bat diff --git a/make_libs_android.bat b/make_libs_android.bat deleted file mode 100644 index 4abfcbb..0000000 --- a/make_libs_android.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -mkdir ..\libs_build_android_%~1 -cd ..\libs_build_android_%~1 -call ..\libs\cmake_android 21 %~1 ..\libs "-DUTILS=0 -DDEBUG=0 -DCMAKE_BUILD_TYPE=Release" -call make install -j4 -cd ..\libs diff --git a/make_libs_android_all.bat b/make_libs_android_all.bat deleted file mode 100644 index b15632e..0000000 --- a/make_libs_android_all.bat +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -for %%a in (x86,x86_64,arm,arm64) do ( - call .\make_libs_android %%a -) diff --git a/pip b/pip deleted file mode 160000 index 3965e54..0000000 --- a/pip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3965e54e38cbb23e8103e1e09a49910d5b5957b3 diff --git a/piqt/CMakeLists.txt b/piqt/CMakeLists.txt deleted file mode 100644 index 08e8ef9..0000000 --- a/piqt/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -cmake_policy(SET CMP0017 NEW) # need include() with .cmake - -macro(piqt_library NAME _MODULES _LIBS) - _qt_project(${NAME} FALSE "PIQt" "${_MODULES}" "pip;${_LIBS}" ${ARGN}) - _qt_install(${NAME} FALSE "pip" "out_HDR" "out_QM") -endmacro() - -macro(piqt_application NAME _MODULES _LIBS) - _qt_project(${NAME} TRUE "PIQt" "${_MODULES}" "pip;${_LIBS}" ${ARGN}) - _qt_install(${NAME} TRUE "pip" "" "out_QM") -endmacro() - - -include_directories(${PIP_INCLUDES}) -add_subdirectory(libs) -if (UTILS) - add_subdirectory(utils) -endif() - -copy_to_parent(piqt_includes) diff --git a/piqt/LICENSE.txt b/piqt/LICENSE.txt deleted file mode 100644 index 0a04128..0000000 --- a/piqt/LICENSE.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/piqt/libs/CMakeLists.txt b/piqt/libs/CMakeLists.txt deleted file mode 100644 index c20718c..0000000 --- a/piqt/libs/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_directories_with_include("piqt_") diff --git a/piqt/utils/CMakeLists.txt b/piqt/utils/CMakeLists.txt deleted file mode 100644 index 4dbf12d..0000000 --- a/piqt/utils/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_directories("piqt_") diff --git a/project_fs/ProjectFilesystemPlugin.json.in b/project_fs/ProjectFilesystemPlugin.json.in deleted file mode 100644 index 3ae41ba..0000000 --- a/project_fs/ProjectFilesystemPlugin.json.in +++ /dev/null @@ -1,11 +0,0 @@ -{ - \"Name\" : \"ProjectFilesystemPlugin\", - \"Version\" : \"1.1.0\", - \"CompatVersion\" : \"1.1.0\", - \"Vendor\" : \"Peri4\", - \"Copyright\" : \"(C) Peri4\", - \"License\" : \"LGPLv3\", - \"Description\" : \"LGPLv3\", - \"Url\" : \"\", - $$dependencyList -} diff --git a/project_fs/filterdialog.cpp b/project_fs/filterdialog.cpp deleted file mode 100644 index 2137cd1..0000000 --- a/project_fs/filterdialog.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "filterdialog.h" -#include -#include - - -FilterDialog::FilterDialog(QWidget * parent): QDialog(parent) { - setupUi(this); - toolButton->setIcon(Utils::Icons::CLEAN.icon()); - toolButton_2->setIcon(Utils::Icons::CLEAN.icon()); - toolButton_3->setIcon(Utils::Icons::CLEAN.icon()); - toolButton_4->setIcon(Utils::Icons::CLEAN.icon()); -} - - -void FilterDialog::changeEvent(QEvent *e) { - QDialog::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - retranslateUi(this); - break; - default: - break; - } -} - - -FilterDialog::Filter FilterDialog::filter() const { - FilterDialog::Filter ret; - ret.files_show = getFilters(lineFilesShow); - ret.files_hide = getFilters(lineFilesHide); - ret.dirs_show = getFilters(lineDirsShow); - ret.dirs_hide = getFilters(lineDirsHide); - return ret; -} - -void FilterDialog::setFilter(const FilterDialog::Filter & f) { - setFilters(lineFilesShow, f.files_show); - setFilters(lineFilesHide, f.files_hide); - setFilters(lineDirsShow, f.dirs_show); - setFilters(lineDirsHide, f.dirs_hide); -} - - -QStringList FilterDialog::getFilters(QLineEdit * le) const { - if (!le) return QStringList(); - QStringList ret = le->text().split(","); - for (int i = 0; i < ret.size(); ++i) - ret[i] = ret[i].trimmed(); - ret.removeAll(""); - return ret; -} - - -void FilterDialog::setFilters(QLineEdit * le, QStringList f) { - if (!le) return; - le->setText(f.join(",")); -} - - -FilterDialog::Filter::Filter(const QVariant & v) { - QByteArray ba = v.toByteArray(); - if (ba.isEmpty()) return; - QDataStream s(ba); - s >> files_show >> files_hide >> dirs_show >> dirs_hide; -} - - -QVariant FilterDialog::Filter::toVariant() const { - QByteArray ba; - QDataStream s(&ba, QIODevice::ReadWrite); - s << files_show << files_hide << dirs_show << dirs_hide; - return QVariant(ba); -} - - -bool FilterDialog::Filter::filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const { - if (fshow.isEmpty() && fhide.isEmpty()) return true; - if (!fhide.isEmpty()) { - if (QDir::match(fhide, path)) - return false; - else { - if (fshow.isEmpty()) - return true; - else - return QDir::match(fshow, path); - } - } - if (!fshow.isEmpty()) - return QDir::match(fshow, path); - return true; -} diff --git a/project_fs/filterdialog.h b/project_fs/filterdialog.h deleted file mode 100644 index 0d1e2a3..0000000 --- a/project_fs/filterdialog.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef FILTERDIALOG_H -#define FILTERDIALOG_H - -#include "ui_filterdialog.h" - -class FilterDialog: public QDialog, private Ui::FilterDialog -{ - Q_OBJECT -public: - explicit FilterDialog(QWidget *parent = 0); - - struct Filter { - Filter() {} - Filter(const QVariant & v); - QVariant toVariant() const; - bool filterFile(const QString & path) const {return filterLogic(files_show, files_hide, path);} - bool filterDir(const QString & path) const {return filterLogic(dirs_show, dirs_hide, path);} - QStringList files_show; - QStringList files_hide; - QStringList dirs_show; - QStringList dirs_hide; - private: - bool filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const; - }; - - Filter filter() const; - void setFilter(const Filter & f); - -protected: - void changeEvent(QEvent *e); - - QStringList getFilters(QLineEdit * le) const; - void setFilters(QLineEdit * le, QStringList f); - -}; - -#endif // FILTERDIALOG_H diff --git a/project_fs/filterdialog.ui b/project_fs/filterdialog.ui deleted file mode 100644 index df38a3f..0000000 --- a/project_fs/filterdialog.ui +++ /dev/null @@ -1,226 +0,0 @@ - - - FilterDialog - - - - 0 - 0 - 342 - 250 - - - - Project filesystem filters - - - - - - Input filters, separated by ",": - - - - - - - - - Show dirs: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - Hide files: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Show files: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - Hide dirs: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - lineFilesShow - lineFilesHide - lineDirsShow - lineDirsHide - toolButton - toolButton_2 - toolButton_3 - toolButton_4 - - - - - buttonBox - accepted() - FilterDialog - accept() - - - 259 - 238 - - - 157 - 274 - - - - - buttonBox - rejected() - FilterDialog - reject() - - - 327 - 238 - - - 286 - 274 - - - - - toolButton - clicked() - lineFilesShow - clear() - - - 329 - 60 - - - 269 - 58 - - - - - toolButton_2 - clicked() - lineFilesHide - clear() - - - 329 - 93 - - - 295 - 91 - - - - - toolButton_3 - clicked() - lineDirsShow - clear() - - - 329 - 126 - - - 295 - 124 - - - - - toolButton_4 - clicked() - lineDirsHide - clear() - - - 329 - 159 - - - 295 - 157 - - - - - diff --git a/project_fs/icons/utilities-terminal.png b/project_fs/icons/utilities-terminal.png deleted file mode 100644 index 9c8effecf8081f1926be0950aaa65f950d844f73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15685 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 PXh2;>N4ZqdCiwpVwSHFo diff --git a/project_fs/projectfilesystem.qrc b/project_fs/projectfilesystem.qrc deleted file mode 100644 index 2b5712f..0000000 --- a/project_fs/projectfilesystem.qrc +++ /dev/null @@ -1,6 +0,0 @@ - - - icons/edit-find.png - icons/utilities-terminal.png - - diff --git a/project_fs/projectfilesystemplugin.cpp b/project_fs/projectfilesystemplugin.cpp deleted file mode 100644 index 37b3c58..0000000 --- a/project_fs/projectfilesystemplugin.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "projectfilesystemplugin.h" -#include "projectfilesystempluginconstants.h" -#include "projectfilesystemwidget.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace ProjectFilesystemPlugin { - namespace Internal { - - ProjectFilesystemPluginPlugin::ProjectFilesystemPluginPlugin() - { - // Create your members - } - - ProjectFilesystemPluginPlugin::~ProjectFilesystemPluginPlugin() - { - // Unregister objects from the plugin manager's object pool - // Delete members - } - - bool ProjectFilesystemPluginPlugin::initialize(const QStringList &arguments, QString *errorString) - { - // Register objects in the plugin manager's object pool - // Load settings - // Add actions to menus - // Connect to other plugins' signals - // In the initialize function, a plugin can be sure that the plugins it - // depends on have initialized their members. - - Q_UNUSED(arguments) - Q_UNUSED(errorString) - - /*auto action = new QAction(tr("ProjectFilesystemPlugin Action"), this); - Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID, - Core::Context(Core::Constants::C_GLOBAL)); - cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A"))); - connect(action, &QAction::triggered, this, &ProjectFilesystemPluginPlugin::triggerAction); - - Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID); - menu->menu()->setTitle(tr("ProjectFilesystemPlugin")); - menu->addAction(cmd); - Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu); - - qDebug() << Core::IContext::widget();*/ - //addAutoReleasedObject(new ProjectFSWidgetFactory()); - (new ProjectFSWidgetFactory())->setParent(this); - - return true; - } - - void ProjectFilesystemPluginPlugin::extensionsInitialized() - { - Utils::globalMacroExpander()->registerPrefix("ProjectFilesystem", "Project filesystem plugin", [](QString v) -> QString {return v;} ); - Utils::globalMacroExpander()->registerFileVariables("ProjectFilesystem", "Selected item", - []() -> QString { return projectfs_menu_target.absoluteFilePath();}); - // Retrieve objects from the plugin manager's object pool - // In the extensionsInitialized function, a plugin can be sure that all - // plugins that depend on it are completely initialized. - } - - ExtensionSystem::IPlugin::ShutdownFlag ProjectFilesystemPluginPlugin::aboutToShutdown() - { - // Save settings - // Disconnect from signals that are not needed during shutdown - // Hide UI (if you add UI that is not in the main window directly) - return SynchronousShutdown; - } - - void ProjectFilesystemPluginPlugin::triggerAction() - { - QMessageBox::information(Core::ICore::mainWindow(), - tr("Action Triggered"), - tr("This is an action from ProjectFilesystemPlugin.")); - } - - } // namespace Internal -} // namespace ProjectFilesystemPlugin diff --git a/project_fs/projectfilesystemplugin.h b/project_fs/projectfilesystemplugin.h deleted file mode 100644 index 4262865..0000000 --- a/project_fs/projectfilesystemplugin.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "projectfilesystemplugin_global.h" -#include "projectfilesystemwidgetplugin.h" - -#include - -namespace ProjectFilesystemPlugin { - namespace Internal { - - class ProjectFilesystemPluginPlugin : public ExtensionSystem::IPlugin - { - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ProjectFilesystemPlugin.json") - - public: - ProjectFilesystemPluginPlugin(); - ~ProjectFilesystemPluginPlugin(); - - bool initialize(const QStringList &arguments, QString *errorString); - void extensionsInitialized(); - ShutdownFlag aboutToShutdown(); - - private: - void triggerAction(); - }; - - } // namespace Internal -} // namespace ProjectFilesystemPlugin diff --git a/project_fs/projectfilesystemplugin.pro b/project_fs/projectfilesystemplugin.pro deleted file mode 100644 index ec797d3..0000000 --- a/project_fs/projectfilesystemplugin.pro +++ /dev/null @@ -1,61 +0,0 @@ -DEFINES += PROJECTFILESYSTEMPLUGIN_LIBRARY - -# ProjectFilesystemPlugin files - -SOURCES += projectfilesystemplugin.cpp \ - projectfilesystemwidget.cpp \ - projectfilesystemwidgetplugin.cpp \ - filterdialog.cpp - -HEADERS += projectfilesystemplugin.h \ - projectfilesystemplugin_global.h \ - projectfilesystempluginconstants.h \ - projectfilesystemwidget.h \ - projectfilesystemwidgetplugin.h \ - filterdialog.h - -FORMS += \ - projectfilesystemwidget.ui \ - filterdialog.ui - -RESOURCES += \ - projectfilesystem.qrc - -#QT += network - -# Qt Creator linking - -## Either set the IDE_SOURCE_TREE when running qmake, -## or set the QTC_SOURCE environment variable, to override the default setting -isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(SDK_QTCREATOR_SRC) - -## Either set the IDE_BUILD_TREE when running qmake, -## or set the QTC_BUILD environment variable, to override the default setting -isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(SDK_QTCREATOR_BUILD) - -## uncomment to build plugin into user config directory -## /plugins/ -## where is e.g. -## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later -## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux -## "~/Library/Application Support/QtProject/Qt Creator" on OS X -#USE_USER_DESTDIR = yes - -###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to -###### _dependencies.pri, where is the name of the directory containing the -###### plugin's sources. - -QTC_PLUGIN_NAME = ProjectFilesystemPlugin -QTC_LIB_DEPENDS += \ - # nothing here at this time - -QTC_PLUGIN_DEPENDS += \ - coreplugin \ - projectexplorer - -QTC_PLUGIN_RECOMMENDS += \ - # optional plugin dependencies. nothing here at this time - -###### End _dependencies.pri contents ###### - -include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri) diff --git a/project_fs/projectfilesystemplugin_global.h b/project_fs/projectfilesystemplugin_global.h deleted file mode 100644 index f2e22e8..0000000 --- a/project_fs/projectfilesystemplugin_global.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include - -#if defined(PROJECTFILESYSTEMPLUGIN_LIBRARY) -# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_EXPORT -#else -# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_IMPORT -#endif diff --git a/project_fs/projectfilesystempluginconstants.h b/project_fs/projectfilesystempluginconstants.h deleted file mode 100644 index 2fb2893..0000000 --- a/project_fs/projectfilesystempluginconstants.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace ProjectFilesystemPlugin { - namespace Constants { - - const char ACTION_ID[] = "ProjectFilesystemPlugin.Action"; - const char MENU_ID[] = "ProjectFilesystemPlugin.Menu"; - - } // namespace ProjectFilesystemPlugin -} // namespace Constants diff --git a/project_fs/projectfilesystemwidget.cpp b/project_fs/projectfilesystemwidget.cpp deleted file mode 100644 index b858862..0000000 --- a/project_fs/projectfilesystemwidget.cpp +++ /dev/null @@ -1,328 +0,0 @@ -#include "projectfilesystemwidget.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QFileInfo projectfs_menu_target; - - -ProjectFilesystemWidget::ProjectFilesystemWidget(QWidget * parent): QWidget(parent) { - setupUi(this); - in_proc = need_rebuild = false; - int is = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this); - label->setFixedSize(is, is); - buttonClear->setIcon(Utils::Icons::CLEAN.icon()); - buttonExpand->setIcon(Utils::Icons::EXPAND.icon()); - buttonCollapse->setIcon(Utils::Icons::COLLAPSE.icon()); - actionOpen_here->setIcon(Utils::Icons::OPENFILE.icon()); - actionOpen_external->setIcon(Utils::Icons::OPENFILE.icon()); - actionShow_external->setIcon(Core::FileIconProvider::icon(QFileIconProvider::Folder)); - actionCopy_name->setIcon(Utils::Icons::COPY.icon()); - actionCopy_path->setIcon(Utils::Icons::COPY.icon()); - popup_menu.addActions(QList() << actionOpen_here << actionOpen_external << actionShow_external << actionOpen_terminal); - popup_menu.addSeparator(); - popup_menu.addActions(QList() << actionCopy_name << actionCopy_path); - proj_plug = 0; - //connect(ProjectExplorer::ProjectTree::instance(), SIGNAL(subtreeChanged(ProjectExplorer::FolderNode*)), this, SLOT(projectsChanged())); - connect(ProjectExplorer::SessionManager::instance(), SIGNAL(startupProjectChanged(ProjectExplorer::Project *)), this, SLOT(startupProjectChanged())); - connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(projectsChanged())); - connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)), this, SLOT(projectsChanged())); - connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(projectsChanged())); - //connect(ProjectExplorer::SessionManager::instance(), SIGNAL(), this, SLOT(startupProjectChanged())); - connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), this, SLOT(fileChanged())); - projectsChanged(); -} - - -void ProjectFilesystemWidget::setCurrentFilter(const FilterDialog::Filter & v) { - cur_filter = v; - projectsChanged(); -} - - -void ProjectFilesystemWidget::changeEvent(QEvent *e) { - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - retranslateUi(this); - break; - default: - break; - } -} - - -void ProjectFilesystemWidget::createTree(QTreeWidgetItem * ti, const QString & dir) { - QFileInfoList fl = QDir(dir).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::LocaleAware | QDir::DirsFirst); - checkProcEvents(); - for (QFileInfo i: fl) { - QString nit = i.fileName(); - if (i.isDir()) { - if (!cur_filter.filterDir(nit)) - continue; - } else { - if (!cur_filter.filterFile(nit)) - continue; - } - QTreeWidgetItem * ni = new QTreeWidgetItem(); - ni->setText(0, nit); - ni->setIcon(0, Core::FileIconProvider::icon(i)); - ni->setData(0, Qt::UserRole, i.absoluteFilePath()); - ni->setData(0, Qt::UserRole + 1, i.isDir()); - item_map[i.absoluteFilePath()] = ni; - if (i.isDir()) { - createTree(ni, dir + QDir::separator() + i.fileName()); - } - ti->addChild(ni); - } - //if (ti->childCount() == 0) delete ti; -} - - -bool ProjectFilesystemWidget::filterTree(QTreeWidgetItem * ti, const QString & filter) { - bool ret = false; - for (int i = 0; i < ti->childCount(); ++i) { - QTreeWidgetItem * ci = ti->child(i); - QString cit = ci->text(0); - if (ci->data(0, Qt::UserRole + 1).toBool()) { - if (!filterTree(ci, filter)) { - ci->setHidden(true); - continue; - } - ci->setHidden(false); - ret = true; - } else { - bool f = false; - if (filter.isEmpty()) { - f = true; - } else { - f = f || cit.contains(filter); - } - ci->setHidden(!f); - if (f) ret = true; - } - } - return ret; -} - - -void ProjectFilesystemWidget::filter() { - QString f = lineFilter->text(); - for (int i = 0; i < tree->topLevelItemCount(); ++i) { - QTreeWidgetItem * ti = tree->topLevelItem(i); - filterTree(ti, f); - } -} - - -void ProjectFilesystemWidget::rememberExpanded(QTreeWidgetItem * ti) { - //QMessageBox::information(0, ti->data(0, Qt::UserRole).toString(), QString::number(ti->childCount())); - for (int i = 0; i < ti->childCount(); ++i) { - QTreeWidgetItem * ci = ti->child(i); - if (ci->data(0, Qt::UserRole + 1).toBool()) { - if (ci->isExpanded()) - last_expanded << ci->data(0, Qt::UserRole).toString(); - rememberExpanded(ci); - } - } -} - - -void ProjectFilesystemWidget::restoreExpanded(QTreeWidgetItem * ti) { - for (int i = 0; i < ti->childCount(); ++i) { - QTreeWidgetItem * ci = ti->child(i); - if (ci->data(0, Qt::UserRole + 1).toBool()) { - if (last_expanded.contains(ci->data(0, Qt::UserRole).toString())) - ci->setExpanded(true); - restoreExpanded(ci); - } - } -} - - -void ProjectFilesystemWidget::setExtVariable() { -} - - -void ProjectFilesystemWidget::checkProcEvents() { - if (tm.elapsed() < 10) return; - QApplication::processEvents(); - tm.start(); -} - - -void ProjectFilesystemWidget::projectsChanged() { - if (in_proc) { - need_rebuild = true; - return; - } - in_proc = true; - tm.start(); - last_expanded.clear(); - item_map.clear(); - int spos = tree->verticalScrollBar()->value(); - rememberExpanded(tree->invisibleRootItem()); - tree->clear(); - QApplication::setOverrideCursor(Qt::WaitCursor); - QList pl = ProjectExplorer::SessionManager::projects(); - for (ProjectExplorer::Project * p: pl) { - QTreeWidgetItem * ri = new QTreeWidgetItem(); - QString dir = p->projectDirectory().toString(); - ri->setText(0, p->displayName()); - QFile logo(dir + "/logo.png"); - if (logo.exists()) - ri->setIcon(0, QIcon(logo.fileName())); - else - ri->setIcon(0, Core::FileIconProvider::icon(QFileIconProvider::Folder)); - ri->setData(0, Qt::UserRole, dir); - ri->setData(0, Qt::UserRole + 1, true); - createTree(ri, dir); - tree->addTopLevelItem(ri); - } - startupProjectChanged(); - fileChanged(); - filter(); - restoreExpanded(tree->invisibleRootItem()); - QApplication::restoreOverrideCursor(); - qApp->processEvents(); - tree->verticalScrollBar()->setValue(spos); - in_proc = false; - if (need_rebuild) { - need_rebuild = false; - projectsChanged(); - } -} - - -void ProjectFilesystemWidget::filterClicked() { - filter_dialog.setFilter(cur_filter); - if (filter_dialog.exec() == QDialog::Rejected) return; - setCurrentFilter(filter_dialog.filter()); -} - - -void ProjectFilesystemWidget::fileChanged() { - Core::IDocument * cd = Core::EditorManager::instance()->currentDocument(); - if (!cd) return; - QString np = cd->filePath().toString(); - QTreeWidgetItem * ti = item_map.value(np); - if (!ti) return; - tree->setCurrentItem(ti); - tree->expandItem(ti); -} - - -void ProjectFilesystemWidget::startupProjectChanged() { - ProjectExplorer::Project * sp = ProjectExplorer::SessionManager::startupProject(); - QFont f(tree->font()), bf(f); - bf.setBold(true); - for (int i = 0; i < tree->topLevelItemCount(); ++i) { - QTreeWidgetItem * ti = tree->topLevelItem(i); - ti->setFont(0, f); - if (!sp) continue; - if (sp->projectDirectory().toString() == ti->data(0, Qt::UserRole).toString()) - ti->setFont(0, bf); - } -} - - -void ProjectFilesystemWidget::on_tree_itemDoubleClicked(QTreeWidgetItem * item, int) { - if (!item) return; - QString afp = item->data(0, Qt::UserRole).toString(); - bool dir = item->data(0, Qt::UserRole + 1).toBool(); - if (dir) return; - if (afp.isEmpty()) return; - Core::EditorManager::openEditor(afp); -} - - -void ProjectFilesystemWidget::on_lineFilter_textChanged(const QString & ) { - filter(); -} - - -void ProjectFilesystemWidget::on_tree_itemClicked(QTreeWidgetItem * item, int column) { - projectfs_menu_target = QFileInfo(); - if (!item) { - setExtVariable(); - return; - } - projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString()); - setExtVariable(); -} - - -void ProjectFilesystemWidget::on_tree_customContextMenuRequested(const QPoint & pos) { - projectfs_menu_target = QFileInfo(); - QTreeWidgetItem * item = tree->itemAt(pos); - //QMessageBox::information(this, "", QString::number(index.row())); - if (!item) { - setExtVariable(); - return; - } - projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString()); - setExtVariable(); - actionOpen_here->setEnabled(!projectfs_menu_target.isDir()); - actionOpen_external->setEnabled(!projectfs_menu_target.isDir()); - popup_menu.popup(tree->mapToGlobal(pos)); -} - - -void ProjectFilesystemWidget::on_actionOpen_here_triggered() { - if (projectfs_menu_target.path().isEmpty()) return; - Core::EditorManager::openEditor(projectfs_menu_target.absoluteFilePath(), Core::Constants::K_DEFAULT_TEXT_EDITOR_ID); -} - - -void ProjectFilesystemWidget::on_actionOpen_external_triggered() { - if (projectfs_menu_target.path().isEmpty()) return; - QString wd = QDir::current().absolutePath(); - QDir::setCurrent(projectfs_menu_target.absoluteDir().path()); - QDesktopServices::openUrl(QUrl::fromLocalFile(projectfs_menu_target.absoluteFilePath())); - QDir::setCurrent(wd); -} - - -void ProjectFilesystemWidget::on_actionShow_external_triggered() { - if (projectfs_menu_target.path().isEmpty()) return; - Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), projectfs_menu_target.absoluteFilePath()); -} - - -void ProjectFilesystemWidget::on_actionOpen_terminal_triggered() { - if (projectfs_menu_target.path().isEmpty()) return; - Core::FileUtils::openTerminal(QDir(projectfs_menu_target.absoluteFilePath()).path()); -} - - -void ProjectFilesystemWidget::on_actionCopy_name_triggered() { - if (projectfs_menu_target.path().isEmpty()) return; - QApplication::clipboard()->setText(projectfs_menu_target.fileName()); -} - - -void ProjectFilesystemWidget::on_actionCopy_path_triggered() { - if (projectfs_menu_target.path().isEmpty()) return; - QApplication::clipboard()->setText(projectfs_menu_target.absoluteFilePath()); -} diff --git a/project_fs/projectfilesystemwidget.h b/project_fs/projectfilesystemwidget.h deleted file mode 100644 index 0832d95..0000000 --- a/project_fs/projectfilesystemwidget.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef PROJECTFILESYSTEMWIDGET_H -#define PROJECTFILESYSTEMWIDGET_H - -#include "ui_projectfilesystemwidget.h" -#include "filterdialog.h" -#include -#include -#include -#include -#include - -extern QFileInfo projectfs_menu_target; - -class ProjectsModel; - -class ProjectFilesystemWidget: public QWidget, private Ui::ProjectFilesystemWidget -{ - Q_OBJECT -public: - explicit ProjectFilesystemWidget(QWidget * parent = 0); - - FilterDialog::Filter currentFilters() const {return cur_filter;} - QString currentSearch() const {return lineFilter->text();} - - void setCurrentFilter(const FilterDialog::Filter & v); - void setCurrentSearch(QString v) {lineFilter->setText(v);} - -protected: - void changeEvent(QEvent * e); - void createTree(QTreeWidgetItem * ti, const QString & dir); - bool filterTree(QTreeWidgetItem * ti, const QString & filter); - void filter(); - void rememberExpanded(QTreeWidgetItem * ti); - void restoreExpanded(QTreeWidgetItem * ti); - void setExtVariable(); - void checkProcEvents(); - - bool in_proc, need_rebuild; - ExtensionSystem::IPlugin * proj_plug; - QMenu popup_menu; - QMap item_map; - QSet last_expanded; - FilterDialog filter_dialog; - FilterDialog::Filter cur_filter; - QElapsedTimer tm; - -public slots: - void projectsChanged(); - void filterClicked(); - -private slots: - void fileChanged(); - void startupProjectChanged(); - - void on_tree_itemDoubleClicked(QTreeWidgetItem * item, int ); - void on_lineFilter_textChanged(const QString &); - void on_tree_itemClicked(QTreeWidgetItem *item, int column); - void on_tree_customContextMenuRequested(const QPoint & pos); - void on_actionOpen_here_triggered(); - void on_actionOpen_external_triggered(); - void on_actionShow_external_triggered(); - void on_actionOpen_terminal_triggered(); - void on_actionCopy_name_triggered(); - void on_actionCopy_path_triggered(); - -}; - -#endif // PROJECTFILESYSTEMWIDGET_H diff --git a/project_fs/projectfilesystemwidget.ui b/project_fs/projectfilesystemwidget.ui deleted file mode 100644 index c05af68..0000000 --- a/project_fs/projectfilesystemwidget.ui +++ /dev/null @@ -1,183 +0,0 @@ - - - ProjectFilesystemWidget - - - - 0 - 0 - 386 - 390 - - - - - - - - - :/icons/edit-find.png - - - true - - - - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 20 - - - - - - - - Expand tree - - - - - - - Collapse tree - - - - - - - - - Qt::CustomContextMenu - - - QAbstractItemView::NoEditTriggers - - - Qt::ElideMiddle - - - QAbstractItemView::ScrollPerPixel - - - true - - - true - - - false - - - - Path - - - - - - - - Open as plain - - - - - Open external ... - - - - - Show external ... - - - - - Copy name - - - - - Copy path - - - - - - :/icons/utilities-terminal.png:/icons/utilities-terminal.png - - - Open terminal ... - - - - - - - - - buttonClear - clicked() - lineFilter - clear() - - - 246 - 37 - - - 212 - 35 - - - - - buttonExpand - clicked() - tree - expandAll() - - - 263 - 28 - - - 251 - 58 - - - - - buttonCollapse - clicked() - tree - collapseAll() - - - 307 - 27 - - - 297 - 71 - - - - - diff --git a/project_fs/projectfilesystemwidgetplugin.cpp b/project_fs/projectfilesystemwidgetplugin.cpp deleted file mode 100644 index 48f619c..0000000 --- a/project_fs/projectfilesystemwidgetplugin.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "projectfilesystemwidgetplugin.h" -#include "projectfilesystemwidget.h" -#include -#include -#include -#include - - -ProjectFSWidgetFactory::ProjectFSWidgetFactory() { - setDisplayName(QString::fromLatin1("Project filesystem")); - setId("project_filesystem"); -} - - -Core::NavigationView ProjectFSWidgetFactory::createWidget() { - Core::NavigationView view; - view.widget = new ProjectFilesystemWidget(); - QToolButton * btn = new QToolButton(); - btn->setIcon(Utils::Icons::RELOAD.icon()); - btn->setToolTip(tr("Reload tree")); - view.dockToolBarWidgets << btn; - connect(btn, SIGNAL(clicked()), view.widget, SLOT(projectsChanged())); - btn = new QToolButton(); - btn->setIcon(Utils::Icons::FILTER.icon()); - btn->setToolTip(tr("Setup filters ...")); - view.dockToolBarWidgets << btn; - connect(btn, SIGNAL(clicked()), view.widget, SLOT(filterClicked())); - return view; -} - - -void ProjectFSWidgetFactory::saveSettings(QSettings * settings, int position, QWidget * widget) { - //QMessageBox::information(0, "", QString::fromLatin1(widget->metaObject()->className())); - ProjectFilesystemWidget * w = qobject_cast(widget); - if (!w) return; - settings->beginGroup("ProjectFilesystem"); - settings->beginWriteArray("widget"); - settings->setArrayIndex(position); - settings->setValue("filters", w->currentFilters().toVariant()); - settings->setValue("search", w->currentSearch()); - settings->endArray(); - settings->endGroup(); - settings->sync(); -} - - -void ProjectFSWidgetFactory::restoreSettings(QSettings * settings, int position, QWidget * widget) { - ProjectFilesystemWidget * w = qobject_cast(widget); - if (!w) return; - settings->beginGroup("ProjectFilesystem"); - settings->beginReadArray("widget"); - settings->setArrayIndex(position); - w->setCurrentFilter(FilterDialog::Filter(settings->value("filters", FilterDialog::Filter().toVariant()))); - w->setCurrentSearch(settings->value("search", QString()).toString()); - settings->endArray(); - settings->endGroup(); -} diff --git a/project_fs/projectfilesystemwidgetplugin.h b/project_fs/projectfilesystemwidgetplugin.h deleted file mode 100644 index ccd652d..0000000 --- a/project_fs/projectfilesystemwidgetplugin.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include - - -class ProjectFSWidgetFactory: public Core::INavigationWidgetFactory -{ -public: - ProjectFSWidgetFactory(); - ~ProjectFSWidgetFactory() {} - - Core::NavigationView createWidget(); - - void saveSettings(QSettings * settings, int position, QWidget * widget); - void restoreSettings(QSettings * settings, int position, QWidget * widget); - -}; diff --git a/qad/CMakeLists.txt b/qad/CMakeLists.txt deleted file mode 100644 index 05f1d54..0000000 --- a/qad/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -cmake_policy(SET CMP0017 NEW) # need include() with .cmake -project(qad) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) - -if (NOT DEFINED ANDROID_PLATFORM) - find_package(OpenGL REQUIRED) -endif() -if (MINGW) - find_package(MinGW REQUIRED) -endif() - - -# Version -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h") - file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h") -endif() -#message(STATUS "Building QAD version ${QAD_VERSION} (${QAD_LIB_TYPE})") - -file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in") - -if (LIB) - install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules) - if (WIN32) - install(FILES ${QAD_VERSION_FILE} DESTINATION ${MINGW_INCLUDE}/qad) - else() - install(FILES ${QAD_VERSION_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qad) - endif() -else() - install(FILES ${QAD_VERSION_FILE} DESTINATION include/qad) -endif() - -add_subdirectory(libs) -if (UTILS) - add_subdirectory(utils) -endif() - -copy_to_parent(qad_includes) - diff --git a/qad/LICENSE.txt b/qad/LICENSE.txt deleted file mode 100644 index 0a04128..0000000 --- a/qad/LICENSE.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/qad/icons/edit-find.png b/qad/icons/edit-find.png deleted file mode 100644 index 140e58102a8c8325000261e28ec5122467132104..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43469 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 - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/qglengine/coeffs_brdf.png b/qglengine/coeffs_brdf.png deleted file mode 100644 index ec34d285dc6b032aeb6e469d9eb91ae8d8438449..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32788 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�m$5COulAtSlazvyA z%1R-r1KZrrJAJZj7w`cm;9-IaDV65If`<{{kV-ngoRu_Jk z@lXB<{Qjm^0oEnA=Mz%F@g(4LRQ>r&<1hR&W3-Mt%L;zvIKLlQkAC@0f05;^cmdhz$K^zYa2FK#tp{g*I;a6)$+&-=yW(eifmHvZwx(%+T*`!xhu z|NWo;tu{6vAF*=el;%^9d{|fISo^Qbzg=yQ_!fR4?Dxz0^*@MS|LdRs_5aKN^AFJm z`jh{+ZS;p}BYH9Y*$xjp@)=+tY_#q42l@YQgq{BEwC%LLPk2AxY5PN9`t$G4Kf$!6 zkKgB<50Zn#*Ks5daJ=NbN12`g{`|M?g!3SMx*az. -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "glbuffer.h" - - -Buffer::Buffer(GLenum target, GLenum _usage) { - target_ = target; - usage_ = _usage; - buffer_ = 0; - prev_size = 0; -} - - -Buffer::~Buffer() { -} - - -void Buffer::init(QOpenGLExtraFunctions * f) { - if (!isInit()) { - f->glGenBuffers(1, &buffer_); - } -} - - -void Buffer::destroy(QOpenGLExtraFunctions * f) { - if (buffer_ != 0) { - f->glDeleteBuffers(1, &buffer_); - } - buffer_ = 0; -} - - -void Buffer::bind(QOpenGLExtraFunctions * f) { - //qDebug() << "bind" << target_ << buffer_; - f->glBindBuffer(target_, buffer_); -} - - -void Buffer::release(QOpenGLExtraFunctions * f) { - f->glBindBuffer(target_, 0); -} - - -void * Buffer::map(QOpenGLExtraFunctions * f, GLbitfield mode, int size) { - if (size < 0) size = prev_size; - return f->glMapBufferRange(target_, 0, size, mode); -} - - -void Buffer::unmap(QOpenGLExtraFunctions * f) { - f->glUnmapBuffer(target_); -} - - -bool Buffer::resize(QOpenGLExtraFunctions * f, int new_size) { - if (new_size <= 0) return false; - //qDebug() << "check resize buffer" << buffer_ << "bytes" << new_size << ", old =" << prev_size; - if (new_size <= prev_size) return false; - prev_size = new_size; - //qDebug() << "resize buffer " << buffer_ << target_ << "for" << new_size << "bytes"; - f->glBufferData(target_, new_size, 0, usage_); - return true; -} - - -void Buffer::load(QOpenGLExtraFunctions * f, const void * data, int size, int offset) { - if (!data || size <= 0) return; - //qDebug() << "load buffer" << buffer_ << "bytes" << size; - f->glBufferSubData(target_, offset, size, data); -} diff --git a/qglengine/core/glbuffer.h b/qglengine/core/glbuffer.h deleted file mode 100644 index 2cf4c5f..0000000 --- a/qglengine/core/glbuffer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - QGL Buffer - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLBUFFER_H -#define GLBUFFER_H - -#include "gltypes.h" - - -class Buffer -{ - friend class ObjectBase; -public: - Buffer(GLenum target, GLenum usage = GL_DYNAMIC_DRAW); - ~Buffer(); - - void init (QOpenGLExtraFunctions * f); - void destroy (QOpenGLExtraFunctions * f); - - void bind (QOpenGLExtraFunctions * f); - void release (QOpenGLExtraFunctions * f); - void * map (QOpenGLExtraFunctions * f, GLbitfield mode, int size = -1); - void unmap (QOpenGLExtraFunctions * f); - - // returns true if size changed - bool resize (QOpenGLExtraFunctions * f, int new_size); - void load (QOpenGLExtraFunctions * f, const void * data, int size, int offset = 0); - - GLuint ID() const {return buffer_;} - GLenum usage() const {return usage_;} - GLenum target() const {return target_;} - void setTarget(GLenum t) {target_ = t;} - bool isInit() const {return buffer_ != 0;} - -private: - GLenum target_, usage_; - GLuint buffer_; - int prev_size; - -}; - - -#endif // GLBUFFER_H diff --git a/qglengine/core/glcubemap.cpp b/qglengine/core/glcubemap.cpp deleted file mode 100644 index 19b8750..0000000 --- a/qglengine/core/glcubemap.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - QGL CubeTexture - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "gltypes.h" -#include "glcubemap.h" -#include "hdr_p.h" - -using namespace QGLEngineShaders; - - -QVector loadFileHDR(const QString & path, QSize * size) { - if (size) *size = QSize(); - QVector ret; - QFile f(path); - if (!f.open(QIODevice::ReadOnly)) { - qDebug() << "[QGLEngine] Can`t open" << path; - return ret; - } - QTextStream ts(&f); - QString line = ts.readLine(256); - if (line != "#?RADIANCE") return ret; - QSize sz; - while (!ts.atEnd()) { - line = ts.readLine(256); - if (line.startsWith("FORMAT")) { - line.remove(0, 7); - if (!line.startsWith("32-bit")) { - qDebug() << "[QGLEngine] File" << path << "has unknown format!"; - return ret; - } - } - if (line.mid(1, 2) == "Y ") { - QStringList sl = line.trimmed().split(" "); - sl.removeAll(""); - if (sl.size() != 4) { - qDebug() << "[QGLEngine] File" << path << "has unknown size!"; - return ret; - } - sz.setWidth (sl[3].toInt()); - sz.setHeight(sl[1].toInt()); - //qDebug() << "found size" << sz; - break; - } - } - if (sz.isEmpty()) return ret; - f.seek(ts.pos()); - QDataStream ds(&f); - int count = sz.width() * sz.height(); - QVector data(count*3); - if (!RGBE_ReadPixels_RLE(&ds, data.data(), sz.width(), sz.height())) - return ret; - - if (size) *size = sz; - ret.resize(count); - //QColor col; - //QImage im(sz, QImage::Format_ARGB32); - //QRgb * imdata = (QRgb*)im.bits(); - for (int i = 0; i < count; ++i) { - QVector3D p(pow(data[i*3 + 2], 1. / 2.2), - pow(data[i*3 + 1], 1. / 2.2), - pow(data[i*3 + 0], 1. / 2.2)); - ret[i] = p; - //col = QColor::fromRgbF(piClamp(p[0], 0.f, 1.f), - // piClamp(p[1], 0.f, 1.f), - // piClamp(p[2], 0.f, 1.f)); - //imdata[i] = col.rgb(); - } - //im.save("_hdr.png"); - - return ret; -} - - -//#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -QVector faceHDR(const QVector & data, QSize sz, QSize & fsz, int face) { - QVector ret; - if (data.isEmpty() || sz.isNull()) return ret; - QRect fr; - int fw = sz.width () / 4; - int fh = sz.height() / 3; - fsz = QSize(fw, fh); - ret.reserve(fw * fh); - switch (face) { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - fr.setRect(fw, fh, fw, fh); - for (int x = fr.left(); x <= fr.right(); ++x) { - for (int y = fr.top(); y <= fr.bottom(); ++y) { - ret << data[y*sz.width() + x]; - } - } - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - fr.setRect(fw*3, fh, fw, fh); - for (int x = fr.right(); x >= fr.left(); --x) { - for (int y = fr.bottom(); y >= fr.top(); --y) { - ret << data[y*sz.width() + x]; - } - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - fr.setRect( 0, fh, fw, fh); - for (int y = fr.bottom(); y >= fr.top(); --y) { - for (int x = fr.left(); x <= fr.right(); ++x) { - ret << data[y*sz.width() + x]; - } - } - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - fr.setRect(fw*2, fh, fw, fh); - for (int y = fr.top(); y <= fr.bottom(); ++y) { - for (int x = fr.right(); x >= fr.left(); --x) { - ret << data[y*sz.width() + x]; - } - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - fr.setRect(fw, 0, fw, fh); - for (int x = fr.left(); x <= fr.right(); ++x) { - for (int y = fr.top(); y <= fr.bottom(); ++y) { - ret << data[y*sz.width() + x]; - } - } - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - fr.setRect(fw, fh*2, fw, fh); - for (int x = fr.left(); x <= fr.right(); ++x) { - for (int y = fr.top(); y <= fr.bottom(); ++y) { - ret << data[y*sz.width() + x]; - } - } - break; - default: break; - } - if (fr.isEmpty()) return ret; - //qDebug() << ret.size() << fr; - return ret; -} - - - -CubeTexture::CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format): f(f_) { - size = _size; - format_ = _format; - id_ = 0; - changed_ = false; -} - - -bool CubeTexture::init() { - if (isInit()) return true; - f->glGenTextures(1, &id_); - f->glBindTexture(GL_TEXTURE_CUBE_MAP, id_); - f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - f->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); - //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - //glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - //glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - //glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - changed_ = false; - return id_ > 0; -} - - -void CubeTexture::destroy() { - if (!isInit()) return; - f->glDeleteTextures(1, &id_); - id_ = 0; -} - - -void CubeTexture::bind(int channel) { - init(); - f->glActiveTexture(GL_TEXTURE0 + channel); - f->glBindTexture(GL_TEXTURE_CUBE_MAP, id_); -} - - -void CubeTexture::release() { - f->glBindTexture(GL_TEXTURE_CUBE_MAP, 0); -} - - -void CubeTexture::loadHDR(const QVector & data, QSize sz) { - bind(); - QSize fsz; - QVector fd; - for (int i = 0; i < 6; ++i) { - fd = faceHDR(data, sz, fsz, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i); - //qDebug() << "load cube" << fd[0]; - //f->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - f->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format_, fsz.width(), fsz.height(), 0, GL_RGB, GL_FLOAT, fd.isEmpty() ? 0 : fd.constData()); - //qDebug() << QString::number(GetLastError(), 16); - } - f->glGenerateMipmap(GL_TEXTURE_CUBE_MAP); -} - - -void CubeTexture::setFileHDR(const QString & path) { - hdr_path = path; - changed_ = true; -} - - -void CubeTexture::load() { - if (!changed_) return; - init(); - if (!hdr_path.isEmpty()) { - QSize sz; - QVector data = loadFileHDR(hdr_path, &sz); - loadHDR(data, sz); - } else { - destroy(); - bind(); - for (int i = 0; i < 6; ++i) { - f->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format_, 1, 1, 0, GL_RGB, GL_FLOAT, 0); - } - f->glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - } - changed_ = false; -} - -/* -void CubeTexture::load() { - if (isEmpty()) return; - create(); - if (!path(0).isEmpty()) loadFront(path(0)); - if (!path(1).isEmpty()) loadBack(path(1)); - if (!path(2).isEmpty()) loadLeft(path(2)); - if (!path(3).isEmpty()) loadRight(path(3)); - if (!path(4).isEmpty()) loadTop(path(4)); - if (!path(5).isEmpty()) loadBottom(path(5)); -} - - -void CubeTexture::loadFromDirectory(const QString & dir) { - QDir d(dir); QFileInfoList sl; - sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadFront(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBack(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadLeft(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadRight(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadTop(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBottom(sl[0].absoluteFilePath()); -} - - -void CubeTexture::loadPathesFromDirectory(const QString & dir) { - QDir d(dir); QFileInfoList sl; - sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[0] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[1] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[2] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[3] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[4] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[5] = sl[0].absoluteFilePath(); -} -*/ diff --git a/qglengine/core/glcubemap.h b/qglengine/core/glcubemap.h deleted file mode 100644 index 6f5ed5d..0000000 --- a/qglengine/core/glcubemap.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - QGL CubeTexture - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLCUBEMAP_H -#define GLCUBEMAP_H - -#include "glshaders_types.h" -#include "chunkstream.h" - -QVector loadFileHDR(const QString & path, QSize * size = 0); - -class CubeTexture { -public: - CubeTexture(QOpenGLExtraFunctions * f_, int _size, const GLenum & _format = GL_RGB16F); - bool init(); - void destroy(); - void bind(int channel = 0); - void release(); - void resize(int _size) {size = _size; changed_ = true;} - void loadHDR(const QVector & data, QSize sz); - void setFileHDR(const QString & path); - QString fileHDR() const {return hdr_path;} - //void loadFromDirectory(const QString & dir); - //void loadFront(const QString & path) {bind(); pathes[0] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_X);} - //void loadBack(const QString & path) {bind(); pathes[1] = path; createGLTexture(id_, rotateQImageRight(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);} - //void loadLeft(const QString & path) {bind(); pathes[2] = path; createGLTexture(id_, QImage(path).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);} - //void loadRight(const QString & path) {bind(); pathes[3] = path; createGLTexture(id_, rotateQImage180(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);} - //void loadTop(const QString & path) {bind(); pathes[4] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);} - //void loadBottom(const QString & path) {bind(); pathes[5] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);} - //void load(); - //bool isEmpty() const {foreach (const QString & i, pathes) if (!i.isEmpty()) return false; return true;} - GLenum format() const {return format_;} - void setFormat(GLenum f) {format_ = f; changed_ = true;} - GLuint id() const {return id_;} - bool isInit() const {return id_ != 0;} - //const QString & path(int side) const {return pathes[side];} - //void setPath(int side, const QString & p) {pathes[side] = p;} - //void loadPathesFromDirectory(const QString & dir); - void load(); -private: - - QOpenGLExtraFunctions * f; - bool changed_; - int size; - GLenum format_; - GLuint id_; - QString hdr_path; - //QVector pathes; -}; - - -#endif // GLCUBEMAP_H diff --git a/qglengine/core/glframebuffer.cpp b/qglengine/core/glframebuffer.cpp deleted file mode 100644 index 88e5c92..0000000 --- a/qglengine/core/glframebuffer.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* - QGL Framebuffer - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include -#include "glframebuffer.h" -#include - - -Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, int colorAttachments_, bool withDepth, GLenum colorFormat_, GLenum _target): f(f_), - pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) { - is_depth = withDepth; - target_ = _target; - color_formats.fill(colorFormat_, colorAttachments_); - colors.fill(0, colorAttachments_); - fbo = drbo = 0; - tex_d = 0; - wid = hei = 0; - pbo_queried = 0; - is_changed = false; -} - - -Framebuffer::Framebuffer(QOpenGLExtraFunctions * f_, QVector colors_, bool withDepth, GLenum _target): f(f_), - pbo(GL_PIXEL_PACK_BUFFER, GL_STREAM_DRAW) { - is_depth = withDepth; - target_ = _target; - color_formats = colors_; - colors.fill(0, colors_.size()); - fbo = drbo = 0; - tex_d = 0; - wid = hei = 0; - pbo_queried = 0; - is_changed = false; -} - - -Framebuffer::~Framebuffer() { - deleteGLFramebuffer(fbo); - deleteGLRenderbuffer(drbo); - for (int i = 0; i < colors.size(); ++i) - deleteGLTexture(f, colors[i]); - deleteGLTexture(f, tex_d); -} - - -void Framebuffer::resize(int width, int height, bool force) { - if ((wid == width) && (hei == height) && !force) return; - wid = width; - hei = height; - deleteGLFramebuffer(fbo); - f->glGenFramebuffers(1, &fbo); - f->glBindFramebuffer(GL_FRAMEBUFFER, fbo); - for (int i = 0; i < colors.size(); ++i) { - deleteGLTexture(f, colors[i]); - createGLTexture(f, colors[i], width, height, color_formats[i], target_); - f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - f->glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, 4); - //f->glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); - f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0); - } - if (is_depth) { - deleteGLTexture(f, tex_d); - deleteGLRenderbuffer(drbo); - f->glGenRenderbuffers(1, &drbo); - f->glBindRenderbuffer(GL_RENDERBUFFER, drbo); - f->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); - f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, drbo); - createGLTexture(f, tex_d, width, height, GL_DEPTH_COMPONENT); - f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - //f->glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); - f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target_, tex_d, 0); - } - f->glBindFramebuffer(GL_FRAMEBUFFER, 0); - if (pbo.isInit()) { - enablePixelBuffer(); - } - is_changed = false; -} - - -QImage Framebuffer::grab() const { - return QImage(); -} - - -void Framebuffer::queryPoint(int index, QPoint p) { - pbo_queried = 0; - if (index < 0 || index >= colors.size()) return; - if (!rect().contains(p) || !pbo.isInit()) return; - f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index); - pbo.bind(f); - f->glReadPixels(p.x(), height() - p.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0); - pbo_queried = 1; - pbo.release(f); -} - - -void Framebuffer::queryPoints(int index, QRect rect_, GLenum pixel_format) { - pbo_queried = 0; - if (index < 0 || index >= colors.size()) return; - rect_ &= rect(); - if (rect_.isEmpty() || !pbo.isInit()) return; - f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index); - pbo.bind(f); - f->glReadPixels(rect_.x(), height() - rect_.bottom(), rect_.width(), rect_.height(), GL_RGBA, pixel_format, 0); - pbo_queried = rect_.width() * rect_.height(); - pbo.release(f); -} - - -void Framebuffer::queryImage(int index) { - queryPoints(index, rect()); -} - - -uint Framebuffer::getPoint() const { - if (!pbo.isInit() || (pbo_queried == 0)) return 0; - uint ret = 0; - pbo.bind(f); - void * map = pbo.map(f, GL_MAP_READ_BIT, sizeof(uint)); - if (map) - memcpy(&ret, map, sizeof(uint)); - pbo.unmap(f); - pbo.release(f); - return ret; -} - - -QVector Framebuffer::getPointsByte() const { - QVector ret; - if (!pbo.isInit() || (pbo_queried == 0)) return ret; - ret.resize(pbo_queried); - pbo.bind(f); - void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(uint)); - if (map) - memcpy(ret.data(), map, pbo_queried * sizeof(uint)); - pbo.unmap(f); - pbo.release(f); - return ret; -} - - -QVector Framebuffer::getPointsFloat() const { - QVector ret; - if (!pbo.isInit() || (pbo_queried == 0)) return ret; - ret.resize(pbo_queried); - pbo.bind(f); - void * map = pbo.map(f, GL_MAP_READ_BIT, pbo_queried * sizeof(QVector4D)); - if (map) - memcpy(ret.data(), map, pbo_queried * sizeof(QVector4D)); - pbo.unmap(f); - pbo.release(f); - return ret; -} - - -QImage Framebuffer::getImage() const { - QImage ret; - if (!pbo.isInit() || (pbo_queried == 0)) return ret; - ret = QImage(size(), QImage::Format_RGBA8888); - int bytes = width() * height() * 4; - pbo.bind(f); - void * map = pbo.map(f, GL_MAP_READ_BIT, bytes); - if (map) - memcpy(ret.bits(), map, bytes); - pbo.unmap(f); - pbo.release(f); - return ret; -} - - -QVector Framebuffer::grabF(int index) const { - QVector ret; - if (index < 0 || index >= colors.size()) return ret; - f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index); - ret.resize(wid * hei * 4); - f->glReadPixels(0, 0, wid, hei, GL_RGBA, GL_FLOAT, ret.data()); - return ret; -} - - -void Framebuffer::blit(int index_from, GLuint fb_to, int index_to, QRect from, QRect to, GLbitfield mask, GLenum filter) const { - if (index_from < 0 || index_from >= colors.size()) return; - GLenum e = GL_COLOR_ATTACHMENT0 + index_to; - f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_to); - f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); - f->glReadBuffer(GL_COLOR_ATTACHMENT0 + index_from); - f->glDrawBuffers(1, &e); - f->glBlitFramebuffer(from.x(), from.y(), from.right(), from.bottom(), to.x(), to.y(), to.right(), to.bottom(), mask, filter); -} - - -void Framebuffer::bind() { - if (is_changed) resize(wid, hei); - if (fbo == 0) return; - f->glGetIntegerv(GL_VIEWPORT, prev_view); - f->glBindFramebuffer(GL_FRAMEBUFFER, fbo); - setWriteBuffers(); - f->glReadBuffer(GL_COLOR_ATTACHMENT0); - f->glViewport(0, 0, wid, hei); -} - - -void Framebuffer::release() { - is_changed = false; - if (fbo == 0) return; - f->glBindFramebuffer(GL_FRAMEBUFFER, 0); - f->glViewport(prev_view[0], prev_view[1], prev_view[2], prev_view[3]); -} - - -void Framebuffer::setWriteBuffer(int index) { - unsetWriteBuffers(); - GLenum e = GL_COLOR_ATTACHMENT0 + index; - f->glDrawBuffers(1, &e); -} - - -void Framebuffer::setWriteBuffers(const int * indeces, int count) { - unsetWriteBuffers(); - QVector buffers; - for (int i = 0; i < count; ++i) - buffers << GL_COLOR_ATTACHMENT0 + indeces[i]; - f->glDrawBuffers(buffers.size(), buffers.constData()); -} - - -void Framebuffer::setWriteBuffers() { - QVector buffers; - for (int i = 0; i < colors.size(); ++i) - buffers << GL_COLOR_ATTACHMENT0 + i; - f->glDrawBuffers(buffers.size(), buffers.constData()); -} - - -void Framebuffer::unsetWriteBuffers() { - QVector buffers(colors.size(), GL_NONE); - f->glDrawBuffers(buffers.size(), buffers.constData()); -} - - -void Framebuffer::enablePixelBuffer() { - pbo.init(f); - pbo.bind(f); - pbo.resize(f, width()*height()*4*4); - pbo.release(f); -} - - -void Framebuffer::setColorTextureFiltering(int index, GLenum filter) { - bindColorTexture(index); - f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, filter); - f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, filter); -} - - -void Framebuffer::bindColorTexture(int index, int channel) { - if (index < 0 || index >= colors.size()) return; - f->glActiveTexture(GL_TEXTURE0 + channel); - f->glBindTexture(GL_TEXTURE_2D, colors[index]); -} - - -void Framebuffer::bindColorTextures() { - for (int i = colors.size() - 1; i >= 0; --i) { - f->glActiveTexture(GL_TEXTURE0 + i); - f->glBindTexture(GL_TEXTURE_2D, colors[i]); - //f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - //f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } -} - - -void Framebuffer::bindDepthTexture(int channel) { - f->glActiveTexture(GL_TEXTURE0 + channel); - f->glBindTexture(GL_TEXTURE_2D, tex_d); -} - - -void Framebuffer::deleteGLRenderbuffer(GLuint & drbo) { - if (drbo != 0) - f->glDeleteRenderbuffers(1, &drbo); - drbo = 0; -} - - -void Framebuffer::deleteGLFramebuffer(GLuint & fbo) { - if (fbo != 0) - f->glDeleteFramebuffers(1, &fbo); - fbo = 0; -} diff --git a/qglengine/core/glframebuffer.h b/qglengine/core/glframebuffer.h deleted file mode 100644 index cc6549e..0000000 --- a/qglengine/core/glframebuffer.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - QGL Framebuffer - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLFRAMEBUFFER_H -#define GLFRAMEBUFFER_H - -#include "glbuffer.h" - - -class Framebuffer -{ - friend class FramebufferMipmap; -public: - Framebuffer(QOpenGLExtraFunctions * f_, int colorAttachments = 1, bool withDepth = true, GLenum colorFormat = GL_RGBA8, GLenum _target = GL_TEXTURE_2D); - Framebuffer(QOpenGLExtraFunctions * f_, QVector colors_, bool withDepth = true, GLenum _target = GL_TEXTURE_2D); - virtual ~Framebuffer(); - - GLuint id() const {return fbo;} - GLuint colorTexture(int index = 0) const {return colors[index];} - //GLenum colorFormat() const {return color_format;} - GLuint depthTexture() const {return tex_d;} - GLenum target() const {return target_;} - bool isInit() const {return fbo != 0;} - int width() const {return wid;} - int height() const {return hei;} - QSize size() const {return QSize(wid, hei);} - QRect rect() const {return QRect(0, 0, wid, hei);} - QImage grab() const; - QVector grabF(int index) const; - void queryPoint(int index, QPoint p); - void queryPoints(int index, QRect rect, GLenum pixel_format = GL_UNSIGNED_BYTE); - void queryImage(int index); - uint getPoint() const; - QVector getPointsByte() const; - QVector getPointsFloat() const; - QImage getImage() const; - int queriedPoints() const {return pbo_queried;} - void blit(int index_from, GLuint fb_to, int index_to, QRect from, QRect to, GLbitfield mask = GL_COLOR_BUFFER_BIT, GLenum filter = GL_NEAREST) const; - - void resize(int width, int height, bool force = false); - void bind(); - void release(); - void setReadBuffer(int index) {glReadBuffer(GL_COLOR_ATTACHMENT0 + index);} - void setWriteBuffer(int index); - void setWriteBuffers(const int * indeces, int count); - void setWriteBuffers(const QVector & indeces) {setWriteBuffers(indeces.constData(), indeces.size());} - void setWriteBuffers(); - void unsetWriteBuffers(); - //void setColorFormat(GLenum format) {color_format = format; is_changed = true;} - void enablePixelBuffer(); - void setColorTextureFiltering(int index, GLenum filter); - - void copyDepthFrom(GLuint tex) {;} - void bindColorTexture(int index, int channel = 0); - void bindColorTextures(); - void bindDepthTexture(int channel); - -private: - void deleteGLRenderbuffer(GLuint & drbo); - void deleteGLFramebuffer(GLuint & fbo); - - bool is_depth, is_changed; - int pbo_queried; - QOpenGLExtraFunctions * f; - mutable Buffer pbo; - QVector colors; - QVector color_formats; - GLenum target_; - GLuint fbo, drbo, tex_d; - GLint prev_view[4], wid, hei; - -}; - -#endif // GLFRAMEBUFFER_H diff --git a/qglengine/core/glframebuffer_mipmap.cpp b/qglengine/core/glframebuffer_mipmap.cpp deleted file mode 100644 index 6a38962..0000000 --- a/qglengine/core/glframebuffer_mipmap.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - QGL FramebufferMipmap - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include -#include "glframebuffer_mipmap.h" -#include - - -FramebufferMipmap::FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels): src_fb(fb) { - index_from = index_from_; - for (int i = 0; i < levels; ++i) - fbo << new Framebuffer(fb.f, 1, false, fb.color_formats[index_from]); -} - - -FramebufferMipmap::~FramebufferMipmap() { - -} - - -void FramebufferMipmap::resize() { - QSize sz = src_fb.size(); - for (int i = 0; i < fbo.size(); ++i) { - sz /= 2; - fbo[i]->resize(sz.width(), sz.height()); - } -} - - -void FramebufferMipmap::create() { - if (fbo.isEmpty()) return; - src_fb.blit(index_from, fbo[0]->id(), 0, src_fb.rect(), fbo[0]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR); - for (int i = 0; i < fbo.size() - 1; ++i) - fbo[i]->blit(0, fbo[i + 1]->id(), 0, fbo[i]->rect(), fbo[i + 1]->rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR); -} diff --git a/qglengine/core/glframebuffer_mipmap.h b/qglengine/core/glframebuffer_mipmap.h deleted file mode 100644 index 1bd9781..0000000 --- a/qglengine/core/glframebuffer_mipmap.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - QGL FramebufferMipmap - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLFRAMEBUFFER_MIPMAP_H -#define GLFRAMEBUFFER_MIPMAP_H - -#include "glframebuffer.h" - - -class FramebufferMipmap -{ -public: - FramebufferMipmap(const Framebuffer & fb, int index_from_, int levels = 2); - virtual ~FramebufferMipmap(); - - int levelsCount() const {return fbo.size();} - int lastLevel() const {return fbo.size() - 1;} - Framebuffer & plane(int level) {return *fbo[level];} - Framebuffer & lastPlane() {return *fbo[lastLevel()];} - int width (int level) const {return fbo[level]->wid;} - int height(int level) const {return fbo[level]->hei;} - QSize size(int level) const {return fbo[level]->size();} - QRect rect(int level) const {return fbo[level]->rect();} - - void resize(); - void create(); - -private: - int index_from; - const Framebuffer & src_fb; - QVector fbo; - -}; - -#endif // GLFRAMEBUFFER_MIPMAP_H diff --git a/qglengine/core/glmaterial.cpp b/qglengine/core/glmaterial.cpp deleted file mode 100644 index 7afb341..0000000 --- a/qglengine/core/glmaterial.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - QGL Material - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "gltypes.h" -#include "gltexture_manager.h" -#include "qglview.h" - -using namespace QGLEngineShaders; - - -Map::Map() { - bitmap_id = 0; - color_amount = 1.f; - color_offset = 0.f; - bitmap_scale = QPointF(1., 1.); - use_bitmap = false; - _changed = true; - _layer = 0; -} - - -void Map::setBitmapPath(const QString & p) { - bitmap_path = p; - _changed = true; -} - - -void Map::load(TextureManager * tm) { - if (bitmap_id == 0) - bitmap_id = tm->loadTexture(bitmap_path, true, _type == mtNormal); -} - - -void Map::copyToQGLMap(QGLMap & m) const { - m.amount = color_amount; - m.offset = color_offset; - m.scale = QVector2D(bitmap_scale); - if (hasBitmap() && use_bitmap) { - m.array_index = tarMaps; - m.map_index = _layer; - } else { - m.array_index = tarEmpty; - m.map_index = (_type == mtNormal ? emrBlue : emrWhite); - } -} - - - - -Material::Material(const QString _name)/*: map_reflection(512)*/ { - setTypes(); - name = _name; - color_diffuse = Qt::white; - color_emission = Qt::black; - glass = false; - transparency = reflectivity = 0.f; - map_roughness.color_amount = 0.75f; - map_metalness.color_amount = 0.25f; - iof = 1.f; - dispersion = 0.05f; - _changed = true; - _index = 0; -} - - -uint Material::hash() { - return qHash(name); -} - - -bool Material::hasTransparency() const { - return float(color_diffuse.alphaF()) * (1.f - transparency) < 1.f; -} - - -bool Material::isMapsChanged() const { - return map_diffuse ._changed || - map_normal ._changed || - map_metalness._changed || - map_roughness._changed || - map_emission ._changed || - map_relief ._changed; -} - - -bool Material::isMapChanged(int type) const { - switch (type) { - case mtDiffuse : return map_diffuse ._changed; - case mtNormal : return map_normal ._changed; - case mtMetalness: return map_metalness._changed; - case mtRoughness: return map_roughness._changed; - case mtEmission : return map_emission ._changed; - case mtRelief : return map_relief ._changed; - } - return false; -} - - -void Material::load(TextureManager * tm) { - map_diffuse .load(tm); - map_normal .load(tm); - map_metalness.load(tm); - map_roughness.load(tm); - map_emission .load(tm); - map_relief .load(tm); -} - - -void Material::setMapsChanged() { - map_diffuse ._changed = true; - map_normal ._changed = true; - map_metalness._changed = true; - map_roughness._changed = true; - map_emission ._changed = true; - map_relief ._changed = true; -} - - -void Material::setTypes() { - map_diffuse ._type = mtDiffuse ; - map_normal ._type = mtNormal ; - map_metalness._type = mtMetalness; - map_roughness._type = mtRoughness; - map_emission ._type = mtEmission ; - map_relief ._type = mtRelief ; -} - - -void Material::detectMaps() { - map_diffuse .use_bitmap = !map_diffuse .bitmap_path.isEmpty(); - map_normal .use_bitmap = !map_normal .bitmap_path.isEmpty(); - map_metalness.use_bitmap = !map_metalness.bitmap_path.isEmpty(); - map_roughness.use_bitmap = !map_roughness.bitmap_path.isEmpty(); - map_emission .use_bitmap = !map_emission .bitmap_path.isEmpty(); - map_relief .use_bitmap = !map_relief .bitmap_path.isEmpty(); -} diff --git a/qglengine/core/glmaterial.h b/qglengine/core/glmaterial.h deleted file mode 100644 index 661d3dc..0000000 --- a/qglengine/core/glmaterial.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - QGL Material - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLMATERIAL_H -#define GLMATERIAL_H - -#include "glshaders_types.h" -#include "chunkstream.h" - - -class Map { -public: - Map(); - void setBitmapPath(const QString & p); - void clearBitmap() {setBitmapPath(QString());} - bool hasBitmap() const {return !bitmap_path.isEmpty();} - void load(TextureManager * tm); - void copyToQGLMap(QGLEngineShaders::QGLMap & m) const; - QString bitmap_path; - GLuint bitmap_id; - QPointF bitmap_offset; - QPointF bitmap_scale; - float color_amount; - float color_offset; - bool use_bitmap; - - bool _changed; - int _type, _layer; -}; - -class Material { -public: - Material(const QString _name = QString()); - uint hash(); - bool hasTransparency() const; - bool isMapsChanged() const; - bool isMapChanged(int type) const; - void load(TextureManager * tm); - void setMapsChanged(); - void setTypes(); - void detectMaps(); - QString name; - QColor color_diffuse; - QColor color_emission; - bool glass; - float transparency; - float reflectivity; - float iof; - float dispersion; - Map map_diffuse ; - Map map_normal ; - Map map_metalness; - Map map_roughness; - Map map_emission ; - Map map_relief ; - bool _changed; - int _index; - //GLCubeTexture map_reflection; -}; - - -inline QDataStream & operator <<(QDataStream & s, const Map & m) { - ChunkStream cs; - cs.add(1, m.bitmap_path).add(2, m.color_amount).add(3, m.color_offset).add(6, m.bitmap_scale) - .add(7, m.use_bitmap); - s << cs.data(); return s; -} -inline QDataStream & operator >>(QDataStream & s, Map & m) { - ChunkStream cs(s); - cs.readAll(); - cs.get(1, m.bitmap_path).get(2, m.color_amount).get(3, m.color_offset).get(6, m.bitmap_scale) - .get(7, m.use_bitmap); - return s; -} - -inline QDataStream & operator <<(QDataStream & s, const Material * m) { - ChunkStream cs; - cs.add(1, m->name).add(2, m->color_diffuse).add(4, m->color_emission) - .add(5, m->transparency).add(6, m->reflectivity).add(7, m->glass).add(8, m->map_diffuse).add(9, m->map_normal) - .add(10, m->map_relief).add(11, m->map_metalness).add(12, m->map_roughness).add(13, m->map_emission); - s << /*qCompress*/(cs.data()); return s; -} -inline QDataStream & operator >>(QDataStream & s, Material *& m) { - m = new Material(); - //QByteArray ba; - //s >> ba; - //ba = qUncompres(ba); - ChunkStream cs(s); - while (!cs.atEnd()) { - switch (cs.read()) { - case 1: cs.get(m->name); break; - case 2: cs.get(m->color_diffuse); break; - case 4: cs.get(m->color_emission); break; - case 5: cs.get(m->transparency); break; - case 6: cs.get(m->reflectivity); break; - case 7: cs.get(m->glass); break; - case 8: cs.get(m->map_diffuse); break; - case 9: cs.get(m->map_normal); break; - case 10: cs.get(m->map_relief); break; - case 11: cs.get(m->map_metalness); break; - case 12: cs.get(m->map_roughness); break; - case 13: cs.get(m->map_emission); break; - } - } - m->setTypes(); - return s; -} - -#endif // GLMATERIAL_H diff --git a/qglengine/core/glmesh.cpp b/qglengine/core/glmesh.cpp deleted file mode 100644 index 1b2079d..0000000 --- a/qglengine/core/glmesh.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* - QGL Mesh - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "glmesh.h" -#include "globject.h" -#include - -using namespace QGLEngineShaders; - -//static int _count = 0; - -Mesh::Mesh(GLenum geom_type_): geom_type(geom_type_), - buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW), - buffer_ind (GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW) { - hash_ = 0; - changed = hash_changed = true; - //qDebug() << "Mesh, now" << ++_count; -} - - -Mesh::~Mesh() { - //qDebug() << "~Mesh, now" << --_count; - //destroy(); -} - - -Mesh * Mesh::clone() { - Mesh * c = new Mesh(); - c->vertices_ = vertices_ ; - c->normals_ = normals_ ; - c->texcoords_ = texcoords_; - c->triangles_ = triangles_; - c->lines_ = lines_; - c->geom_type = geom_type; - c->hash_ = hash_; - c->hash_changed = hash_changed; - //qDebug() << "clone VBO"; - return c; -} - - -void Mesh::init(QOpenGLExtraFunctions * f) { - if (!isInit()) { - buffer_geom.init(f); - buffer_ind .init(f); - changed = true; - } -} - - -void Mesh::destroy(QOpenGLExtraFunctions * f) { - buffer_geom.destroy(f); - buffer_ind .destroy(f); - QList vaol = vao_map.values(); - foreach (VertexObject* vao, vaol) - vao->destroy(f); - qDeleteAll(vao_map); - vao_map.clear(); -} - - -void Mesh::calculateNormals() { - normals_.resize(vertices_.size()); - QVector3D dv1, dv2, n; - foreach (const Vector3i & t, triangles_) { - QVector3D & v0(vertices_[t.p0]); - QVector3D & v1(vertices_[t.p1]); - QVector3D & v2(vertices_[t.p2]); - dv1 = v1 - v0, dv2 = v2 - v0; - n = QVector3D::crossProduct(dv1, dv2).normalized(); - normals_[t.p0] = n; - normals_[t.p1] = n; - normals_[t.p2] = n; - } -} - - -void Mesh::calculateTangents() { - if (vertices_.isEmpty() || texcoords_.isEmpty()) return; - if (texcoords_.size() != vertices_.size()) return; - tangents_ .resize(vertices_.size()); - bitangents_.resize(vertices_.size()); - //qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "..."; - QVector3D dv1, dv2; - QVector2D dt1, dt2; - QVector3D tan, bitan; - foreach (const Vector3i & t, triangles_) { - QVector3D & v0(vertices_ [t.p0]); - QVector3D & v1(vertices_ [t.p1]); - QVector3D & v2(vertices_ [t.p2]); - QVector2D & t0(texcoords_[t.p0]); - QVector2D & t1(texcoords_[t.p1]); - QVector2D & t2(texcoords_[t.p2]); - dv1 = v1 - v0, dv2 = v2 - v0; - dt1 = t1 - t0, dt2 = t2 - t0; - tan = (dv1 * dt2.y() - dv2 * dt1.y()).normalized(); - bitan = (dv2 * dt1.x() - dv1 * dt2.x()).normalized(); - tangents_ [t.p0] = tan; - tangents_ [t.p1] = tan; - tangents_ [t.p2] = tan; - bitangents_[t.p0] = bitan; - bitangents_[t.p1] = bitan; - bitangents_[t.p2] = bitan; - //qDebug() << " t" << t << vi << ti << dv1.toQVector3D() << "..."; - } - //qDebug() << "calculateBinormals" << vcnt << tcnt << tangents_.size(); -} - - -VertexObject * Mesh::vaoByType(int type) { - VertexObject *& vao(vao_map[type]); - if (!vao) { - vao = new VertexObject(); - } - return vao; -} - - -bool Mesh::rebuffer(QOpenGLExtraFunctions * f) { - changed = false; - if (vertices_.isEmpty()) return true; - if (normals_.isEmpty()) - calculateNormals(); - calculateTangents(); - vert_count = qMin(vertices_.size(), normals_.size()); - vert_count = qMin(vert_count, tangents_.size()); - vert_count = qMin(vert_count, bitangents_.size()); - vert_count = qMin(vert_count, texcoords_.size()); - data_.resize(vert_count); - for (int i = 0; i < vert_count; ++i) { - Vertex & v(data_[i]); - v.pos = vertices_ [i]; - v.normal = normals_ [i]; - v.tangent = tangents_ [i]; - v.bitangent = bitangents_[i]; - v.tex = texcoords_ [i]; - } - int gsize = data_.size() * sizeof(Vertex); - int tsize = triangles_.size() * sizeof(Vector3i); - int lsize = lines_.size() * sizeof(Vector2i); - - buffer_geom.bind(f); - buffer_geom.resize(f, gsize); - buffer_geom.load(f, data_.constData(), gsize); - - buffer_ind.bind(f); - if (geom_type == GL_TRIANGLES) { - buffer_ind.resize(f, tsize); - buffer_ind.load(f, triangles_.constData(), tsize); - } else { - buffer_ind.resize(f, lsize); - buffer_ind.load(f, lines_.constData(), lsize); - } - - return !isEmpty(); -} - - -void Mesh::draw(QOpenGLExtraFunctions * f, int count, int type) { - if (isEmpty()) return; - if (!isInit()) init(f); - if (changed) rebuffer(f); - //qDebug() << "draw" << geom_type << vert_count << count; - - VertexObject * vao = vaoByType(type); - vao->bindBuffers(f, buffer_geom, buffer_ind); - if (geom_type == GL_TRIANGLES) - vao->draw(f, geom_type, triangles_.size() * 3, count); - else - vao->draw(f, geom_type, lines_.size() * 2, count); -} - - -void Mesh::clear() { - vertices_ .clear(); - normals_ .clear(); - tangents_ .clear(); - bitangents_.clear(); - texcoords_ .clear(); - triangles_ .clear(); - lines_ .clear(); - data_ .clear(); - changed = hash_changed = true; -} - - -void Mesh::loadObject(QOpenGLExtraFunctions * f, const Object & object, int type) { - VertexObject * vao = vaoByType(type); - vao->loadObject(f, object); -} - - -void Mesh::loadObjects(QOpenGLExtraFunctions * f, const QVector & objects, int type) { - VertexObject * vao = vaoByType(type); - vao->loadObjects(f, objects); -} - - -void Mesh::loadSelections(QOpenGLExtraFunctions * f, const QVector & sels, int type) { - VertexObject * vao = vaoByType(type); - vao->loadSelections(f, sels); -} - - -uint Mesh::hash() const { - if (hash_changed) { - hash_changed = false; - hash_ = qHashBits(vertices_ .constData(), vertices_ .size() * sizeof(QVector3D)); - hash_ ^= qHashBits(normals_ .constData(), normals_ .size() * sizeof(QVector3D)); - hash_ ^= qHashBits(texcoords_.constData(), texcoords_.size() * sizeof(QVector2D)); - hash_ ^= qHashBits(triangles_.constData(), triangles_.size() * sizeof( Vector3i)); - hash_ ^= qHashBits(lines_ .constData(), lines_ .size() * sizeof( Vector2i)); - } - return hash_; -} - - -bool Mesh::isObjectsChanged(int type) const { - return (const_cast(this))->vaoByType(type)->isObjectsChanged(); -} - - -bool Mesh::isSelectionChanged(int type) const { - return (const_cast(this))->vaoByType(type)->isSelectionChanged(); -} - - -void Mesh::setObjectsChanged(int type, bool yes) { - vaoByType(type)->setObjectsChanged(yes); -} - - -void Mesh::setSelectionChanged(int type, bool yes) { - vaoByType(type)->setSelectionChanged(yes); -} - - -void Mesh::setAllObjectsChanged(bool yes) { - QMapIterator it(vao_map); - while (it.hasNext()) - it.next().value()->setObjectsChanged(yes); -} - - -void Mesh::setAllSelectionChanged(bool yes) { - QMapIterator it(vao_map); - while (it.hasNext()) - it.next().value()->setSelectionChanged(yes); -} - - -void Mesh::translatePoints(const QVector3D & dp) { - QMatrix4x4 m; - m.translate(dp); - transformPoints(m); -} - - -void Mesh::scalePoints(const QVector3D & dp) { - QMatrix4x4 m; - m.scale(dp); - transformPoints(m); -} - - -void Mesh::rotatePoints(const double & angle, const QVector3D & a) { - QMatrix4x4 m; - m.rotate(angle, a); - transformPoints(m); -} - - -void Mesh::transformPoints(const QMatrix4x4 & mat) { - if (vertices_.isEmpty()) return; - int vcnt = vertices_.size(), ncnt = normals_.size(); - for (int i = 0; i < vcnt; ++i) { - vertices_[i] = (mat * QVector4D(vertices_[i], 1)).toVector3D(); - if (i < ncnt) - normals_[i] = (mat * QVector4D(normals_[i], 0)).toVector3D(); - } - changed = hash_changed = true; -} - - -void Mesh::flipNormals() { - if (vertices_.isEmpty()) return; - for (int i = 0; i < triangles_.size(); ++i) - piSwap(triangles_[i].p1, triangles_[i].p2); - for (int i = 0; i < lines_.size(); ++i) - piSwap(lines_[i].p0, lines_[i].p1); - int ncnt = normals_.size(); - for (int i = 0; i < ncnt; ++i) - normals_[i] = -normals_[i]; - changed = hash_changed = true; -} - - -void Mesh::append(const Mesh * m) { - if (!m) return; - if (m->isEmpty()) return; - if (normals_.isEmpty()) calculateNormals(); - int vcnt = vertices_.size(); - vertices_ .append(m->vertices_ ); - normals_ .append(m->normals_ ); - texcoords_.append(m->texcoords_); - QVector tri = m->triangles_; - for (int i = 0; i < tri.size(); ++i) - tri[i] += vcnt; - triangles_.append(tri); - QVector lin = m->lines_; - for (int i = 0; i < lin.size(); ++i) - lin[i] += vcnt; - lines_.append(lin); -} - - -bool Mesh::saveToFile(const QString & filename) { - if (filename.isEmpty()) return false; - QFile f(filename); - QByteArray ba; - if (f.open(QFile::WriteOnly)) { - QDataStream out(&ba, QFile::WriteOnly); - out << vertices_ << normals_ << texcoords_ << triangles_ << lines_; - ba = qCompress(ba); - f.resize(0); - f.write(ba); - f.close(); - return true; - } - return false; -} - - -bool Mesh::loadFromFile(const QString & filename) { - if (filename.isEmpty()) return false; - QFile f(filename); - QByteArray ba; - if (f.open(QFile::ReadOnly)) { - ba = f.readAll(); - if (ba.isEmpty()) return false; - ba = qUncompress(ba); - QDataStream in(ba); - in >> vertices_ >> normals_ >> texcoords_ >> triangles_ >> lines_; - changed = hash_changed = true; - f.close(); - return !isEmpty(); - } - return false; -} - - -Box3D Mesh::boundingBox() const { - if (vertices_.isEmpty()) return Box3D(); - int vcnt = vertices_.size(); - //qDebug() << "calculateBinormals" << vcnt << tcnt << vertices_.size() << texcoords_.size() << "..."; - GLfloat mix, miy, miz, max, may, maz; - QVector3D v0(vertices_[0]); - mix = max = v0.x(); - miy = may = v0.y(); - miz = maz = v0.z(); - Box3D bound; - for (int i = 1; i < vcnt; ++i) { - const QVector3D & v(vertices_[i]); - if (mix > v.x()) mix = v.x(); - if (max < v.x()) max = v.x(); - if (miy > v.y()) miy = v.y(); - if (may < v.y()) may = v.y(); - if (miz > v.z()) miz = v.z(); - if (maz < v.z()) maz = v.z(); - } - bound.x = mix; - bound.y = miy; - bound.z = miz; - bound.length = max - mix; - bound.width = may - miy; - bound.height = maz - miz; - return bound; -} - - -QDataStream & operator <<(QDataStream & s, const Mesh * m) { - ChunkStream cs; - //qDebug() << "place VBO" << m.vertices_.size() << m.normals_.size() << m.texcoords_.size() << m.colors_.size() << "..."; - cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_) - .add(6, m->triangles_).add(7, m->lines_).add(10, int(m->geom_type)); - //qDebug() << "place VBO done" << cs.data().size() << "..."; - s << /*qCompress*/(cs.data()); return s; -} - - -QDataStream & operator >>(QDataStream & s, Mesh *& m) { - m = new Mesh(); - //QByteArray ba; - //s >> ba; - //ba = qUncompress(ba); - ChunkStream cs(s); - while (!cs.atEnd()) { - switch (cs.read()) { - case 1 : cs.get(m->vertices_ ); break; - case 2 : cs.get(m->normals_ ); break; - case 3 : cs.get(m->texcoords_); break; - case 6 : cs.get(m->triangles_); break; - case 7 : cs.get(m->lines_ ); break; - case 10: m->geom_type = cs.getData(); break; - } - } - m->changed = true; - return s; -} diff --git a/qglengine/core/glmesh.h b/qglengine/core/glmesh.h deleted file mode 100644 index e87f336..0000000 --- a/qglengine/core/glmesh.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - QGL Mesh - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLMESH_H -#define GLMESH_H - -#include -#include "glvertexobject.h" - - -class Mesh -{ - friend class ObjectBase; - friend class Scene; - friend class Renderer; - friend QDataStream & operator <<(QDataStream & s, const Mesh * m); - friend QDataStream & operator >>(QDataStream & s, Mesh *& m); -public: - Mesh(GLenum geom_type_ = GL_TRIANGLES); - ~Mesh(); - - Mesh * clone(); - - //GLVBO & operator =(const GLVBO & o) {return *this;} - - void init (QOpenGLExtraFunctions * f); - void destroy (QOpenGLExtraFunctions * f); - bool rebuffer(QOpenGLExtraFunctions * f); - void draw (QOpenGLExtraFunctions * f, int count, int type = 0); - void clear(); - void loadObject (QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object, int type = 0); - void loadObjects (QOpenGLExtraFunctions * f, const QVector & objects, int type = 0); - void loadSelections(QOpenGLExtraFunctions * f, const QVector & sels, int type = 0); - - int verticesCount() const {return vertices_.size();} - int trianglesCount() const {return triangles_.size();} - int linesCount() const {return lines_.size();} - bool isInit() const {return buffer_geom.isInit();} - bool isEmpty() const {return vertices_.isEmpty();} - uint hash() const; - - bool isObjectsChanged (int type = 0) const; - bool isSelectionChanged (int type = 0) const; - void setObjectsChanged (int type = 0, bool yes = true); - void setSelectionChanged(int type = 0, bool yes = true); - void setAllObjectsChanged (bool yes = true); - void setAllSelectionChanged(bool yes = true); - - QVector & vertices () {changed = hash_changed = true; return vertices_;} - QVector & normals () {changed = hash_changed = true; return normals_;} - QVector & texcoords() {changed = hash_changed = true; return texcoords_;} - QVector< Vector3i> & indicesTriangles() {changed = hash_changed = true; return triangles_;} - QVector< Vector2i> & indicesLines () {changed = hash_changed = true; return lines_;} - - void translatePoints(const QVector3D & dp); - void translatePoints(const double & x, const double & y, const double & z) {translatePoints(QVector3D(x, y, z));} - void scalePoints (const QVector3D & dp); - void scalePoints (const double & s) {scalePoints(QVector3D(s, s, s));} - void rotatePoints (const double & angle, const QVector3D & a); - void rotatePoints (const double & angle, const double & x, const double & y, const double & z) {rotatePoints(angle, QVector3D(x, y, z));} - void transformPoints(const QMatrix4x4 & mat); - void flipNormals(); - void append(const Mesh * m); - - bool saveToFile(const QString & filename); - bool loadFromFile(const QString & filename); - - Box3D boundingBox() const; - -private: - void calculateNormals(); - void calculateTangents(); - VertexObject * vaoByType(int type); - - QVector vertices_, normals_, tangents_, bitangents_; - QVector texcoords_; - QVector< Vector3i> triangles_; - QVector< Vector2i> lines_; - - QVector data_; - GLenum geom_type; - Buffer buffer_geom, buffer_ind; - QMap vao_map; - mutable uint hash_; - mutable bool hash_changed; - int vert_count; - bool changed; - -}; - - -QDataStream & operator <<(QDataStream & s, const Mesh * m); -QDataStream & operator >>(QDataStream & s, Mesh *& m); - -#endif // GLMESH_H diff --git a/qglengine/core/glprimitives.cpp b/qglengine/core/glprimitives.cpp deleted file mode 100644 index 6f6579b..0000000 --- a/qglengine/core/glprimitives.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/* - QGL Primitives - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "glprimitives.h" -#include "glmesh.h" - - -Mesh * Primitive::plane(float width, float length) { - Mesh * ret = new Mesh(); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector3i> & i(ret->indicesTriangles ()); - float hw = width / 2.f, hl = length / 2.f; - for (int j = 0; j < 4; ++j) n << QVector3D(0., 0., 1.); - t << QVector2D(0., 0.) << QVector2D(0., 1.) << QVector2D(1., 1.) << QVector2D(1., 0.); - v << QVector3D(-hw, -hl, 0.) << QVector3D(-hw, hl, 0.) << QVector3D(hw, hl, 0.) << QVector3D(hw, -hl, 0.); - i << Vector3i(0, 2, 1) << Vector3i(0, 3, 2); - return ret; -} - - -Mesh * Primitive::cube(float width, float length, float height) { - Mesh * ret = new Mesh(); - QVector3D scale(width, length, height); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector3i> & i(ret->indicesTriangles ()); - float hs = 0.5f; - int si = 0; - QMatrix4x4 mat; - - si = v.size(); - for (int j = 0; j < 4; ++j) n << QVector3D(0., -1., 0.); - t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.); - v << QVector3D(-hs, -hs, -hs) << QVector3D(hs, -hs, -hs) << QVector3D(hs, -hs, hs) << QVector3D(-hs, -hs, hs); - i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3); - - for (int r = 0; r < 3; ++r) { - si = v.size(); - mat.rotate(90., 0., 0., 1.); - QVector3D cn = mat.map(n[0]); - for (int j = 0; j < 4; ++j) { - n << cn; - v << mat.map(QVector4D(v[j])).toVector3D(); - } - t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.); - i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3); - } - - mat.setToIdentity(); - mat.rotate(90., 1., 0.,0.); - for (int r = 0; r < 2; ++r) { - si = v.size(); - mat.rotate(180., 1., 0.,0.); - QVector3D cn = mat.map(n[0]); - for (int j = 0; j < 4; ++j) { - n << cn; - v << mat.map(QVector4D(v[j])).toVector3D(); - } - t << QVector2D(0., 0.) << QVector2D(1., 0.) << QVector2D(1., 1.) << QVector2D(0., 1.); - i << Vector3i(si + 0, si + 1, si + 2) << Vector3i(si + 0, si + 2, si + 3); - } - - for (int i = 0; i < v.size(); ++i) - v[i] *= scale; - - return ret; -} - - -Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float radius, float end_angle) { - Mesh * ret = new Mesh(); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector3i> & ind(ret->indicesTriangles()); - int hseg = segments_h + 1, wlseg = segments_wl + 1; - double crw, crl, a, ch, twl; - double eang = deg2rad * end_angle; - - QVector3D cp; - for (int i = 0; i <= hseg; i++) { - ch = -cos((double)i / hseg * M_PI); - cp.setZ(ch * radius); - twl = sqrt(1. - ch * ch); - crw = twl * radius; - crl = twl * radius; - int cvcnt = wlseg * 2; - for (int j = 0; j < cvcnt; j++) { - a = (double)j / (cvcnt - 1) * eang; - cp.setX(crl * cos(a)); - cp.setY(crw * sin(a)); - v << cp; - t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f); - n << cp.normalized(); - int si = v.size() - 1; - if (j > 0 && i > 0) { - ind << Vector3i(si - cvcnt - 1, si, si - 1); - ind << Vector3i(si - cvcnt, si, si - cvcnt - 1); - } - } - } - if (end_angle < 360.) { - Mesh * cap = Primitive::disc(segments_h+1, radius, 180); - cap->rotatePoints(90, 0, 1, 0); - cap->rotatePoints(-90, 0, 0, 1); - ret->append(cap); - cap->flipNormals(); - cap->rotatePoints(end_angle, 0, 0, 1); - ret->append(cap); - delete cap; - } - return ret; -} - - -Mesh * Primitive::disc(int segments, float radius, float end_angle) { - Mesh * ret = new Mesh(); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector3i> & ind(ret->indicesTriangles()); - - segments = qMax(segments + 1, 4); - QVector3D cp; - v << QVector3D(); - n << QVector3D(0, 0, 1); - t << QVector2D(0.5f, 0.5f); - end_angle *= deg2rad; - for (int i = 0; i < segments; i++) { - double a = (double)i / (segments - 1) * end_angle; - cp.setX(radius * cos(a)); - cp.setY(radius * sin(a)); - v << cp; - n << QVector3D(0, 0, 1); - t << QVector2D(cp.x() / radius + 1, cp.y() / radius + 1); - int si = v.size() - 1; - if (i > 0) ind << Vector3i(si - 1, si, 0); - } - return ret; -} - - -QVector3D coneNormal(double r, double height, double ang) { - QVector3D norm; - norm.setX(r * cos(ang)); - norm.setY(r * sin(ang)); - norm.setZ(0.); - double rl = norm.length(); - double ca = atan2(rl, height); - norm *= cos(ca); - norm.setZ(norm.length() * tan(ca)); - return norm.normalized(); -} - - -Mesh * Primitive::cone(int segments, float radius, float height) { - Mesh * ret = new Mesh(); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector3i> & ind(ret->indicesTriangles()); - - int seg = qMax(segments + 1, 4); - QVector3D cp; - for (int i = 0; i < seg; i++) { - double a = (double)i / (seg - 1) * M_2PI; - cp.setX(radius * cos(a)); - cp.setY(radius * sin(a)); - if (i > 0) { - v << QVector3D(0, 0, height); - t << QVector2D((double)(i - 1) / (seg - 1), 1.f); - double ta = ((double)i - 0.5) / (seg - 1) * M_2PI; - n << coneNormal(radius, height, ta); - } - v << cp; - t << QVector2D((double)i / (seg - 1), 0.f); - n << coneNormal(radius, height, a); - int si = v.size() - 1; - if (i > 0) - ind << Vector3i(si - 1, si - 2, si); - } - - Mesh * cap = Primitive::disc(segments, radius); - cap->flipNormals(); - ret->append(cap); - delete cap; - - return ret; -} - - -Mesh * Primitive::cylinder(int segments, float radius, float height, float end_angle) { - Mesh * ret = new Mesh(); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector3i> & ind(ret->indicesTriangles()); - - int seg = qMax(segments + 1, 4); - QVector3D cp, norm; - double eang = deg2rad * end_angle; - - for (int i = 0; i < seg; i++) { - double a = (double)i / (seg - 1) * eang; - cp.setX(radius * cos(a)); - cp.setY(radius * sin(a)); - cp.setZ(0.); - norm = cp.normalized(); - v << cp; - cp.setZ(height); - v << cp; - t << QVector2D((double)i / (seg - 1), 0.f); - t << QVector2D((double)i / (seg - 1), 1.f); - n << norm; n << norm; - int si = v.size() - 1; - if (i > 0) { - ind << Vector3i(si - 2, si - 1, si); - ind << Vector3i(si - 1, si - 2, si - 3); - } - } - - Mesh * cap = Primitive::disc(segments, radius, end_angle); - cap->flipNormals(); - ret->append(cap); - cap->translatePoints(QVector3D(0., 0., height)); - cap->flipNormals(); - ret->append(cap); - delete cap; - - if (end_angle < 360.) { - Mesh * cap = Primitive::plane(radius, height); - cap->rotatePoints(90, 1, 0, 0); - //cap->rotatePoints(-90, 0, 0, 1); - cap->translatePoints(radius/2, 0, height/2); - ret->append(cap); - cap->flipNormals(); - cap->rotatePoints(end_angle, 0, 0, 1); - ret->append(cap); - delete cap; - } - - return ret; -} - - -Mesh * Primitive::arrow(int segments, float thick, float angle) { - double cone_r = 1.5 * thick; - double cone_h = 2. * cone_r / tan(angle * deg2rad); - Mesh * ret = new Mesh(); - Mesh * m = Primitive::cylinder(segments, thick / 2., 1. - cone_h); - ret->append(m); - delete m; - m = Primitive::cone(segments, cone_r, cone_h); - m->translatePoints(QVector3D(0., 0., 1. - cone_h)); - ret->append(m); - delete m; - return ret; -} - - -Mesh * Primitive::torus(int segments_main, int segments_second, float radius_main, float radius_second, float end_angle) { - Mesh * ret = new Mesh(); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector3i> & ind(ret->indicesTriangles()); - - QVector cv, cn; - QVector ct; - segments_second = qMax(segments_second + 1, 4); - for (int i = 0; i < segments_second; i++) { - double x = (double)i / (segments_second - 1); - double a = x * M_2PI; - cv << QVector3D(radius_second * cos(a), 0., radius_second * sin(a)); - cn << cv.back().normalized(); - ct << QVector2D(0., x); - cv.back() += QVector3D(radius_main, 0., 0.); - } - - segments_main = qMax(segments_main + 1, 4); - int ccnt = cv.size(), pcnt = 0; - for (int i = 0; i < segments_main; i++) { - double x = (double)i / (segments_main - 1); - QMatrix4x4 rm; - rm.rotate(x * end_angle, 0., 0., 1.); - for (int j = 0; j < ccnt; j++) { - ct[j].setX(x); - v << rm.map(cv[j]); - n << rm.map(cn[j]); - } - t.append(ct); - if (i > 0) { - for (int j = 0; j < ccnt - 1; j++) { - ind << Vector3i(pcnt + j, pcnt + j + 1, pcnt + j - ccnt); - ind << Vector3i(pcnt + j + 1, pcnt + j + 1 - ccnt, pcnt + j - ccnt); - } - } - pcnt = v.size(); - } - if (end_angle < 360.) { - Mesh * cap = Primitive::disc(segments_second-1, radius_second); - cap->rotatePoints(90, 1, 0, 0); - cap->translatePoints(radius_main, 0, 0); - ret->append(cap); - cap->flipNormals(); - cap->rotatePoints(end_angle, 0, 0, 1); - ret->append(cap); - delete cap; - } - return ret; -} - - - - -Mesh * Primitive::cubeFrame(float width, float length, float height) { - Mesh * ret = new Mesh(GL_LINES); - QVector3D scale(width, length, height); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector2i> & i(ret->indicesLines()); - float hs = 0.5f; - v << QVector3D(-hs, -hs, -hs) << QVector3D(-hs, hs, -hs) << QVector3D( hs, hs, -hs) << QVector3D( hs, -hs, -hs); - v << QVector3D(-hs, -hs, hs) << QVector3D(-hs, hs, hs) << QVector3D( hs, hs, hs) << QVector3D( hs, -hs, hs); - for (int j = 0; j < 8; ++j) { - v[j] *= scale; - t << QVector2D(0, 0); - n << QVector3D(0,0,1); - } - for (int j = 0; j < 4; ++j) { - i << Vector2i(j, (j + 1) % 4); - i << Vector2i(j, j + 4); - i << Vector2i(j + 4, (j + 1) % 4 + 4); - } - return ret; -} - - -Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float radius) { - Mesh * ret = new Mesh(GL_LINES); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector2i> & ind(ret->indicesLines()); - int hseg = segments_h + 1, wlseg = segments_wl + 1; - double crw, crl, a, ch, twl; - - QVector3D cp; - for (int i = 0; i <= hseg; i++) { - ch = -cos((double)i / hseg * M_PI); - cp.setZ(ch * radius); - twl = sqrt(1. - ch * ch); - crw = twl * radius; - crl = twl * radius; - int cvcnt = wlseg * 2; - for (int j = 0; j < cvcnt; j++) { - a = (double)j / (cvcnt - 1) * M_2PI; - cp.setX(crl * cos(a)); - cp.setY(crw * sin(a)); - v << cp; - t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f); - n << cp.normalized(); - int si = v.size() - 1; - if (j > 0 && i > 0) { - ind << Vector2i(si, si - 1); - ind << Vector2i(si - cvcnt, si); - } - } - } - return ret; -} - - -Mesh * Primitive::coneFrame(int segments, float radius, float height) { - Mesh * ret = new Mesh(GL_LINES); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector2i> & ind(ret->indicesLines()); - - int seg = qMax(segments + 1, 4); - QVector3D cp; - for (int i = 0; i < seg; i++) { - double a = (double)i / (seg - 1) * M_2PI; - cp.setX(radius * cos(a)); - cp.setY(radius * sin(a)); - if (i > 0) { - v << QVector3D(0, 0, height); - t << QVector2D((double)(i - 1) / (seg - 1), 1.f); - double ta = ((double)i - 0.5) / (seg - 1) * M_2PI; - n << coneNormal(radius, height, ta); - } - v << cp; - t << QVector2D((double)i / (seg - 1), 0.f); - n << coneNormal(radius, height, a); - int si = v.size() - 1; - if (i > 0) { - ind << Vector2i(si - 1, si); - ind << Vector2i(si - 2, si); - } - } - - return ret; -} - - -Mesh * Primitive::lineFrame(QVector3D p0, QVector3D p1) { - Mesh * ret = new Mesh(GL_LINES); - QVector & v(ret->vertices ()); - QVector & n(ret->normals ()); - QVector & t(ret->texcoords()); - QVector< Vector2i> & ind(ret->indicesLines()); - v << p0 << p1; - n << QVector3D(0,0,1) << QVector3D(0,0,1); - t << QVector2D(0,0) << QVector2D(1,0); - ind << Vector2i(0, 1); - return ret; -} diff --git a/qglengine/core/glprimitives.h b/qglengine/core/glprimitives.h deleted file mode 100644 index 7129bb1..0000000 --- a/qglengine/core/glprimitives.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - QGL Primitives - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLPRIMITIVE_CUBE_H -#define GLPRIMITIVE_CUBE_H - -#include "gltypes.h" - - -namespace Primitive { - - -Mesh * plane(float width = 1., float length = 1.); - -Mesh * cube(float width = 1., float length = 1., float height = 1.); - -Mesh * ellipsoid(int segments_wl, int segments_h, float radius = 1., float end_angle = 360.); - -Mesh * disc(int segments, float radius = 1., float end_angle = 360.); - -Mesh * cone(int segments, float radius = 1., float height = 1.); - -Mesh * cylinder(int segments, float radius = 1., float height = 1., float end_angle = 360.); - -Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1 - -Mesh * torus(int segments_main = 30, int segments_second = 16, float radius_main = 2.5, float radius_second = 0.5, float end_angle = 360.); - - -Mesh * lineFrame(QVector3D p0, QVector3D p1); - -Mesh * cubeFrame(float width = 1., float length = 1., float height = 1.); - -Mesh * ellipsoidFrame(int segments_wl, int segments_h, float radius = 1.); - -Mesh * coneFrame(int segments, float radius = 1., float height = 1.); - -} - -/* -class GLPrimitivePoint: public GLObjectBase -{ -public: - GLPrimitivePoint(double size = 1., QVector3D pos = QVector3D()) {sz = 8.;} - virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); -private: - double sz; -}; - - - - -class GLPrimitiveLine: public GLObjectBase -{ -public: - GLPrimitiveLine(QVector3D p0_ = QVector3D(), QVector3D p1_ = QVector3D()) {p0 = p0_; p1 = p1_;} - virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); - QVector3D point0() const {return p0;} - QVector3D point1() const {return p1;} - void setPoint0(const QVector3D & p) {p0 = p;} - void setPoint1(const QVector3D & p) {p1 = p;} -private: - QVector3D p0, p1; -}; - - - - -class GLPrimitiveEllipsoid: public GLObjectBase -{ -public: - GLPrimitiveEllipsoid(float width = 1., float length = 1., float height = 1., int seg_wl = 10, int seg_h = 10, QVector3D pos = QVector3D()); - virtual void init(); -private: - void putTriangle(const QVector3D & v0, const QVector3D & v1, const QVector3D & v2); - float w, l, h; - int swl, sh; -}; - - -class GLPrimitiveAxis: public GLObjectBase -{ -public: - GLPrimitiveAxis() {accept_fog = accept_light = cast_shadow = rec_shadow = select_ = false;} - virtual void draw(QOpenGLShaderProgram * prog, bool simplest = false); -}; -*/ - -#endif // GLPRIMITIVE_CUBE_H diff --git a/qglengine/core/glshaders.cpp b/qglengine/core/glshaders.cpp deleted file mode 100644 index 4fff0d2..0000000 --- a/qglengine/core/glshaders.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - QGLEngineShaders - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "gltypes.h" -#include "qglview.h" -#include "glshaders.h" -#include "glshaders_headers.h" - -using namespace QGLEngineShaders; - - -bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QString & content, const QString & file, bool add_qgl, const QString & defs) { - if (type == 0 || content.isEmpty()) { - content.clear(); - return true; - } - //qDebug() << "[QGLEngine] Shader" << file << "found" << (QOpenGLShader::ShaderTypeBit)(int)type << "section ..."; - if (add_qgl) { - switch (type) { - case QOpenGLShader::Fragment: - content.prepend(qgl_fragment_head); - content.prepend(qgl_uniform); - content.prepend(qgl_structs); - break; - case QOpenGLShader::Vertex : - content.prepend(qgl_vertex_head ); - break; - case QOpenGLShader::Geometry: - content.prepend(qgl_geometry_head); - break; - } - } - content.prepend(defs); - content.prepend(qgl_common_head); - bool ret = prog->addShaderFromSourceCode(type, content.toLatin1()); - if (!ret) qDebug() << "[QGLEngine] Shader" << file << "Compile error:\n" << prog->log(); - content.clear(); - return ret; -} - - -QString prepareDefines(const QStringList & defines) { - if (defines.isEmpty()) return QString(); - QString ret; - foreach (QString s, defines) - ret.append("#define " + s + "\n"); - return ret; -} - - -bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, bool add_qgl, const QStringList & defines) { - if (!prog) - prog = new QOpenGLShaderProgram(); - prog->removeAllShaders(); - QFile f(file); - if (!f.open(QIODevice::ReadOnly)) { - qDebug() << "[QGLEngine] Shader" << file << "Error: can`t open file!"; - return false; - } - QTextStream ts(&f); - QString cur_shader, line, pl, defs = prepareDefines(defines); - QOpenGLShader::ShaderType type = 0; - while (!ts.atEnd()) { - line = ts.readLine(); - pl = line.trimmed().remove(' ').remove('\t').mid(2).toLower(); - pl.chop(2); - if (pl == "vertex" || pl == "vert") { - if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; - type = QOpenGLShader::Vertex; - continue; - } - if (pl == "fragment" || pl == "frag") { - if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; - type = QOpenGLShader::Fragment; - continue; - } - if (pl == "geometry" || pl == "geom") { - if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; - type = QOpenGLShader::Geometry; - continue; - } - if (pl == "tessellation_control") { - if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; - type = QOpenGLShader::TessellationControl; - continue; - } - if (pl == "tessellation_evaluation") { - if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; - type = QOpenGLShader::TessellationEvaluation; - continue; - } - cur_shader.append("\n"); - cur_shader.append(line); - } - if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; - if (!prog->link()) { - qDebug() << "[QGLEngine] Shader" << file << "Link error:\n" << prog->log(); - return false; - } - qDebug() << "[QGLEngine] Shader" << file << "ok"; - return true; -} - - -bool QGLEngineShaders::loadShaders(QOpenGLShaderProgram *& prog, const QStringList & files, bool add_qgl, const QStringList & defines) { - if (!prog) - prog = new QOpenGLShaderProgram(); - prog->removeAllShaders(); - QString cur_shader, defs = prepareDefines(defines); - foreach (QString f, files) { - QFileInfo fi(f); - QOpenGLShader::ShaderType type = 0; - if (fi.suffix().toLower() == "vert") type = QOpenGLShader::Vertex ; - if (fi.suffix().toLower() == "frag") type = QOpenGLShader::Fragment; - if (fi.suffix().toLower() == "geom") type = QOpenGLShader::Geometry; - if (type == 0) continue; - QFile file(f); - if (!file.open(QIODevice::ReadOnly)) { - qDebug() << "[QGLEngine] Shader" << f << "Error: can`t open file!"; - return false; - } - cur_shader = file.readAll(); - if (!addShader(prog, type, cur_shader, f, add_qgl, defs)) return false; - } - if (!prog->link()) { - qDebug() << "[QGLEngine] Shader" << files << "Link error:\n" << prog->log(); - return false; - } - qDebug() << "[QGLEngine] Shader" << files << "ok"; - return true; -} diff --git a/qglengine/core/glshaders.h b/qglengine/core/glshaders.h deleted file mode 100644 index 57fc6a9..0000000 --- a/qglengine/core/glshaders.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - QGLEngineShaders - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLSHADERS_H -#define GLSHADERS_H - -#include "gltypes.h" - -namespace QGLEngineShaders { - -bool loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, bool add_qgl = true, const QStringList & defines = QStringList()); -bool loadShaders(QOpenGLShaderProgram *& prog, const QStringList & files, bool add_qgl = true, const QStringList & defines = QStringList()); - -} - -#endif // GLSHADERS_H diff --git a/qglengine/core/glshaders_headers.h b/qglengine/core/glshaders_headers.h deleted file mode 100644 index dac5c6e..0000000 --- a/qglengine/core/glshaders_headers.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - QGLEngineShaders - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLSHADERS_HEADERS_H -#define GLSHADERS_HEADERS_H - -namespace QGLEngineShaders { - -const int max_materials = 128; -const int max_lights = 256 ; - -const char qgl_common_head[] = - "#version 400 core\n" - ""; - -const char qgl_vertex_head[] = - "layout(location = 1 ) in vec3 qgl_Vertex ;\n" - "layout(location = 2 ) in vec3 qgl_Normal ;\n" - "layout(location = 3 ) in vec3 qgl_Tangent ;\n" - "layout(location = 4 ) in vec3 qgl_Bitangent ;\n" - "layout(location = 5 ) in vec2 qgl_Texture ;\n" - "layout(location = 6 ) in uint qgl_Material ;\n" - "layout(location = 7 ) in uint qgl_ObjectSelected;\n" - "layout(location = 8 ) in uint qgl_ObjectID ;\n" - "layout(location = 9 ) in vec4 qgl_ObjectColor ;\n" - "layout(location = 10) in mat4 qgl_ModelMatrix ;\n" - "out vec2 qgl_FragTexture;\n" - "flat out uint qgl_MaterialIndex;\n" - "uniform mat4 qgl_ViewMatrix;\n" - "uniform mat4 qgl_ViewProjMatrix;\n" - "mat3 qgl_getNormalMatrix() {return inverse(mat3(qgl_ViewMatrix * qgl_ModelMatrix));}\n" - "mat3 qgl_getTangentMatrix() {return mat3(qgl_ViewMatrix * qgl_ModelMatrix);}\n" - "vec4 qgl_ftransform() {return qgl_ViewProjMatrix * (qgl_ModelMatrix * vec4(qgl_Vertex, 1));}\n" - ""; - -const char qgl_fragment_head[] = - "in vec2 qgl_FragTexture;\n" - "flat in uint qgl_MaterialIndex;\n" - "out vec4 qgl_FragData[gl_MaxDrawBuffers];\n" - "vec4 qgl_materialTexture(uint type, vec2 coord, vec4 tex_shift) {\n" - " coord *= qgl_material[qgl_MaterialIndex].map[type].scale;\n" - " vec4 t = texture(qgl_texture_array[qgl_material[qgl_MaterialIndex].map[type].array_index],\n" - " vec3(coord, qgl_material[qgl_MaterialIndex].map[type].map_index));\n" - " t += tex_shift;\n" - " t.rgb = t.rgb * qgl_material[qgl_MaterialIndex].map[type].amount + qgl_material[qgl_MaterialIndex].map[type].offset;\n" - " return t;\n" - "}\n" - "#define qgl_FragColor qgl_FragData[0]\n" - ""; - -const char qgl_geometry_head[] = - ""; - -const char qgl_structs[] = - "#define QGL_MAPS_COUNT 6\n" - "#define QGL_MAP_DIFFUSE 0\n" - "#define QGL_MAP_NORMAL 1\n" - "#define QGL_MAP_METALNESS 2\n" - "#define QGL_MAP_ROUGHNESS 3\n" - "#define QGL_MAP_EMISSION 4\n" - "#define QGL_MAP_RELIEF 5\n" - "#define QGL_TEXTURE_ARRAY_EMPTY 0\n" - "#define QGL_TEXTURE_ARRAY_MAPS 1\n" - "struct QGLMap {\n" - " float offset;\n" - " float amount;\n" - " vec2 scale;\n" - " uint array_index;\n" - " uint map_index;\n" - "};\n" - "struct QGLMaterial {\n" - " vec4 color_diffuse;\n" - //" vec4 color_specular;\n" - " vec4 color_emission;\n" - " float transparency;\n" - " float reflectivity;\n" - " float iof;\n" - " float dispersion;\n" - " QGLMap map[QGL_MAPS_COUNT];\n" - "};\n" - "struct QGLLightParameter {\n" - " vec4 color;\n" - " vec4 decay_intensity;\n" - " vec4 angles;\n" - //" sampler2DShadow shadow;\n" - //" sampler2D shadowColor\n" - //" mat4 shadowMatrix;\n" - //" vec4 shadowDir0;\n" - //" vec4 shadowDir1;\n" - "};\n" - "struct QGLLightPosition {\n" - " vec4 position;\n" - " vec4 direction;\n" - "};\n" - ""; - -const char qgl_uniform[] = - "layout (std140) uniform QGLMaterialData {\n" - " QGLMaterial qgl_material[128];\n" - "};\n" - "layout (std140) uniform QGLLightParameterData {\n" - " QGLLightParameter qgl_light_parameter[256];\n" - "};\n" - "layout (std140) uniform QGLLightPositionData {\n" - " QGLLightPosition qgl_light_position[256];\n" - "};\n" - "uniform sampler2DArray qgl_texture_array[2];\n" - ""; - -} - -#endif // GLSHADERS_HEADERS_H diff --git a/qglengine/core/glshaders_types.cpp b/qglengine/core/glshaders_types.cpp deleted file mode 100644 index fe57b1b..0000000 --- a/qglengine/core/glshaders_types.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - QGLEngineShaders - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "glshaders_types.h" - - -QGLEngineShaders::QGLMap::QGLMap() { - offset = 0.; - amount = 1.; - scale = QVector2D(1., 1.); - array_index = map_index = 0; -} - - -QGLEngineShaders::QGLMaterial::QGLMaterial() { - color_diffuse = QVector4D(1., 1., 1., 0.); - color_emission = QVector4D(0., 0., 0., 0.); - transparency = 0.; - reflectivity = 0.; - iof = 0.; - dispersion = 0.; - map[mtNormal].map_index = emrBlue; - map[mtRoughness].amount = 0.75; - map[mtMetalness].amount = 0.25; -} - - -void QGLEngineShaders::prepareDrawGeom(QOpenGLExtraFunctions * f) { - //qDebug() << "prepareDrawGeom"; - - f->glEnableVertexAttribArray(pos_loc ); - f->glEnableVertexAttribArray(normal_loc ); - f->glEnableVertexAttribArray(tangent_loc ); - f->glEnableVertexAttribArray(bitangent_loc); - f->glEnableVertexAttribArray(tex_loc ); - - int size = sizeof(Vertex); - f->glVertexAttribPointer(pos_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)pos_offset ); - f->glVertexAttribPointer(normal_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)normal_offset ); - f->glVertexAttribPointer(tangent_loc , 3, GL_FLOAT, GL_FALSE, size, (const void *)tangent_offset ); - f->glVertexAttribPointer(bitangent_loc, 3, GL_FLOAT, GL_FALSE, size, (const void *)bitangent_offset); - f->glVertexAttribPointer(tex_loc , 2, GL_FLOAT, GL_FALSE, size, (const void *)tex_offset ); -} - - -void QGLEngineShaders::prepareDrawObj(QOpenGLExtraFunctions * f) { - //qDebug() << "prepareDrawObj"; - - f->glEnableVertexAttribArray(material_loc ); - f->glEnableVertexAttribArray(object_id_loc); - f->glEnableVertexAttribArray(color_loc ); - for (int i = 0; i < 4; ++i) { - f->glEnableVertexAttribArray(modelmatrix_loc + i); - } - - GLsizei size = sizeof(Object); - f->glVertexAttribIPointer(material_loc , 1, GL_UNSIGNED_INT , size, (const void *)material_offset ); - f->glVertexAttribIPointer(object_id_loc, 1, GL_UNSIGNED_INT , size, (const void *)object_id_offset); - f->glVertexAttribPointer (color_loc , 4, GL_FLOAT, GL_FALSE, size, (const void *)color_offset ); - for (int i = 0; i < 4; ++i) { - f->glVertexAttribPointer(modelmatrix_loc + i, 4, GL_FLOAT, GL_FALSE, size, (const void *)(modelmatrix_offset + sizeof(QVector4D)*i)); - } - - f->glVertexAttribDivisor(material_loc , 1); - f->glVertexAttribDivisor(object_id_loc, 1); - f->glVertexAttribDivisor(color_loc , 1); - for (int i = 0; i < 4; ++i) { - f->glVertexAttribDivisor(modelmatrix_loc + i, 1); - } - -} - - -void QGLEngineShaders::prepareDrawSel(QOpenGLExtraFunctions * f) { - //qDebug() << "prepareDrawObj"; - - f->glEnableVertexAttribArray(is_selected_loc); - GLsizei size = 1; - f->glVertexAttribIPointer(is_selected_loc, 1, GL_UNSIGNED_BYTE, size, (const void *)is_selected_offset); - f->glVertexAttribDivisor(is_selected_loc, 1); - -} diff --git a/qglengine/core/glshaders_types.h b/qglengine/core/glshaders_types.h deleted file mode 100644 index 55f44bc..0000000 --- a/qglengine/core/glshaders_types.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - QGLEngineShaders - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLSHADERS_TYPES_H -#define GLSHADERS_TYPES_H - -#include "gltypes.h" - -namespace QGLEngineShaders { - - -/// VBO - -// geometry -const GLsizei pos_offset = 0; -const GLsizei normal_offset = sizeof(QVector3D) + pos_offset ; -const GLsizei tangent_offset = sizeof(QVector3D) + normal_offset ; -const GLsizei bitangent_offset = sizeof(QVector3D) + tangent_offset ; -const GLsizei tex_offset = sizeof(QVector3D) + bitangent_offset; - -// object -const GLsizei material_offset = 0; -const GLsizei object_id_offset = sizeof(GLuint ) + material_offset ; -const GLsizei color_offset = sizeof(GLuint ) + object_id_offset ; -const GLsizei modelmatrix_offset = sizeof(QVector4D) + color_offset; - -const GLsizei is_selected_offset = 0; - -const GLuint pos_loc = 1 ; // qgl_Vertex -const GLuint normal_loc = 2 ; // qgl_Normal -const GLuint tangent_loc = 3 ; // qgl_Tangent -const GLuint bitangent_loc = 4 ; // qgl_Bitangent -const GLuint tex_loc = 5 ; // qgl_Texture - -const GLuint material_loc = 6 ; // qgl_Material -const GLuint object_id_loc = 8 ; // qgl_ObjectID -const GLuint color_loc = 9 ; // qgl_ObjectColor -const GLuint modelmatrix_loc = 10; // qgl_ModelViewProjectionMatrix - -const GLuint is_selected_loc = 7 ; // qgl_ObjectSelected - -#pragma pack(push, 1) -struct Vertex { - QVector3D pos; - QVector3D normal; - QVector3D tangent; - QVector3D bitangent; - QVector2D tex; -}; -struct Object { - Object() { - material = object_id = 0; - color = QVector4D(1,1,1,1); - QMatrix4x4().copyDataTo(modelmatrix); - } - GLuint material; - GLuint object_id; - QVector4D color; - GLfloat modelmatrix[16]; -}; -#pragma pack(pop) - - -/// UBO - -enum BindingPoints { - bpMaterials, - bpLightParameters, - bpLightPositions, -}; - -enum MapType { - mtDiffuse = 0, - mtNormal = 1, - mtMetalness = 2, - mtRoughness = 3, - mtEmission = 4, - mtRelief = 5, -}; -enum TextureArrayRole { - tarEmpty = 0, - tarMaps = 1, -}; -enum EmptyMapRole { - emrWhite = 0, - emrBlue = 1, -}; -#define QGL_MAPS_COUNT 6 -#pragma pack(push, 1) -struct QGLMap { - QGLMap(); - GLfloat offset; - GLfloat amount; - QVector2D scale; - GLuint array_index; - GLuint map_index; - GLfloat __res_2[2]; -}; -struct QGLMaterial { - QGLMaterial(); - QVector4D color_diffuse; - QVector4D color_emission; - GLfloat transparency; - GLfloat reflectivity; - GLfloat iof; - GLfloat dispersion; - QGLMap map[QGL_MAPS_COUNT]; -}; -struct QGLLightParameter { - QVector4D color; - QVector4D decay_intensity; // [^0, ^1, ^2, intensity] - QVector4D angles; // [start, cos(start), end, cos(end)] - //GLfloat shadow; - //GLfloat shadowMatrix[16]; -}; -struct QGLLightPosition { - QVector4D position; - QVector4D direction; -}; -#pragma pack(pop) - -void prepareDrawGeom(QOpenGLExtraFunctions * f); -void prepareDrawObj (QOpenGLExtraFunctions * f); -void prepareDrawSel (QOpenGLExtraFunctions * f); - - -} - -#endif // GLSHADERS_TYPES_H diff --git a/qglengine/core/gltexturearray.cpp b/qglengine/core/gltexturearray.cpp deleted file mode 100644 index 1149ad6..0000000 --- a/qglengine/core/gltexturearray.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - QGL Texture2DArray - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "gltexturearray.h" - - -Texture2DArray::Texture2DArray(bool filter) { - target_ = GL_TEXTURE_2D_ARRAY; - texture_ = 0; - layers_ = 0; - filtering_ = filter; -} - - -Texture2DArray::~Texture2DArray() { -} - - -void Texture2DArray::init(QOpenGLExtraFunctions * f) { - if (!isInit()) { - f->glGenTextures(1, &texture_); - } -} - - -void Texture2DArray::destroy(QOpenGLExtraFunctions * f) { - if (texture_ != 0) { - f->glDeleteTextures(1, &texture_); - } - texture_ = 0; -} - - -void Texture2DArray::bind(QOpenGLExtraFunctions * f, int channel) { - f->glActiveTexture(GL_TEXTURE0 + channel); - f->glBindTexture(target_, texture_); -} - - -void Texture2DArray::release(QOpenGLExtraFunctions * f) { - f->glBindTexture(target_, 0); -} - - -bool Texture2DArray::resize(QOpenGLExtraFunctions * f, QSize new_size, int layers_count) { - if (new_size.isNull() || layers_count <= 0) return false; - if ((size_ == new_size) && (layers_ >= layers_count)) return false; - size_ = new_size; - layers_ = layers_count; - f->glBindTexture(target_, texture_); - f->glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_REPEAT); - f->glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_REPEAT); - if (filtering_) { - f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - f->glTexParameteri(target_, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8); - } else { - f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - f->glTexImage3D(target_, 0, GL_RGBA8, size_.width(), size_.height(), layers_, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - return true; -} - - -void Texture2DArray::load(QOpenGLExtraFunctions * f, const QImage & image, int layer) { - if (image.isNull() || size_.isNull() || layer < 0 || layer >= layers_) return; - QImage im = image.mirrored(false, true) - .scaled(size_, Qt::IgnoreAspectRatio, Qt::SmoothTransformation) - .convertToFormat(QImage::Format_RGBA8888); - //qDebug() << "Texture2DArray::load image" << image.size() << "to layer" << layer; - f->glTexSubImage3D(target_, 0, 0, 0, layer, size_.width(), size_.height(), 1, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits()); -} - - -void Texture2DArray::mipmaps(QOpenGLExtraFunctions * f) { - f->glBindTexture(target_, texture_); - f->glGenerateMipmap(target_); -} diff --git a/qglengine/core/gltexturearray.h b/qglengine/core/gltexturearray.h deleted file mode 100644 index f8b32b7..0000000 --- a/qglengine/core/gltexturearray.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - QGL Texture2DArray - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLTEXTUREARRAY_H -#define GLTEXTUREARRAY_H - -#include "gltypes.h" - - -class Texture2DArray -{ - friend class ObjectBase; -public: - Texture2DArray(bool filter); - ~Texture2DArray(); - - void init (QOpenGLExtraFunctions * f); - void destroy (QOpenGLExtraFunctions * f); - - void bind (QOpenGLExtraFunctions * f, int channel = 0); - void release (QOpenGLExtraFunctions * f); - - // returns true if size changed - bool resize (QOpenGLExtraFunctions * f, QSize new_size, int layers_count); - void load (QOpenGLExtraFunctions * f, const QImage & image, int layer); - void mipmaps (QOpenGLExtraFunctions * f); - - GLuint ID() const {return texture_;} - bool isInit() const {return texture_ != 0;} - -private: - GLenum target_; - GLuint texture_; - QSize size_; - int layers_; - bool filtering_; - -}; - - -#endif // GLTEXTUREARRAY_H diff --git a/qglengine/core/gltransform.cpp b/qglengine/core/gltransform.cpp deleted file mode 100644 index d92ebb7..0000000 --- a/qglengine/core/gltransform.cpp +++ /dev/null @@ -1,441 +0,0 @@ -/* - QGL Transform - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - - -#include "gltransform.h" -#include "gltypes.h" -#include - - -inline void composeQMatrix4x4(const QVector3D & position, const QVector3D & orientation, const QVector3D & scale, QMatrix4x4 &m) { - const QMatrix3x3 rot3x3(Transform::toRotationMatrix(orientation)); - - // set up final matrix with scale, rotation and translation - m(0, 0) = scale.x() * rot3x3(0, 0); m(0, 1) = scale.y() * rot3x3(0, 1); m(0, 2) = scale.z() * rot3x3(0, 2); m(0, 3) = position.x(); - m(1, 0) = scale.x() * rot3x3(1, 0); m(1, 1) = scale.y() * rot3x3(1, 1); m(1, 2) = scale.z() * rot3x3(1, 2); m(1, 3) = position.y(); - m(2, 0) = scale.x() * rot3x3(2, 0); m(2, 1) = scale.y() * rot3x3(2, 1); m(2, 2) = scale.z() * rot3x3(2, 2); m(2, 3) = position.z(); - // no projection term - m(3, 0) = 0.0f; m(3, 1) = 0.0f; m(3, 2) = 0.0f; m(3, 3) = 1.0f; -} - -inline void decomposeQMatrix3x3(const QMatrix3x3 & m, QMatrix3x3 & Q, QVector3D & D, QVector3D & U) { - // Factor M = QR = QDU where Q is orthogonal, D is diagonal, - // and U is upper triangular with ones on its diagonal. - // Algorithm uses Gram-Schmidt orthogonalization (the QR algorithm). - // - // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then - // q0 = m0/|m0| - // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0| - // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1| - // - // where |V| indicates length of vector V and A*B indicates dot - // product of vectors A and B. The matrix R has entries - // - // r00 = q0*m0 r01 = q0*m1 r02 = q0*m2 - // r10 = 0 r11 = q1*m1 r12 = q1*m2 - // r20 = 0 r21 = 0 r22 = q2*m2 - // - // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00, - // u02 = r02/r00, and u12 = r12/r11. - - // Q = rotation - // D = scaling - // U = shear - - // D stores the three diagonal entries r00, r11, r22 - // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12 - - // build orthogonal matrix Q - float invLen = 1.0f / std::sqrt(m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0)); - Q(0, 0) = m(0, 0) * invLen; - Q(1, 0) = m(1, 0) * invLen; - Q(2, 0) = m(2, 0) * invLen; - - float dot = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1); - Q(0, 1) = m(0, 1) - dot * Q(0, 0); - Q(1, 1) = m(1, 1) - dot * Q(1, 0); - Q(2, 1) = m(2, 1) - dot * Q(2, 0); - invLen = 1.0f / std::sqrt(Q(0, 1) * Q(0, 1) + Q(1, 1) * Q(1, 1) + Q(2, 1) * Q(2, 1)); - Q(0, 1) *= invLen; - Q(1, 1) *= invLen; - Q(2, 1) *= invLen; - - dot = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2); - Q(0, 2) = m(0, 2) - dot * Q(0, 0); - Q(1, 2) = m(1, 2) - dot * Q(1, 0); - Q(2, 2) = m(2, 2) - dot * Q(2, 0); - dot = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2); - Q(0, 2) -= dot * Q(0, 1); - Q(1, 2) -= dot * Q(1, 1); - Q(2, 2) -= dot * Q(2, 1); - invLen = 1.0f / std::sqrt(Q(0, 2) * Q(0, 2) + Q(1, 2) * Q(1, 2) + Q(2, 2) * Q(2, 2)); - Q(0, 2) *= invLen; - Q(1, 2) *= invLen; - Q(2, 2) *= invLen; - - // guarantee that orthogonal matrix has determinant 1 (no reflections) - const float det = Q(0, 0) * Q(1, 1) * Q(2, 2) + Q(0, 1) * Q(1, 2) * Q(2, 0) + - Q(0, 2) * Q(1, 0) * Q(2, 1) - Q(0, 2) * Q(1, 1) * Q(2, 0) - - Q(0, 1) * Q(1, 0) * Q(2, 2) - Q(0, 0) * Q(1, 2) * Q(2, 1); - if (det < 0.0f) - Q *= -1.0f; - - // build "right" matrix R - QMatrix3x3 R(Qt::Uninitialized); - R(0, 0) = Q(0, 0) * m(0, 0) + Q(1, 0) * m(1, 0) + Q(2, 0) * m(2, 0); - R(0, 1) = Q(0, 0) * m(0, 1) + Q(1, 0) * m(1, 1) + Q(2, 0) * m(2, 1); - R(1, 1) = Q(0, 1) * m(0, 1) + Q(1, 1) * m(1, 1) + Q(2, 1) * m(2, 1); - R(0, 2) = Q(0, 0) * m(0, 2) + Q(1, 0) * m(1, 2) + Q(2, 0) * m(2, 2); - R(1, 2) = Q(0, 1) * m(0, 2) + Q(1, 1) * m(1, 2) + Q(2, 1) * m(2, 2); - R(2, 2) = Q(0, 2) * m(0, 2) + Q(1, 2) * m(1, 2) + Q(2, 2) * m(2, 2); - - // the scaling component - D[0] = R(0, 0); - D[1] = R(1, 1); - D[2] = R(2, 2); - - // the shear component - U[0] = R(0, 1) / D[0]; - U[1] = R(0, 2) / D[0]; - U[2] = R(1, 2) / D[1]; -} - -inline bool hasScale(const QMatrix4x4 &m) { - // If the columns are orthonormal and form a right-handed system, then there is no scale - float t(m.determinant()); - if (!qFuzzyIsNull(t - 1.0f)) - return true; - t = m(0, 0) * m(0, 0) + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0); - if (!qFuzzyIsNull(t - 1.0f)) - return true; - t = m(0, 1) * m(0, 1) + m(1, 1) * m(1, 1) + m(2, 1) * m(2, 1); - if (!qFuzzyIsNull(t - 1.0f)) - return true; - t = m(0, 2) * m(0, 2) + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2); - if (!qFuzzyIsNull(t - 1.0f)) - return true; - return false; -} - -inline void decomposeQMatrix4x4(const QMatrix4x4 & m, QVector3D & position, QVector3D & orientation, QVector3D & scale) { - Q_ASSERT(m.isAffine()); - - const QMatrix3x3 m3x3(m.toGenericMatrix<3, 3>()); - - QMatrix3x3 rot3x3(Qt::Uninitialized); - if (hasScale(m)) { - decomposeQMatrix3x3(m3x3, rot3x3, scale, position); - } else { - // we know there is no scaling part; no need for QDU decomposition - scale = QVector3D(1.0f, 1.0f, 1.0f); - rot3x3 = m3x3; - } - orientation = Transform::fromRotationMatrix(rot3x3); - position = QVector3D(m(0, 3), m(1, 3), m(2, 3)); -} - - - - -Transform::Transform(): m_scale(1.0f, 1.0f, 1.0f), - m_translation(), m_eulerRotationAngles(), m_matrixDirty(false) { -} - - -Transform & Transform::operator =(const Transform & t) { - m_scale = t.m_scale; - m_translation = t.m_translation; - m_eulerRotationAngles = t.m_eulerRotationAngles; - m_matrixDirty = true; - return *this; -} - - -void Transform::setMatrix(const QMatrix4x4 & m) { - if (m != matrix()) { - m_matrix = m; - m_matrixDirty = false; - QVector3D s; - QVector3D t; - QVector3D r; - decomposeQMatrix4x4(m, t, r, s); - m_scale = s; - m_translation = t; - m_eulerRotationAngles = r; - } -} - - -void Transform::setRotationX(float r) { - if (m_eulerRotationAngles.x() == r) - return; - m_eulerRotationAngles.setX(r); - m_matrixDirty = true; -} - - -void Transform::setRotationY(float r) { - if (m_eulerRotationAngles.y() == r) - return; - m_eulerRotationAngles.setY(r); - m_matrixDirty = true; -} - - -void Transform::setRotationZ(float r) { - if (m_eulerRotationAngles.z() == r) - return; - m_eulerRotationAngles.setZ(r); - m_matrixDirty = true; -} - - -QMatrix4x4 Transform::matrix() const { - buildMatrix(); - return m_matrix; -} - - -QMatrix4x4 Transform::matrixRotate() const { - buildMatrix(); - return m_matrixR; -} - - -QMatrix4x4 Transform::matrixScale() const { - buildMatrix(); - return m_matrixS; -} - - -QMatrix4x4 Transform::matrixRotateScale() const { - buildMatrix(); - return m_matrixWT; -} - - -QVector3D Transform::direction() const { - return matrixRotate().mapVector(QVector3D(0,0,-1)).normalized(); -} - - -void Transform::buildMatrix() const { - if (m_matrixDirty) { - composeQMatrix4x4(m_translation, m_eulerRotationAngles, m_scale, m_matrix); - composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, m_scale, m_matrixWT); - composeQMatrix4x4(QVector3D(), m_eulerRotationAngles, QVector3D(1,1,1), m_matrixR); - composeQMatrix4x4(QVector3D(), QVector3D(), m_scale, m_matrixS); - m_matrixDirty = false; - } -} - - -float Transform::rotationX() const { - return m_eulerRotationAngles.x(); -} - - -float Transform::rotationY() const { - return m_eulerRotationAngles.y(); -} - - -float Transform::rotationZ() const { - return m_eulerRotationAngles.z(); -} - - -void Transform::setScale(const QVector3D & s) { - if (s != m_scale) { - m_scale = s; - m_matrixDirty = true; - } -} - - -void Transform::setScaleX(float s) { - if (s != m_scale.x()) { - m_scale.setX(s); - m_matrixDirty = true; - } -} - - -void Transform::setScaleY(float s) { - if (s != m_scale.y()) { - m_scale.setY(s); - m_matrixDirty = true; - } -} - - -void Transform::setScaleZ(float s) { - if (s != m_scale.z()) { - m_scale.setZ(s); - m_matrixDirty = true; - } -} - - -QVector3D Transform::scale3D() const { - return m_scale; -} - - -float Transform::scale() const { - return m_scale.x(); -} - - -void Transform::setRotation(const QVector3D & r) { - if (r != m_eulerRotationAngles) { - m_eulerRotationAngles = r; - m_matrixDirty = true; - } -} - - -QVector3D Transform::rotation() const { - return m_eulerRotationAngles; -} - - -void Transform::setTranslation(const QVector3D & t) { - if (t != m_translation) { - m_translation = t; - m_matrixDirty = true; - } -} - - -void Transform::setTranslationX(float t) { - if (t != m_translation.x()) { - m_translation.setX(t); - m_matrixDirty = true; - } -} - - -void Transform::setTranslationY(float t) { - if (t != m_translation.y()) { - m_translation.setY(t); - m_matrixDirty = true; - } -} - - -void Transform::setTranslationZ(float t) { - if (t != m_translation.z()) { - m_translation.setZ(t); - m_matrixDirty = true; - } -} - - -QVector3D Transform::translation() const { - return m_translation; -} - - -QQuaternion Transform::fromAxisAndAngle(const QVector3D & axis, float angle) { - return QQuaternion::fromAxisAndAngle(axis, angle); -} - - -QQuaternion Transform::fromAxisAndAngle(float x, float y, float z, float angle) { - return QQuaternion::fromAxisAndAngle(x, y, z, angle); -} - - -QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1, - const QVector3D & axis2, float angle2) { - const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); - const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); - return q2 * q1; -} - - -QQuaternion Transform::fromAxesAndAngles(const QVector3D & axis1, float angle1, - const QVector3D & axis2, float angle2, - const QVector3D & axis3, float angle3) { - const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); - const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); - const QQuaternion q3 = QQuaternion::fromAxisAndAngle(axis3, angle3); - return q3 * q2 * q1; -} - - -QQuaternion Transform::fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) { - return QQuaternion::fromAxes(xAxis, yAxis, zAxis); -} - - -QVector3D Transform::fromDirection(QVector3D d, float pitch) { - QVector3D ret; - d.normalize(); - ret[0] = M_PI - acos(d.z()); - ret[1] = pitch * deg2rad; - ret[2] = -atan2(d.x(), d.y()); - normalizeAngleRad(ret[0]); - normalizeAngleRad(ret[2]); - return ret * rad2deg; -} - - -QVector3D Transform::fromRotationMatrix(const QMatrix3x3 & m) { - //return QQuaternion::fromRotationMatrix(m); - float sy = sqrt(m(0,0) * m(0,0) + m(1,0) * m(1,0)); - bool singular = sy < 1.E-6; // If - float x, y, z; - if (!singular) { - x = atan2( m(2,1), m(2,2)); - y = atan2(-m(2,0), sy); - z = atan2( m(1,0), m(0,0)); - } else { - x = atan2(-m(1,2), m(1,1)); - y = atan2(-m(2,0), sy); - z = 0.; - } - return QVector3D(x, y, z) * rad2deg; -} - - -QMatrix3x3 Transform::toRotationMatrix(const QVector3D & r) { - QMatrix4x4 m; - if (r.z() != 0.f) m.rotate(r.z(), 0., 0., 1.); - if (r.y() != 0.f) m.rotate(r.y(), 0., 1., 0.); - if (r.x() != 0.f) m.rotate(r.x(), 1., 0., 0.); - return m.toGenericMatrix<3,3>(); -} - - -QMatrix4x4 Transform::rotateAround(const QVector3D & point, float angle, const QVector3D & axis) { - QMatrix4x4 m; - m.translate(point); - m.rotate(angle, axis); - m.translate(-point); - return m; -} - - -QMatrix4x4 Transform::rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis) { - return QMatrix4x4(xAxis.x(), yAxis.x(), zAxis.x(), 0.0f, - xAxis.y(), yAxis.y(), zAxis.y(), 0.0f, - xAxis.z(), yAxis.z(), zAxis.z(), 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); -} diff --git a/qglengine/core/gltransform.h b/qglengine/core/gltransform.h deleted file mode 100644 index f1e42de..0000000 --- a/qglengine/core/gltransform.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - QGL Transform - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLTRANSFORM_H -#define GLTRANSFORM_H - -#include -#include -#include -#include - - -class Transform { - friend QDataStream & operator >>(QDataStream & s, Transform & v); -public: - Transform(); - Transform & operator =(const Transform & t); - - float scale() const; - QVector3D scale3D() const; - QVector3D rotation() const; - QVector3D translation() const; - QMatrix4x4 matrix() const; - QMatrix4x4 matrixRotate() const; - QMatrix4x4 matrixScale() const; - QMatrix4x4 matrixRotateScale() const; - QVector3D direction() const; - - float rotationX() const; - float rotationY() const; - float rotationZ() const; - - void setScale(float s) {setScale(QVector3D(s, s, s));} - void setScale(const QVector3D & s); - void setScaleX(float s); - void setScaleY(float s); - void setScaleZ(float s); - - void setRotation(const QVector3D & r); - void setRotationX(float r); - void setRotationY(float r); - void setRotationZ(float r); - - void setTranslation(const QVector3D & t); - void setTranslationX(float t); - void setTranslationY(float t); - void setTranslationZ(float t); - - void setMatrix(const QMatrix4x4 & matrix); - void setDirty(bool yes = true) {m_matrixDirty = yes;} - - - static QQuaternion fromAxisAndAngle(const QVector3D & axis, float angle); - static QQuaternion fromAxisAndAngle(float x, float y, float z, float angle); - - static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1, - const QVector3D & axis2, float angle2); - static QQuaternion fromAxesAndAngles(const QVector3D & axis1, float angle1, - const QVector3D & axis2, float angle2, - const QVector3D & axis3, float angle3); - static QQuaternion fromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis); - - static QVector3D fromDirection(QVector3D d, float pitch = 0.f); - static QVector3D fromRotationMatrix(const QMatrix3x3 & m); - static QMatrix3x3 toRotationMatrix(const QVector3D & r); - - static QMatrix4x4 rotateAround(const QVector3D & point, float angle, const QVector3D & axis); - static QMatrix4x4 rotateFromAxes(const QVector3D & xAxis, const QVector3D & yAxis, const QVector3D & zAxis); - -protected: - void buildMatrix() const; - - QVector3D m_scale; - QVector3D m_translation; - QVector3D m_eulerRotationAngles; - - mutable QMatrix4x4 m_matrix, m_matrixWT, m_matrixR, m_matrixS; - mutable bool m_matrixDirty; - -}; - - -inline QDataStream & operator <<(QDataStream & s, const Transform & v) { - //ChunkStream cs; - //cs.add(1, v.matrix()); - //s << cs.data(); return s; - s << v.matrix(); return s; -} -inline QDataStream & operator >>(QDataStream & s, Transform & v) { - //ChunkStream cs(s); - //while (!cs.atEnd()) { - // switch (cs.read()) { - // case 1: v.setMatrix(cs.getData()); break; - // } - //} - //return s; - QMatrix4x4 m; - s >> m; - v.setMatrix(m); - v.m_matrixDirty = true; - return s; -} - -#endif // QT3DCORE_QTRANSFORM_H diff --git a/qglengine/core/gltypes.cpp b/qglengine/core/gltypes.cpp deleted file mode 100644 index 22493de..0000000 --- a/qglengine/core/gltypes.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - QGLView Types - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "glcamera.h" -#include "qglview.h" -#include "gltexture_manager.h" - -#include - -//__GLWidget__ * currentQGLView; -//QMutex globMutex; - - -QString readCharsUntilNull(QDataStream & s) { - QString str; - char ch; - s.readRawData(&ch, 1); - while (ch != '\0') { - str += ch; - s.readRawData(&ch, 1); - } - return str; -} - - -QString findFile(const QString & file, const QStringList & pathes) { - QFileInfo fi(QString(file).replace("\\", "/")); - //qDebug() << "search" << file << "in" << pathes; - if (fi.exists()) return fi.absoluteFilePath(); - QString fn = fi.fileName(); - if (fn.contains("/")) fn = fn.mid(fn.lastIndexOf("/")); - foreach (QString p, pathes) { - QFileInfoList fil = QDir(p).entryInfoList(QStringList(fn), QDir::Files | QDir::NoDotAndDotDot); - //qDebug() << "findFile" << fn << "in" << p << "->" << fil.size(); - if (!fil.isEmpty()) - return fil[0].absoluteFilePath(); - } - return QString(); -} - - -void glDrawQuad(QOpenGLShaderProgram * prog, QVector4D * corner_dirs, GLfloat x, GLfloat y, GLfloat w, GLfloat h) { - //glResetAllTransforms(); - glSetPolygonMode(GL_FILL); - glDisable(GL_LIGHTING); - glEnable(GL_TEXTURE_2D); - int loc = prog ? prog->attributeLocation("qgl_Color") : -1, - locv = prog ? prog->attributeLocation("qgl_Vertex") : -1, - loct = prog ? prog->attributeLocation("qgl_Texture") : -1, - locc = prog ? prog->attributeLocation("view_corner") : -1; - //if (prog) {qDebug() << locv << loct << locc;} - QOpenGLFunctions * glFuncs = QOpenGLContext::currentContext()->functions(); - if (prog) { - static const GLfloat cols [] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f}; - static const GLfloat verts[] = {x, y, x+w, y, x, y+h, x+w, y+h}; - static const GLfloat texs [] = {0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f}; - GLfloat vcs[] = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}; - if (corner_dirs) { - vcs[0] = corner_dirs[0].x(); vcs[1] = corner_dirs[0].y(); vcs[2] = corner_dirs[0].z(); - vcs[3] = corner_dirs[1].x(); vcs[4] = corner_dirs[1].y(); vcs[5] = corner_dirs[1].z(); - vcs[6] = corner_dirs[2].x(); vcs[7] = corner_dirs[2].y(); vcs[8] = corner_dirs[2].z(); - vcs[9] = corner_dirs[3].x(); vcs[10] = corner_dirs[3].y(); vcs[11] = corner_dirs[3].z(); - } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glFuncs->glBindBuffer(GL_ARRAY_BUFFER, 0); - glFuncs->glEnableVertexAttribArray(loc); - glFuncs->glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, cols); - glFuncs->glEnableVertexAttribArray(locv); - glFuncs->glVertexAttribPointer(locv, 2, GL_FLOAT, 0, 0, verts); - glFuncs->glEnableVertexAttribArray(loct); - glFuncs->glVertexAttribPointer(loct, 2, GL_FLOAT, 0, 0, texs); - glFuncs->glEnableVertexAttribArray(locc); - glFuncs->glVertexAttribPointer(locc, 3, GL_FLOAT, 0, 0, vcs); - glFuncs->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glFuncs->glDisableVertexAttribArray(loc); - glFuncs->glDisableVertexAttribArray(locv); - glFuncs->glDisableVertexAttribArray(loct); - glFuncs->glDisableVertexAttribArray(locc); - } else { - glBegin(GL_TRIANGLE_STRIP); - glColor4f(1.f, 1.f, 1.f, 1.f); - glTexCoord2f(0.f, 0.f); glVertex2f(x, y); - glTexCoord2f(1.f, 0.f); glVertex2f(x+w, y); - glTexCoord2f(0.f, 1.f); glVertex2f(x, y+h); - glTexCoord2f(1.f, 1.f); glVertex2f(x+w, y+h); - glEnd(); - } -} - - -QMatrix4x4 getGLMatrix(GLenum matrix) { - GLfloat gm[16]; - glGetFloatv(matrix, gm); - float qm[16]; - for (int i = 0; i < 16; ++i) - qm[i] = gm[i]; - return QMatrix4x4(qm).transposed(); -} - - -void setGLMatrix(QMatrix4x4 matrix) { - GLfloat gm[16]; - float qm[16]; - matrix.transposed().copyDataTo(qm); - for (int i = 0; i < 16; ++i) - gm[i] = qm[i]; - glLoadMatrixf(gm); -} - - -void qglMultMatrix(const QMatrix4x4 & m) { - GLfloat gm[16]; - float qm[16]; - m.transposed().copyDataTo(qm); - for (int i = 0; i < 16; ++i) - gm[i] = qm[i]; - glMultMatrixf(gm); -} - - -void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int height, const GLenum & format, const GLenum & target) { - //glClearError(); - if (tex == 0) { - f->glGenTextures(1, &tex); - f->glBindTexture(target, tex); - } - //glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_COMPONENT16 || format == GL_DEPTH_COMPONENT24 || format == GL_DEPTH_COMPONENT32) - f->glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr); - else { - int type = GL_UNSIGNED_BYTE; - int fmt = GL_RGBA; - if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGBA32F || format == GL_RGBA16F) - type = GL_FLOAT; - if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGB8 || format == GL_RGB) - fmt = GL_RGB; - f->glTexImage2D(target, 0, format, width, height, 0, fmt, type, nullptr); - //glGenerateMipmap(target); - //qDebug() << "glTexImage2D" << width << height << QString::number(t, 16); - } - //qDebug() << QString::number(glGetError(), 16); -} - - -void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & image, const GLenum & format, const GLenum & target) { - if (tex == 0) { - f->glGenTextures(1, &tex); - } - f->glBindTexture(target, tex); - QImage im = image.mirrored(false, true).convertToFormat(QImage::Format_RGBA8888); - //const QImage & cim(im); - f->glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT); - f->glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT); - f->glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT); - if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) { - f->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - f->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - f->glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8); - } else { - f->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - f->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - glClearError(); - f->glTexImage2D(target, 0, format, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.constBits()); - if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D || target == GL_TEXTURE_3D) { - f->glGenerateMipmap(target); - } - //qDebug() << target << format << tex << im.width() << im.height() << im.bits() << QString::number(glGetError(), 16); -} - - -QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_) { - QMatrix4x4 ret; - float t = 1.f / (tanf(angle * deg2rad / 2.f)), e = 2.4e-7f; - if (aspect >= 1.) { - ret(0, 0) = t / aspect; - ret(1, 1) = t; - } else { - ret(0, 0) = t; - ret(1, 1) = t * aspect; - } - ret(2, 2) = e - 1.f;//far_ / (far_ - near_) - 1.; - ret(2, 3) = (e - 2.f) * near_;//2. * far_ * near_ / (far_ - near_); - ret(3, 2) = -1.f; - ret(3, 3) = 0.f; - return ret; -} - - -QImage rotateQImageLeft(const QImage & im) { - QImage ri(im.height(), im.width(), im.format()); - QPainter p(&ri); - p.rotate(90); - p.drawImage(0, -im.height(), im); - p.end(); - return ri; -} - - -QImage rotateQImageRight(const QImage & im) { - QImage ri(im.height(), im.width(), im.format()); - QPainter p(&ri); - p.rotate(-90); - p.drawImage(-im.width(), 0, im); - p.end(); - return ri; -} - - - - -QColor colorFromString(const QString & str) { - QString s = str.trimmed(); - int i = s.indexOf("\t"); - float r, g, b; - r = s.left(i).toFloat(); s = s.right(s.length() - i - 1); i = s.indexOf("\t"); - g = s.left(i).toFloat(); s = s.right(s.length() - i - 1); - b = s.toFloat(); - return QColor(r * 255.f, g * 255.f, b * 255.f); -} - - -QVector3D orthToVector(const QVector3D & v, const float & scale) { - if (v.isNull()) return QVector3D(); - QVector3D rv, fn, sn; - if (v.x() != 0.f) rv.setZ(1.); - else if (v.y() != 0.f) rv.setX(1.); - else rv.setY(1.); - fn = QVector3D::crossProduct(v, rv).normalized(); - sn = QVector3D::crossProduct(v, fn).normalized(); - return fn * urand(scale) + sn * urand(scale); -} - - -QVector3D rotateVector(const QVector3D & v, const QVector3D & a) { - QMatrix4x4 m; - m.rotate(a.z(), 0., 0., 1.); - m.rotate(a.y(), 0., 1., 0.); - m.rotate(a.x(), 1., 0., 0.); - return m * v; -} - - -void setVectorLength(QVector3D & v, const float & l) { - float vl = v.length(); - if (vl == 0.f) return; - float c = l / vl; - v *= c; -} - - -void lengthenVector(QVector3D & v, const float & l) { - float vl = v.length(); - if (l == 0.f || vl == 0.f) return; - float c = 1.f + l / vl; - v *= c; -} - - -Vector2i::Vector2i(const QString & str) { - QString s = str.trimmed(); - int i = s.indexOf("\t"); - p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); - p1 = s.toInt(); -} - - -Vector3i::Vector3i(const QString & str) { - QString s = str.trimmed(); - int i = s.indexOf("\t"); - p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1); i = s.indexOf("\t"); - p1 = s.left(i).toInt(); s = s.right(s.length() - i - 1); - p2 = s.toInt(); -} - - -void glEnableDepth() { - glEnable(GL_DEPTH_TEST); - //glDepthFunc(GL_GREATER); - glDepthFunc(GL_LESS); - glDepthMask(GL_TRUE); -} - - -void glDisableDepth() { - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); -} - - -void glClearFramebuffer(const QColor & color, bool depth) { - glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); - //glClearDepth(0.); - if (depth) - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - glClear(GL_COLOR_BUFFER_BIT); -} - - - - -Box3D::Box3D(const QVector & points) { - x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f; - if (points.isEmpty()) return; - float ix, iy, iz, ax, ay, az; - ix = ax = points[0].x(); - iy = ay = points[0].y(); - iz = az = points[0].z(); - for (int i = 1; i < points.size(); ++i) { - ix = qMin(ix, points[i].x()); ax = qMax(ax, points[i].x()); - iy = qMin(iy, points[i].y()); ay = qMax(ay, points[i].y()); - iz = qMin(iz, points[i].z()); az = qMax(az, points[i].z()); - } - x = ix; - y = iy; - z = iz; - length = ax - ix; - width = ay - iy; - height = az - iz; -} - - -QVector Box3D::corners() const { - QVector ret; - ret << QVector3D(x, y, z) << QVector3D(x, y + width, z) << QVector3D(x, y, z + height) << QVector3D(x, y + width, z + height) - << QVector3D(x + length, y, z) << QVector3D(x + length, y + width, z) - << QVector3D(x + length, y, z + height) << QVector3D(x + length, y + width, z + height); - return ret; -} - - -Box3D & Box3D::operator |=(const Box3D & o) { - if (o.isEmpty()) return *this; - if (isEmpty()) *this = o; - else { - GLfloat mx = x + length, my = y + width, mz = z + height; - GLfloat omx = o.x + o.length, omy = o.y + o.width, omz = o.z + o.height; - x = qMin(x, o.x); y = qMin(y, o.y); z = qMin(z, o.z); - mx = qMax(mx, omx); my = qMax(my, omy); mz = qMax(mz, omz); - length = mx - x; width = my - y; height = mz - z; - } - return *this; -} - - -QVector3D vectorFromString(const QString & str) { - QTextStream s(const_cast(&str), QIODevice::ReadOnly); - QVector3D ret; - float f(0.f); - s >> f; ret.setX(f); - s >> f; ret.setY(f); - s >> f; ret.setZ(f); - return ret; -} diff --git a/qglengine/core/gltypes.h b/qglengine/core/gltypes.h deleted file mode 100644 index 5550643..0000000 --- a/qglengine/core/gltypes.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - QGLView Types - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLTYPES_H -#define GLTYPES_H - -#if WIN32 || WIN64 || _WIN32 || _WIN64 || __WIN32__ || __WIN64__ -# define WINDOWS -#endif -#if __QNX__ || __QNXNTO__ -# define QNX -#endif -#ifdef __APPLE__ -# define MAC -#endif -#ifndef WINDOWS -# ifndef QNX -# ifndef MAC -# define LINUX -# endif -# endif -#endif -#if __GNUC__ -# define CC_GCC -#elif _MSC_VER -# define CC_VC -#endif - - -#include -//#ifndef WINDOWS -//# ifdef MAC -//# include -//# include -//# include -//# else -//# include -//# include -//# include -//# endif -//#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef QNX -# include -# include -#else -# include -# include -#endif -#include -#include "qglengine_version.h" - - -//#ifdef WINDOWS -//# define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -//# define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -//#endif - -#ifndef M_PI -# define M_PI 3.14159265358979323846 -#endif -#ifndef M_2PI -# define M_2PI 6.28318530717958647692 -#endif -#ifndef M_PI_3 -# define M_PI_3 1.04719755119659774615 -#endif - -#ifndef GL_RGBA16F -# define GL_RGBA16F GL_RGBA16F_ARB -#endif - -using std::complex; - -#ifndef PIP_VERSION -typedef long long llong; -typedef unsigned char uchar; -typedef unsigned short int ushort; -typedef unsigned int uint; -typedef unsigned long ulong; -typedef unsigned long long ullong; -typedef long double ldouble; - -const float deg2rad = atanf(1.f) / 45.f; -const float rad2deg = 45.f / atanf(1.f); - -# ifdef WINDOWS -inline int random() {return rand();} -# endif -#else -#define random randomi -#endif - -#ifdef CC_VC -inline float round(const float & v) {return floor(v + 0.5);} -#endif -inline float randomu() {return float(random()) / RAND_MAX;} - -inline const QSizeF operator *(const QSizeF & f, const QSizeF & s) {return QSizeF(f.width() * s.width(), f.height() * s.height());} -#ifndef PIP_VERSION -template inline void piSwap(T & f, T & s) {T t(f); f = s; s = t;} -template inline Type piMin(const Type & f, const Type & s) {return (f > s) ? s : f;} -template inline Type piMin(const Type & f, const Type & s, const Type & t) {return (f < s && f < t) ? f : ((s < t) ? s : t);} -template inline Type piMax(const Type & f, const Type & s) {return (f < s) ? s : f;} -template inline Type piMax(const Type & f, const Type & s, const Type & t) {return (f > s && f > t) ? f : ((s > t) ? s : t);} -template inline Type piClamp(const Type & v, const Type & min, const Type & max) {return (v > max ? max : (v < min ? min : v));} -inline ushort letobe_s(ushort v) {return (v << 8) | (v >> 8);} -inline uint letobe_i(const uint & v) {return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000);} -#endif -// return [-1, 1] -inline float urand(const float & scale = 1.) {return ((float)rand() / RAND_MAX - .5f) * (scale + scale);} -// return [0, 1] -inline float uprand(const float & scale = 1.) {return ((float)rand() / RAND_MAX) * scale;} -QString readCharsUntilNull(QDataStream & s); -QString findFile(const QString & file, const QStringList & pathes); -inline QColor operator *(const QColor & c, float v) {return QColor(piClamp(c.red() * v, 0, 255), piClamp(c.green() * v, 0, 255), piClamp(c.blue() * v, 0, 255), piClamp(c.alpha() * v, 0, 255));} -inline QColor operator /(const QColor & c, float v) {return QColor(piClamp(c.red() / v, 0, 255), piClamp(c.green() / v, 0, 255), piClamp(c.blue() / v, 0, 255), piClamp(c.alpha() / v, 0, 255));} - - -inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());} -inline void glClearError() {int c = 100; while (glGetError() != GL_NO_ERROR && --c > 0) glGetError();} -inline void glSetCapEnabled(GLenum cap, bool on = true) {if (on) glEnable(cap); else glDisable(cap);} -inline void glSetPolygonMode(GLenum mode) {glPolygonMode(GL_FRONT_AND_BACK, mode);} -inline void deleteGLTexture(QOpenGLExtraFunctions * f, GLuint & tex) {if (tex != 0) f->glDeleteTextures(1, &tex); tex = 0;} -void glEnableDepth(); -void glDisableDepth(); -void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true); -void glDrawQuad(QOpenGLShaderProgram * prog = nullptr, QVector4D * corner_dirs = nullptr, GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f); -void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, int width, int height, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); -void createGLTexture(QOpenGLExtraFunctions * f, GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA, const GLenum & target = GL_TEXTURE_2D); -QMatrix4x4 glMatrixPerspective(float angle, float aspect, float near_); -QImage rotateQImageLeft(const QImage & im); -QImage rotateQImageRight(const QImage & im); -inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);} - -class QGLView; -class MouseController; -class ObjectBase; -class AimedObject; -class Light; -class Camera; -class Texture; -class CubeTexture; -class Map; -class Material; -class TextureManager; -class Texture2DArray; -class Framebuffer; -class FramebufferMipmap; -class VertexObject; -class Mesh; -class Scene; -class RendererBase; -class Renderer; -class RendererMaterial; -class RendererService; -class RendererSelection; - -enum RenderPass { - rpSolid, - rpTransparent, -}; - -typedef QList ObjectBaseList; - -struct Box3D { - GLfloat x; - GLfloat y; - GLfloat z; - GLfloat width; - GLfloat length; - GLfloat height; - GLfloat angle_z; - GLfloat angle_xy; - GLfloat angle_roll; - Box3D() {x = y = z = width = length = height = angle_z = angle_xy = angle_roll = 0.f;} - Box3D(const QVector3D & center, GLfloat hwid, GLfloat hlen, GLfloat hhei) {x = center.x() - hwid; y = center.y() - hlen; z = center.z() - hhei; width = 2 * hwid; length = 2 * hlen; height = 2 * hhei; angle_z = angle_xy = angle_roll = 0.f;} - Box3D(const QVector & points); - bool isEmpty() const {return (qAbs(width) < 1E-6f) && (qAbs(length) < 1E-6f) && (qAbs(height) < 1E-6f);} - QVector3D randomPoint() const {return QVector3D(uprand(length) + x, uprand(width) + y, uprand(height) + z);} - QVector3D pos() const {return QVector3D(x, y, z);} - QVector3D size() const {return QVector3D(length, width, height);} - QVector3D center() const {return QVector3D(length / 2.f + x, width / 2.f + y, height / 2.f + z);} - QVector3D angles() const {return QVector3D(angle_xy, angle_roll, angle_z);} - QVector corners() const; - void setPos(const QVector3D & p) {x = p.x(); y = p.y(); z = p.z();} - void setAngles(const QVector3D & a) {angle_xy = a.x(); angle_roll = a.y(); angle_z = a.z();} - void setSize(const QVector3D & s) {length = s.x(); width = s.y(); height = s.z();} - Box3D & moveTo(const QVector3D & v) {x = v.x(); y = v.y(); z = v.z(); return *this;} - Box3D & move(const QVector3D & v) {x += v.x(); y += v.y(); z += v.z(); return *this;} - Box3D movedTo(const QVector3D & v) const {Box3D t(*this); t.x = v.x(); t.y = v.y(); t.z = v.z(); return t;} - Box3D moved(const QVector3D & v) const {Box3D t(*this); t.x += v.x(); t.y += v.y(); t.z += v.z(); return t;} - Box3D & operator |=(const Box3D & o); -}; - -inline QDebug operator <<(QDebug d, const Box3D & v) {d << "Box3D {start (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}"; return d;} - - -#pragma pack(push, 1) -struct Vector2i { - Vector2i(int p0_ = 0, int p1_ = 0) {p0 = p0_; p1 = p1_;} - Vector2i(const QString & str); - Vector2i movedX(const int & o) {return Vector2i(p0 + o, p1);} - Vector2i movedY(const int & o) {return Vector2i(p0, p1 + o);} - Vector2i moved(const int & x, const int & y) {return Vector2i(p0 + x, p1 + y);} - GLint p0; - GLint p1; - bool operator ==(const Vector2i & o) const {return p0 == o.p0 && p1 == o.p1;} - bool operator !=(const Vector2i & o) const {return p0 != o.p0 || p1 != o.p1;} - void operator +=(int v) {p0 += v; p1 += v;} - QVector2D toQVector2D() const {return QVector2D(p0, p1);} -}; -#pragma pack(pop) - -inline Vector2i operator +(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 + s.p0, f.p1 + s.p1);} -inline Vector2i operator -(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 - s.p0, f.p1 - s.p1);} -inline Vector2i operator /(const Vector2i & f, const int & s) {return Vector2i(f.p0 / s, f.p1 / s);} -inline uint qHash(const Vector2i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24));} -inline QDebug operator <<(QDebug d, const Vector2i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << "}"; return d.space();} - -inline QDataStream & operator <<(QDataStream & s, const Vector2i & v) {s << v.p0 << v.p1; return s;} -inline QDataStream & operator >>(QDataStream & s, Vector2i & v) {s >> v.p0 >> v.p1; return s;} - - -#pragma pack(push, 1) -struct Vector3i { - Vector3i(int p0_ = 0, int p1_ = 0, int p2_ = 0) {p0 = p0_; p1 = p1_; p2 = p2_;} - Vector3i(const QString & str); - Vector3i movedX(const int & o) {return Vector3i(p0 + o, p1, p2);} - Vector3i movedY(const int & o) {return Vector3i(p0, p1 + o, p2);} - Vector3i movedZ(const int & o) {return Vector3i(p0, p1, p2 + o);} - Vector3i moved(const int & x, const int & y, const int & z) {return Vector3i(p0 + x, p1 + y, p2 + z);} - GLint p0; - GLint p1; - GLint p2; - bool operator ==(const Vector3i & o) const {return p0 == o.p0 && p1 == o.p1 && p2 == o.p2;} - bool operator !=(const Vector3i & o) const {return p0 != o.p0 || p1 != o.p1 || p2 != o.p2;} - void operator +=(int v) {p0 += v; p1 += v; p2 += v;} - QVector3D toQVector3D() const {return QVector3D(p0, p1, p2);} -}; -#pragma pack(pop) - -inline Vector3i operator +(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 + s.p0, f.p1 + s.p1, f.p2 + s.p2);} -inline Vector3i operator -(const Vector3i & f, const Vector3i & s) {return Vector3i(f.p0 - s.p0, f.p1 - s.p1, f.p2 - s.p2);} -inline Vector3i operator /(const Vector3i & f, const int & s) {return Vector3i(f.p0 / s, f.p1 / s, f.p2 / s);} -inline uint qHash(const Vector3i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24)) ^ ((v.p2 << 16) | (v.p2 >> 16));} -inline QDebug operator <<(QDebug d, const Vector3i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << ", " << v.p2 << "}"; return d.space();} - -inline QDataStream & operator <<(QDataStream & s, const Vector3i & v) {s << v.p0 << v.p1 << v.p2; return s;} -inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;} - - -QVector3D vectorFromString(const QString & str); -QColor colorFromString(const QString & str); -inline QVector4D QColor2QVector(const QColor & c) {return QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF());} -inline float cosABV(const QVector3D & v0, const QVector3D & v1) { - float l = v0.length() * v1.length(); - if (l == 0.f) return 0.; - return (QVector3D::dotProduct(v0, v1)) / l; -} -inline void normalizeAngleRad(float & a) {while (a < 0.) a += M_2PI; while (a >= M_2PI) a -= M_2PI;} -inline void normalizeAngleDeg(float & a) {while (a < 0.) a += 360. ; while (a >= 360. ) a -= 360. ;} -inline QVector3D projection(const QVector3D & v, const QVector3D & to) {return to.normalized() * v.length() * cosABV(v, to);} -QVector3D orthToVector(const QVector3D & v, const float & scale = 1.); -QVector3D rotateVector(const QVector3D & v, const QVector3D & a); -void setVectorLength(QVector3D & v, const float & l); -void lengthenVector(QVector3D & v, const float & l); -inline float squareLength(const QVector3D & from, const QVector3D & to) {return (to.x() - from.x())*(to.x() - from.x()) + (to.y() - from.y())*(to.y() - from.y()) + (to.z() - from.z())*(to.z() - from.z());} -inline QVector3D directionFromAngles(const QVector3D & a) {return rotateVector(QVector3D(1., 0., 0.), a);} -inline float frac(const float & x, const float & b) {return x - int(x / b) * b;} - - -#endif // GLTYPES_H diff --git a/qglengine/core/glvertexobject.cpp b/qglengine/core/glvertexobject.cpp deleted file mode 100644 index e4a5437..0000000 --- a/qglengine/core/glvertexobject.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - QGL VertexObject - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "glvertexobject.h" - -using namespace QGLEngineShaders; - - -VertexObject::VertexObject(): - buffer_obj (GL_ARRAY_BUFFER, GL_STREAM_DRAW), - buffer_sel (GL_ARRAY_BUFFER, GL_STREAM_DRAW) { - vao_ = 0; - buffers_binded = false; - objects_changed = selected_changed = true; -} - - -VertexObject::~VertexObject() { -} - - -void VertexObject::init(QOpenGLExtraFunctions * f) { - if (!isInit()) { - buffer_obj.init(f); - buffer_sel.init(f); - f->glGenVertexArrays(1, &vao_); - } -} - - -void VertexObject::destroy(QOpenGLExtraFunctions * f) { - if (vao_ != 0) { - buffer_obj.destroy(f); - buffer_sel.destroy(f); - f->glDeleteVertexArrays(1, &vao_); - } - vao_ = 0; -} - - -void VertexObject::bind(QOpenGLExtraFunctions * f) { - //qDebug() << "bind" << target_ << buffer_; - f->glBindVertexArray(vao_); -} - - -void VertexObject::release(QOpenGLExtraFunctions * f) { - f->glBindVertexArray(0); -} - - -void VertexObject::bindBuffers(QOpenGLExtraFunctions * f, Buffer & geom, Buffer & elem, bool force) { - if (!force && buffers_binded) return; - buffers_binded = true; - - init(f); - bind(f); - - geom.bind(f); - prepareDrawGeom(f); - - elem.bind(f); - - buffer_obj.bind(f); - prepareDrawObj(f); - - buffer_sel.bind(f); - prepareDrawSel(f); - - release(f); -} - - -void VertexObject::loadObject(QOpenGLExtraFunctions * f, const Object & object) { - loadBuffer(f, buffer_obj, &object, sizeof(Object)); -} - - -void VertexObject::loadObjects(QOpenGLExtraFunctions * f, const QVector & objects) { - loadBuffer(f, buffer_obj, objects.constData(), objects.size() * sizeof(Object)); -} - - -void VertexObject::loadSelections(QOpenGLExtraFunctions * f, const QVector & sels) { - loadBuffer(f, buffer_sel, sels.constData(), sels.size()); -} - - -void VertexObject::draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count) { - bind(f); - f->glDrawElementsInstanced(geom_type, vert_cout, GL_UNSIGNED_INT, 0, obj_count); - release(f); -} - - -void VertexObject::loadBuffer(QOpenGLExtraFunctions * f, Buffer & buf, const void * data, int size) { - buf.init(f); - if (!data) return; - buf.bind(f); - buf.resize(f, size); - buf.load(f, data, size); -} diff --git a/qglengine/core/glvertexobject.h b/qglengine/core/glvertexobject.h deleted file mode 100644 index 58b0894..0000000 --- a/qglengine/core/glvertexobject.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - QGL VertexObject - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLVERTEXOBJECT_H -#define GLVERTEXOBJECT_H - -#include "glbuffer.h" -#include "glshaders_types.h" - - -class VertexObject -{ - friend class Mesh; -public: - VertexObject(); - ~VertexObject(); - - void init (QOpenGLExtraFunctions * f); - void destroy (QOpenGLExtraFunctions * f); - - void bind (QOpenGLExtraFunctions * f); - void release (QOpenGLExtraFunctions * f); - - void bindBuffers (QOpenGLExtraFunctions * f, Buffer & geom, Buffer & elem, bool force = false); - void loadObject (QOpenGLExtraFunctions * f, const QGLEngineShaders::Object & object); - void loadObjects (QOpenGLExtraFunctions * f, const QVector & objects); - void loadSelections(QOpenGLExtraFunctions * f, const QVector & sels); - - void draw(QOpenGLExtraFunctions * f, GLenum geom_type, int vert_cout, int obj_count); - - GLuint ID() const {return vao_;} - bool isInit() const {return vao_ != 0;} - - bool isObjectsChanged() const {return objects_changed;} - bool isSelectionChanged() const {return selected_changed;} - void setObjectsChanged(bool yes = true) {objects_changed = yes;} - void setSelectionChanged(bool yes = true) {selected_changed = yes;} - -private: - void loadBuffer(QOpenGLExtraFunctions * f, Buffer & buf, const void * data, int size); - - GLuint vao_; - Buffer buffer_obj, buffer_sel; - bool buffers_binded, objects_changed, selected_changed; - -}; - - -#endif // GLVERTEXOBJECT_H diff --git a/qglengine/core/hdr.cpp b/qglengine/core/hdr.cpp deleted file mode 100644 index d1e2248..0000000 --- a/qglengine/core/hdr.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - QGL HDR - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "hdr_p.h" -#include "qmath.h" - -#define RGBE_DATA_RED 2 -#define RGBE_DATA_GREEN 1 -#define RGBE_DATA_BLUE 0 -/* number of floats per pixel */ -#define RGBE_DATA_SIZE 3 - - -void rgbe2float(float *red, float *green, float *blue, uchar rgbe[4]) { - float f; - if (rgbe[3]) { - f = static_cast(ldexp(1.0,rgbe[3]-(int)(128+8))); - *red = rgbe[0] * f; - *green = rgbe[1] * f; - *blue = rgbe[2] * f; - } - else - *red = *green = *blue = 0.0; -} - - -/* simple read routine. will not correctly handle run length encoding */ -bool RGBE_ReadPixels(QDataStream * fp, float * data, int numpixels) { - uchar rgbe[4]; - while(numpixels-- > 0) { - if (fp->readRawData((char*)rgbe, sizeof(rgbe)) < 1) - return false; - rgbe2float(&data[RGBE_DATA_RED], &data[RGBE_DATA_GREEN], &data[RGBE_DATA_BLUE],rgbe); - data += RGBE_DATA_SIZE; - } - return true; -} - - -bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines) { - uchar rgbe[4], *ptr, *ptr_end; - int i, count; - uchar buf[2]; - QByteArray scanline_buffer; - - if ((scanline_width < 8)||(scanline_width > 0x7fff)) - /* run length encoding is not allowed so read flat*/ - return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines); - scanline_buffer.resize(4*scanline_width); - /* read in each successive scanline */ - while(num_scanlines > 0) { - if (fp->readRawData((char*)rgbe,sizeof(rgbe)) < 1) { - return false; - } - if ((rgbe[0] != 2)||(rgbe[1] != 2)||(rgbe[2] & 0x80)) { - /* this file is not run length encoded */ - rgbe2float(&data[RGBE_DATA_RED],&data[RGBE_DATA_GREEN],&data[RGBE_DATA_BLUE],rgbe); - data += RGBE_DATA_SIZE; - return RGBE_ReadPixels(fp,data,scanline_width*num_scanlines-1); - } - if ((((int)rgbe[2])<<8 | rgbe[3]) != scanline_width) { - return false; - } - ptr = (uchar*)scanline_buffer.data(); - /* read each of the four channels for the scanline into the buffer */ - for(i=0;i<4;i++) { - ptr_end = (uchar*)scanline_buffer.data() + ((i+1)*scanline_width); - while(ptr < ptr_end) { - if (fp->readRawData((char*)buf,sizeof(buf[0])*2) < 1) { - return false; - } - if (buf[0] > 128) { - /* a run of the same value */ - count = buf[0]-128; - if ((count == 0)||(count > ptr_end - ptr)) { - return false; - } - while(count-- > 0) - *ptr++ = buf[1]; - } - else { - /* a non-run */ - count = buf[0]; - if ((count == 0)||(count > ptr_end - ptr)) { - return false; - } - *ptr++ = buf[1]; - if (--count > 0) { - if (fp->readRawData((char*)ptr,sizeof(*ptr)*count) < 1) { - return false; - } - ptr += count; - } - } - } - } - /* now convert data from buffer into floats */ - for(i=0;i. -*/ - -#ifndef HDR_P_H -#define HDR_P_H - -#include - -bool RGBE_ReadPixels_RLE(QDataStream * fp, float * data, int scanline_width, int num_scanlines); - -#endif // HDR_P_H diff --git a/qglengine/formats/loader_assimp.cpp b/qglengine/formats/loader_assimp.cpp deleted file mode 100644 index fe53b77..0000000 --- a/qglengine/formats/loader_assimp.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - QGL Loader Assimp - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "loader_assimp.h" -#include "glscene.h" -#include "glmesh.h" -#include "glmaterial.h" -#include "globject.h" -#include -#include -#include -#include -#include - -QString fromAiString (const aiString & s) {return QString::fromLocal8Bit(s.C_Str());} -QColor fromAiColor (const aiColor4D & c) {return QColor::fromRgbF(piClamp(c.r, 0.f, 1.f), piClamp(c.g, 0.f, 1.f), piClamp(c.b, 0.f, 1.f));} -QVector3D fromAiVector3D(const aiVector3D & v) {return QVector3D(v.x, v.y, v.z);} - Vector3i fromAiFace (const aiFace & v) {return Vector3i(v.mIndices[0], v.mIndices[1], v.mIndices[2]);} -QMatrix4x4 fromAiMatrix4D(const aiMatrix4x4 & v) {return QMatrix4x4(v.a1, v.a2, v.a3, v.a4, - v.b1, v.b2, v.b3, v.b4, - v.c1, v.c2, v.c3, v.c4, - v.d1, v.d2, v.d3, v.d4);} -bool isAiMeshTriangles(const aiMesh * m) {return (m->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) == aiPrimitiveType_TRIANGLE;} - - -Mesh * assimpMesh(const aiMesh * m) { - if (!m) return 0; - if (!isAiMeshTriangles(m)) return 0; - Mesh * ret = new Mesh(); - int vcnt = m->mNumVertices, tcnt = m->mNumFaces; - - QVector & v(ret->vertices()); v.resize(vcnt); - QVector & t(ret->texcoords()); t.resize(vcnt); - QVector< Vector3i> & ind(ret->indicesTriangles()); - - for (int i = 0; i < vcnt; ++i) - v[i] = fromAiVector3D(m->mVertices[i]); - - if (m->HasNormals()) { - QVector & n(ret->normals()); - n.resize(vcnt); - for (int i = 0; i < vcnt; ++i) - n[i] = fromAiVector3D(m->mNormals[i]); - } - - if (m->HasTextureCoords(0)) { - for (int i = 0; i < vcnt; ++i) - t[i] = fromAiVector3D(m->mTextureCoords[0][i]).toVector2D(); - } - - if (m->HasFaces()) { - ind.resize(tcnt); - for (int i = 0; i < tcnt; ++i) - ind[i] = fromAiFace(m->mFaces[i]); - } else { - tcnt = vcnt / 3; - ind.resize(tcnt); - int si = 0; - for (int i = 0; i < tcnt; ++i) { - si = i+i+i; - ind[i] = Vector3i(si, si+1, si+2); - } - } - - //qDebug() << "add mesh" << v.size() << ret->normals().size() << ret->texcoords().size() << ret->indices().size(); - - return ret; -} - - -QColor aiMatColor(const aiMaterial * m, const char * key, uint s0, uint s1, const QColor & def = Qt::white) { - aiColor4D col; - aiReturn r = m->Get(key, s0, s1, col); - //qDebug() << key << r << col.r << col.g << col.b; - if (r != aiReturn_SUCCESS) return def; - return fromAiColor(col); -} -float aiMatFloat(const aiMaterial * m, const char * key, uint s0, uint s1, float def = 0.f) { - float ret; - aiReturn r = m->Get(key, s0, s1, ret); - if (r != aiReturn_SUCCESS) return def; - return ret; -} -QString aiMatString(const aiMaterial * m, const char * key, uint s0, uint s1) { - aiString p; - aiReturn r = const_cast(m)->Get(key, s0, s1, p); - //qDebug() << "GetTexture" << key << s0 << r << fromAiString(p); - if (r != aiReturn_SUCCESS) return QString(); - return fromAiString(p); -} -Material * assimpMaterial(const aiMaterial * m) { - if (!m) return 0; - Material * ret = new Material(); - ///WARNING: no function GetName() in aiMaterial in stable release - //ret->name = fromAiString(const_cast(m)->GetName()); - aiString name; - const_cast(m)->Get(AI_MATKEY_NAME,name); - ret->name = fromAiString(name); - //qDebug() << "mat" << ret->name; - //for (int i = 0; i < m->mNumProperties; ++i) { - // qDebug()<< fromAiString(m->mProperties[i]->mKey);// << "=" << aiMatFloat(m, m->mProperties[i]->mKey.C_Str(), 0, 0); - //} - ret->color_diffuse = aiMatColor(m, AI_MATKEY_COLOR_DIFFUSE); - ret->color_emission = aiMatColor(m, AI_MATKEY_COLOR_EMISSIVE); - float shine = aiMatFloat(m, AI_MATKEY_SHININESS, -1.f); - if (shine >= 0) { - ret->map_roughness.color_amount = 0.8f - (shine / 100.f * 0.6f); - //qDebug() << "shine" << shine; - } - ret->map_diffuse .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_DIFFUSE(0)); - ret->map_normal .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_NORMALS(0)); - //ret->map_metalness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SPECULAR(0)); - ret->map_roughness.bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_SHININESS(0)); - ret->map_emission .bitmap_path = aiMatString(m, AI_MATKEY_TEXTURE_EMISSIVE(0)); - ret->transparency = 1.f - aiMatFloat(m, AI_MATKEY_OPACITY, 1.f); - ret->detectMaps(); - ret->setTypes(); - return ret; -} - - -Light * assimpLight(const aiLight * l) { - if (!l) return 0; - if (l->mType != aiLightSource_POINT && l->mType != aiLightSource_SPOT) - return 0; - Light * ret = new Light(); - ret->setName(fromAiString(l->mName)); - ret->setPos(fromAiVector3D(l->mPosition)); - ret->setDirection(fromAiVector3D(l->mDirection)); - ret->decay_const = l->mAttenuationConstant ; - ret->decay_linear = l->mAttenuationLinear ; - ret->decay_quadratic = l->mAttenuationQuadratic; - ret->angle_start = l->mAngleInnerCone * rad2deg; - ret->angle_end = l->mAngleOuterCone * rad2deg; - if (l->mType == aiLightSource_SPOT) - ret->light_type = Light::Cone; - QVector3D col(l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b); - ret->intensity = col.length(); - col /= ret->intensity; - ret->setColor(QColor::fromRgbF(col[0], col[1], col[2])); - return ret; -} - - -ObjectBaseList assimpObject(const aiNode * n, const QVector & meshes, aiMesh ** ai_meshes, - const QVector & materials, - const QMap & light_by_name, QVector & out_lights) { - if (!n) return ObjectBaseList(); - ObjectBaseList ret; - ObjectBase * obj = 0; - QString name = fromAiString(n->mName); - Light * light = light_by_name.value(name, 0); - if (light) { - obj = light->clone(); - out_lights << (Light*)obj; - } else - obj = new ObjectBase(); - obj->setName(name); - obj->setMatrix(fromAiMatrix4D(n->mTransformation)); - ret << obj; - //qDebug() << "add object" << ret << ret->name(); - if (!light) { - //qDebug() << name << "has" << n->mNumMeshes << "meshes"; - for (uint i = 0; i < n->mNumMeshes; ++i) { - int mi = n->mMeshes[i]; - if (meshes[mi]) { - if (obj->mesh()) { - obj = obj->clone(false); - ret << obj; - } - obj->setMesh(meshes[mi]); - int mati = ai_meshes[mi]->mMaterialIndex; - if (mati >= 0 || mati < materials.size()) - obj->setMaterial(materials[mati]); - //ret->setMesh(meshes[mi]); - //qDebug() << "set mesh" << mi << ret->mesh(); - //break; - } - } - } - for (uint i = 0; i < n->mNumChildren; ++i) { - ObjectBaseList cl = assimpObject(n->mChildren[i], meshes, ai_meshes, materials, light_by_name, out_lights); - foreach (ObjectBase * c, cl) - obj->addChild(c); - } - - return ret; -} - - -Scene * loadScene(const QString & filepath) { - if (filepath.isEmpty()) return 0; - qDebug() << "[Loader Assimp] Import" << filepath << "..."; - Assimp::Importer importer; - const aiScene * ais = importer.ReadFile(filepath.toUtf8(), aiProcess_Triangulate | - aiProcess_SortByPType | - aiProcess_GenUVCoords | - aiProcess_TransformUVCoords); - if (!ais) { - qDebug() << "[Loader Assimp] Error: \"" + QString(importer.GetErrorString()) + "\""; - return 0; - } - qDebug() << "[Loader Assimp] Imported" << ais->mNumMeshes << "meshes"; - QVector meshes; - for (uint i = 0; i < ais->mNumMeshes; ++i) - meshes << assimpMesh(ais->mMeshes[i]); - QVector materials; - for (uint i = 0; i < ais->mNumMaterials; ++i) - materials << assimpMaterial(ais->mMaterials[i]); - QVector lights; - for (uint i = 0; i < ais->mNumLights; ++i) - lights << assimpLight(ais->mLights[i]); - QMap light_by_name; - foreach (Light * l, lights) - if (l) - light_by_name[l->name()] = l; - - QVector out_lights; - ObjectBaseList rootl = assimpObject(ais->mRootNode, meshes, ais->mMeshes, materials, light_by_name, out_lights); - if (rootl.isEmpty()) return 0; - ObjectBase * root = rootl[0]; - root->transferTransformToChildren(true); - - ObjectBaseList rcl = root->children(true); - foreach (ObjectBase * c, rcl) { - foreach (Light * l, out_lights) { - if (c->name() == (l->name() + ".Target")) { - l->setDistance((l->worldPos() - c->worldPos()).length()); - delete c; - break; - } - } - } - root->cleanTree(); - - Scene * scene = new Scene(); - scene->setName(root->name()); - foreach (ObjectBase * o, root->children()) - scene->addObject(o); - lights.removeAll(0); - qDeleteAll(lights); - - return scene; -} - - -QStringList supportedFormats() { - Assimp::Importer importer; - aiString ret; - importer.GetExtensionList(ret); - return fromAiString(ret).toLower().split(";"); -} diff --git a/qglengine/formats/loader_assimp.h b/qglengine/formats/loader_assimp.h deleted file mode 100644 index 348c32f..0000000 --- a/qglengine/formats/loader_assimp.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - QGL Loader Assimp - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef LOADER_ASSIMP_H -#define LOADER_ASSIMP_H - -#include "gltypes.h" - -Scene * loadScene(const QString & filepath); -QStringList supportedFormats(); - -#endif // LOADER_ASSIMP_H diff --git a/qglengine/formats/loader_qgl.cpp b/qglengine/formats/loader_qgl.cpp deleted file mode 100644 index 9e04190..0000000 --- a/qglengine/formats/loader_qgl.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - QGL Loader QGL - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "loader_qgl.h" -#include "glscene.h" -#include - - -Scene * loadFromQGLFile(const QString & filepath) { - QFile f(filepath); - if (!f.exists()) { - qDebug() << "[Loader QGL] Error: can`t open \"" + filepath + "\""; - return 0; - } - f.open(QIODevice::ReadOnly); - QDataStream s(&f); - s.setVersion(QDataStream::Qt_5_0); - char sign[4]; - s.readRawData(sign, 4); - if ((sign[0] != 'Q') || (sign[1] != 'G') || (sign[2] != 'L') || (sign[3] != 'E')) { - qDebug() << "[Loader QGL] Error: \"" + filepath + "\" is not valid QGLEngine file!"; - return 0; - } - ushort version = 0x1; - f.peek((char*)&version, 2); - if (version != 1) { - qDebug() << "[Loader QGL] Error: \"" + filepath + "\" unsupported version!"; - return 0; - } - Scene * ret = 0; - s.skipRawData(2); - s >> ret; - //root->buildTransform(); - qDebug() << "[Loader QGL] Loaded" << ret->objectsCount(true) << "objects from" << filepath; - return ret; -} - - -bool saveToQGLFile(const QString & filepath, const Scene * scene) { - QFile f(filepath); - if (!f.open(QIODevice::ReadWrite)) - return false; - f.resize(0); - QDataStream s(&f); - s.setVersion(QDataStream::Qt_5_0); - char sign[4] = {'Q', 'G', 'L', 'E'}; - ushort version = 0x1; - s.writeRawData(sign, 4); - s.writeRawData((char*)&version, 2); - s << scene; - return true; -} diff --git a/qglengine/formats/loader_qgl.h b/qglengine/formats/loader_qgl.h deleted file mode 100644 index 72aed12..0000000 --- a/qglengine/formats/loader_qgl.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - QGL Loader QGL - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef LOADER_QGL_H -#define LOADER_QGL_H - -#include "gltypes.h" -#include - -Scene * loadFromQGLFile(const QString & filepath); -bool saveToQGLFile(const QString & filepath, const Scene * scene); - -#endif // LOADER_QGL_H diff --git a/qglengine/glcamera.cpp b/qglengine/glcamera.cpp deleted file mode 100644 index d7dda9a..0000000 --- a/qglengine/glcamera.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - QGL Camera - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "gltypes.h" -#include "qglview.h" - - -Camera::Camera() { - type_ = glCamera; - fov_ = 60.; - roll_ = 0.; - //setRotationX(90.f); - depth_start = 0.1f; - mirror_x = mirror_y = false; -} - - -QMatrix4x4 Camera::offsetMatrix() const { - QMatrix4x4 ret; - ret.translate(parent_ ? -offset_ : -aim()); - return ret; -} - -/* -void Camera::localTransform(QMatrix4x4 & m) { - return; - if (parent_) - m *= parent_->worldTransform(); - QMatrix4x4 ret; - //qDebug() << "local camera"; - ret.translate(0., 0., -distance()); - ret.rotate(angles_.y(), 1., 0., 0.); - ret.rotate(angles_.x(), 0., 1., 0.); - ret.rotate(angles_.z(), 0., 0., 1.); - //m *= ret.inverted(); -} -*/ - -void Camera::assign(const Camera & c) { - trans = c.trans; - aim_dist = c.aim_dist; - fov_ = c.fov_; - mirror_x = c.mirror_x; - mirror_y = c.mirror_y; - depth_start = c.depth_start; - buildTransform(); -} - - -ObjectBase * Camera::clone(bool withChildren) { - Camera * o = new Camera(*this); - //GLObjectBase::clone(withChildren); - o->is_init = false; - o->name_ = name_;// + "_copy"; - o->scene_ = nullptr; - o->children_.clear(); - if (withChildren) { - for (int i = 0; i < children_.size(); ++i) - o->addChild(children_[i]->clone(withChildren)); - } - o->trans = trans; - o->aim_dist = aim_dist; - o->fov_ = fov_; - o->roll_ = roll_; - o->mirror_x = mirror_x; - o->mirror_y = mirror_y; - o->depth_start = depth_start; - o->meta = meta; - return o; -} - - -QMatrix4x4 Camera::viewMatrix() const { - QMatrix4x4 ret; - //qDebug() << pos() << aim(); - ret.translate(0., 0., -distance()); - ret.rotate(-roll_, 0., 0., 1.); - ret *= trans.matrixRotateScale().inverted(); - //ret.rotate(angles_.y(), 1., 0., 0.); - //ret.rotate(angles_.x(), 0., 1., 0.); - //pm.translate(-aim_); - if (parent_) { - QMatrix4x4 pmat = parent_->worldTransform(); - offset_ = pmat.column(3).toVector3D(); - pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; - pmat.translate(aim()); - ret *= pmat.inverted(); - } - return ret; -} - - -QMatrix4x4 Camera::projectionMatrix(double aspect) const { - return glMatrixPerspective(fov_, aspect, depth_start); -} diff --git a/qglengine/glcamera.h b/qglengine/glcamera.h deleted file mode 100644 index c8743f8..0000000 --- a/qglengine/glcamera.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - QGL Camera - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLCAMERA_H -#define GLCAMERA_H - -#include "globject.h" - -//extern QMatrix4x4 globCameraMatrix; -//extern Camera * currentCamera; - -class Camera: public AimedObject -{ - friend class QGLView; - friend class GLParticlesSystem; - friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p); - friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p); -public: - Camera(); - - void setFOV(const float & f) {fov_ = f;} - void setAngles(const QVector3D & a) {setRotation(a);} - void setAngleZ(const float & a) {setRotationZ(a);} - void setAngleXY(const float & a) {setRotationX(a);} - void setAngleRoll(const float & a) {roll_ = a;} - void setDepthStart(const float & d) {depth_start = d;} - void setMirrorX(bool yes) {mirror_x = yes;} - void setMirrorY(bool yes) {mirror_y = yes;} - - float FOV() const {return fov_;} - float angleZ() const {return rotationZ();} - float angleXY() const {return rotationX();} - float angleRoll() const {return roll_;} - float depthStart() const {return depth_start;} - bool isMirrorX() const {return mirror_x;} - bool isMirrorY() const {return mirror_y;} - void assign(const Camera & c); - - virtual ObjectBase * clone(bool withChildren = true); - QMatrix4x4 viewMatrix() const; - QMatrix4x4 projectionMatrix(double aspect) const; - QMatrix4x4 offsetMatrix() const; - - QMatrix4x4 fullViewMatrix() const {return viewMatrix() * offsetMatrix();} - -private: - mutable QVector3D offset_; - GLfloat fov_, roll_; - GLfloat depth_start; - bool mirror_x; - bool mirror_y; - -}; - -#endif // GLCAMERA_H diff --git a/qglengine/globject.cpp b/qglengine/globject.cpp deleted file mode 100644 index bad61ee..0000000 --- a/qglengine/globject.cpp +++ /dev/null @@ -1,717 +0,0 @@ -/* - QGL ObjectBase & Light - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "globject.h" -#include "glcamera.h" -#include "glscene.h" -#include "glmesh.h" -#include -//static int _count = 0; - -ObjectBase::ObjectBase(Mesh * geom, Material * mat) { - type_ = glMesh; - render_mode = View; - prev_pass = rpSolid; - parent_ = nullptr; - color_ = Qt::white; - is_root = is_init = selected_ = false; - visible_ = accept_fog = accept_light = cast_shadow = rec_shadow = select_ = true; - line_width = -1.; - id_ = 0; - blend_src = GL_SRC_ALPHA; - blend_dest = GL_ONE_MINUS_SRC_ALPHA; - type_ = glMesh; - raw_matrix = selected_aim = false; - mat_.setToIdentity(); - scene_ = nullptr; - mesh_ = geom; - material_ = mat; - //qDebug() << "ObjectBase, now" << ++_count; -} - - -ObjectBase::~ObjectBase() { - //qDebug() << "~ObjectBase, now" << --_count; - if (parent_) parent_->children_.removeAll(this); - if (scene_) { - scene_->__objectDeleted(this); - scene_->setTreeChanged(); - scene_->setTreeStructChanged(); - } - foreach (ObjectBase * c, children_) { - c->parent_ = nullptr; - delete c; - } -} - - -ObjectBase * ObjectBase::clone(bool withChildren) { - ObjectBase * o = new ObjectBase(); - o->prev_pass = prev_pass; - o->is_init = false; - o->accept_light = accept_light; - o->accept_fog = accept_fog; - o->visible_ = visible_; - o->color_ = color_; - o->type_ = type_; - o->raw_matrix = raw_matrix; - o->mat_ = mat_; - o->trans = trans; - o->itransform_ = itransform_; - o->bound = bound; - o->name_ = name_;// + "_copy"; - o->blend_src = blend_src; - o->blend_dest = blend_dest; - o->pos_h = pos_h; - o->material_ = material_; - o->mesh_ = mesh_; - o->meta = meta; - o->scene_ = nullptr; - if (withChildren) { - for (int i = 0; i < children_.size(); ++i) - o->addChild(children_[i]->clone(withChildren)); - } - return o; -} - - -void ObjectBase::destroy() { - if (mesh_) delete mesh_; -} - - -void ObjectBase::init() { - calculateBoundingBox(); - //material_.reflection.create(); - //qDebug() << "init" << vbo.buffer_; - is_init = true; -} - - -RenderPass ObjectBase::pass() const { - RenderPass ret = rpSolid; - if (material_) - if (material_->hasTransparency()) - ret = rpTransparent; - return ret; -} - - -void ObjectBase::setScene(Scene * v) { - scene_ = v; - foreach (ObjectBase * c, children_) - c->setScene(v); -} - - -void ObjectBase::addChild(ObjectBase * o) { - if (o == this) return; - if (o->parent_) - o->parent_->children_.removeAll(o); - children_ << o; - o->parent_ = this; - o->setScene(scene_); - o->buildTransform(); - /*if (scene_) { - ObjectBaseList cl = o->children(true); - cl << o; - //foreach (ObjectBase * i, cl) { - // emit view_->objectAdded(i); - //} - }*/ - setSceneTreeChanged(); -} - - -void ObjectBase::removeChild(ObjectBase * o) { - if (o == this) return; - children_.removeAll(o); - o->parent_ = nullptr; - o->buildTransform(); - setSceneTreeChanged(); -} - - -void ObjectBase::removeChild(int index) { - children_[index]->parent_ = nullptr; - children_[index]->buildTransform(); - children_.removeAt(index); - setSceneTreeChanged(); -} - - -void ObjectBase::clearChildren(bool deleteAll) { - foreach (ObjectBase * i, children_) { - i->scene_ = nullptr; - i->parent_ = nullptr; - i->clearChildren(deleteAll); - if (deleteAll) { - delete i; - } else { - i->buildTransform(); - } - } - children_.clear(); - setSceneTreeChanged(); -} - - -ObjectBase * ObjectBase::child(int index) { - if (index < 0 || index >= children_.size()) return nullptr; - return children_[index]; -} - - -ObjectBase * ObjectBase::child(const QString & name) { - foreach (ObjectBase * i, children_) - if (i->name_ == name) return i; - return nullptr; -} - - -const ObjectBase * ObjectBase::child(int index) const { - if (index < 0 || index >= children_.size()) return nullptr; - return children_[index]; -} - - -const ObjectBase * ObjectBase::child(const QString & name) const { - foreach (ObjectBase * i, children_) - if (i->name_ == name) return i; - return nullptr; -} - - -ObjectBaseList ObjectBase::children(bool all_) { - if (!all_) return children_; - ObjectBaseList cl; - addChildren(cl, this); - return cl; -} - - -bool ObjectBase::isVisible(bool check_parents) const { - if (!check_parents) return visible_; - if (!visible_) return false; - ObjectBase * p = parent_; - while (p) { - if (!p->visible_) return false; - p = p->parent_; - } - return true; -} - - -void ObjectBase::setVisible(bool v) { - visible_ = v; - setSceneTreeChanged(); -} - - -void ObjectBase::rotateZ(GLfloat a) { - raw_matrix = false; - trans.setRotationZ(trans.rotationZ() + a); - //angles_.setZ(angles_.z() + a); - //while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); - //while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); - buildTransform(); -} - - -void ObjectBase::setRotationZ(GLfloat a) { - raw_matrix = false; - trans.setRotationZ(a); - //angles_.setZ(a); - //while (angles_.z() < -360.f) angles_.setZ(angles_.z() + 360.f); - //while (angles_.z() > 360.f) angles_.setZ(angles_.z() - 360.f); - buildTransform(); -} - - -void ObjectBase::setTransform(const Transform & t) { - trans = t; - buildTransform(); -} - - -void ObjectBase::addChildren(ObjectBaseList & list, ObjectBase * where) { - foreach (ObjectBase * i, where->children_) { - list << i; - addChildren(list, i); - } -} - - -void ObjectBase::calculateBoundingBox() { - bound = Box3D(); - if (mesh_) { - bound = mesh_->boundingBox(); - QVector c = bound.corners(), tc; - foreach (QVector3D p, c) - tc << (itransform_ * QVector4D(p, 1)).toVector3D(); - bound = Box3D(tc); - } - foreach (ObjectBase * i, children_) { - i->calculateBoundingBox(); - bound |= i->boundingBox(); - } -} - - -void ObjectBase::updateTransform() { - buildTransform(true); -} - - -void ObjectBase::setProperty(const QString & pn, const QVariant & v) { - meta[pn] = v; -} - - -QVariant ObjectBase::property(const QString & pn, bool * exists) const { - if (exists) *exists = meta.contains(pn); - return meta.value(pn); -} - - -bool ObjectBase::hasProperty(const QString & pn) const { - return meta.contains(pn); -} - - -void ObjectBase::removeProperty(const QString & pn) { - meta.remove(pn); -} - - -void ObjectBase::setMatrix(const QMatrix4x4 & t) { - //raw_matrix = true; - //mat_ = t; - //pos_ = mat_.column(3).toVector3D(); - //mat_.setColumn(3, QVector4D(0., 0., 0., 1.)); - raw_matrix = false; - trans.setMatrix(t); - buildTransform(); -} - - -QMatrix4x4 ObjectBase::matrix() const { - return trans.matrix(); -} - - -QVector3D ObjectBase::inParentSpace(const QVector3D & v) const { - if (!parent_) return v; - return (parent_->matrix() * QVector4D(v, 1)).toVector3D(); -} - - -void ObjectBase::transferTransformToChildren(bool only_scale) { - QMatrix4x4 m = trans.matrix(); - if (only_scale) m = trans.matrixScale(); - foreach (ObjectBase * i, children_) - i->trans.setMatrix(m * i->trans.matrix()); - if (only_scale) resetScale(); - else setMatrix(QMatrix4x4()); -} - - -void ObjectBase::cleanTree() { - for (int i = 0; i < children_.size(); ++i) { - ObjectBase * o = children_[i]; - if (!o->hasChildren() && !o->mesh() && (o->type() == glMesh)) { - delete o; - --i; - } - o->cleanTree(); - } -} - - -bool ObjectBase::isSelected(bool check_parents) const { - if (!check_parents) return selected_; - if (selected_) return true; - ObjectBase * p = parent_; - while (p) { - if (p->selected_) return true; - p = p->parent_; - } - return false; -} - - -void ObjectBase::setSelected(bool yes) { - //qDebug() << "select" << name() << view_; - if (select_) - selected_ = yes; - if (!selected_) - selected_aim = false; -} - - -ObjectBase * ObjectBase::selectedParent() const { - ObjectBase * p = parent_; - while (p) { - if (p->selected_) return p; - p = p->parent_; - } - return 0; -} - - -void ObjectBase::setMaterial(Material * m, bool with_children) { - material_ = m; - if (with_children) - foreach (ObjectBase * i, children_) i->setMaterial(m, true); - setObjectsChanged(); - if (scene_) scene_->mat_changed = scene_->tree_changed = true; -} - - -void ObjectBase::setColor(QColor c, bool with_children) { - color_ = c; - if (with_children) - foreach (ObjectBase * i, children_) i->setColor(c, true); - setObjectsChanged(); -} - - -void ObjectBase::setMesh(Mesh * v) { - if (scene_) - v = scene_->attachMesh(v); - mesh_ = v; - setSceneTreeChanged(); - setObjectsChanged(); -} - - -void ObjectBase::buildTransform(bool force) { - if (force) trans.setDirty(); - itransform_.setToIdentity(); - ObjectBase * p = parent_; - if (p) - itransform_ = p->itransform_; - //if (raw_matrix) { - // itransform_.translate(pos_); - // itransform_ *= mat_; - // //qDebug() << "raw_matrix" << itransform_; - //} else - localTransform(itransform_); - //qDebug() << name_ << itransform_; - foreach (ObjectBase * i, children_) - i->buildTransform(force); - setObjectsChanged(); -} - - -void ObjectBase::initInternal() { - init(); - foreach (ObjectBase * i, children_) i->initInternal(); -} - - -void ObjectBase::localTransform(QMatrix4x4 & m) { - m *= trans.matrix(); -} - - -void ObjectBase::setSceneTreeChanged() { - if (scene_) { - scene_->setTreeChanged(); - scene_->setTreeStructChanged(); - } - setObjectsChanged(); -} - - -void ObjectBase::setObjectsChanged() { - int p = pass(); - if (mesh_) { - mesh_->setObjectsChanged (p, true); - mesh_->setSelectionChanged(p, true); - if (prev_pass != p) { - mesh_->setObjectsChanged (prev_pass, true); - mesh_->setSelectionChanged(prev_pass, true); - } - } - prev_pass = p; -} - - -QMatrix4x4 ObjectBase::worldMatrix(QMatrix4x4 parent) const { - QMatrix4x4 mat; - //mat.translate(pos_); - //if (raw_matrix) { - // mat *= mat_; - //} else { - // if (angles_.z() != 0.f) mat.rotate(angles_.z(), 0., 0., 1.); - // if (angles_.y() != 0.f) mat.rotate(angles_.y(), 0., 1., 0.); - // if (angles_.x() != 0.f) mat.rotate(angles_.x(), 1., 0., 0.); - // mat.scale(scale_); - //} - mat = trans.matrix(); - return parent * mat; -} - - - - -AimedObject::AimedObject() { - aim_dist = 1.; -} - - -QVector3D AimedObject::worldAim() const { - QVector3D ret = worldPos() + worldDirection() * aim_dist; - return ret; -} - - -void AimedObject::setAim(const QVector3D & p) { - QVector3D dir = p - pos(); - trans.setRotation(Transform::fromDirection(dir, trans.rotationY())); - aim_dist = dir.length(); - buildTransform(); - //if (!p.isNull()) - //qDebug() << "setAim" << p << aim() << worldAim(); -} - - -QVector3D AimedObject::direction() const { - return trans.direction(); -} - - -void AimedObject::setDirection(const QVector3D & d) { - //double len = qMax(aim_.length(), 0.001f); - //aim_ = d.normalized() * len; - buildTransform(); -} - - -void AimedObject::flyCloser(double s) { - double tl = 1. / (1. + s); - move(direction() * aim_dist * (1. - tl)); - aim_dist *= tl; -} - - -void AimedObject::flyFarer(double s) { - double tl = 1. * (1. + s); - move(direction() * aim_dist * (1. - tl)); - aim_dist *= tl; -} - - -void AimedObject::flyToDistance(double d) { - move(direction() * (aim_dist - d)); - aim_dist = d; - //qDebug() << d << (aim() - pos()).length() << aim(); -} - - -void AimedObject::moveForward(const float & x, bool withZ) { - QVector3D dv = itransform_.mapVector(QVector3D(0, 0, -x)); - if (!withZ) dv[2] = 0.; - move(dv); -} - - -void AimedObject::moveLeft(const float & x, bool withZ) { - QVector3D dv = itransform_.mapVector(QVector3D(-x, 0, 0)); - if (!withZ) dv[2] = 0.; - move(dv); -} - - -void AimedObject::moveUp(const float & x, bool onlyZ) { - QVector3D dv = itransform_.mapVector(QVector3D(0, x, 0)); - if (onlyZ) dv[0] = dv[1] = 0.; - move(dv); -} - - -void AimedObject::orbitZ(const float & a) { - QVector3D pa = aim(); - rotateZ(-a); - move(pa - aim()); -} - - -void AimedObject::orbitXY(const float & a) { - QVector3D pa = aim(); - rotateX(-a); - move(pa - aim()); -} - - -void AimedObject::transformChanged() { - -} - - - - -Light::Light(): AimedObject(), shadow_map(0, true, GL_R16F) { - type_ = glLight; - light_type = Omni; - intensity = 1.; - angle_start = angle_end = 180.; - decay_linear = decay_quadratic = decay_start = 0.; - decay_const = decay_end = 1.; - setDirection(0, 0, -1.); -} - - -Light::Light(const QVector3D & p, const QColor & c, float i): AimedObject(), shadow_map(0, true, GL_R16F) { - type_ = glLight; - light_type = Omni; - intensity = i; - color_ = c; - angle_start = angle_end = 180.; - decay_linear = decay_quadratic = decay_start = 0.; - decay_const = decay_end = 1.; - setPos(p); - setDirection(0, 0, -1.); -} - - -ObjectBase * Light::clone(bool withChildren) { - Light * o = new Light(*this); - //GLObjectBase::clone(withChildren); - o->is_init = false; - o->name_ = name_;// + "_copy"; - o->scene_ = nullptr; - o->children_.clear(); - if (withChildren) { - for (int i = 0; i < children_.size(); ++i) - o->addChild(children_[i]->clone(withChildren)); - } - o->color_ = color_; - o->light_type = light_type; - o->trans = trans; - o->aim_dist = aim_dist; - o->angle_start = angle_start; - o->angle_end = angle_end; - o->intensity = intensity; - o->decay_const = decay_const; - o->decay_linear = decay_linear; - o->decay_quadratic = decay_quadratic; - o->meta = meta; - return o; -} - - -void Light::apply() { - if (scene_) scene_->setLightsChanged(); -} - - -QDataStream & operator <<(QDataStream & s, const ObjectBase * p) { - ChunkStream cs; - //qDebug() << "place" << p->name() << "..."; - cs.add(1, int(p->type_)).add(2, p->accept_light).add(3, p->accept_fog).add(4, p->visible_) - .add(5, p->cast_shadow).add(6, p->rec_shadow).add(7, p->raw_matrix).add(8, p->line_width) - .add(9, int(p->render_mode)).add(14, p->mat_).add(16, p->children_.size()) - .add(17, p->name_).add(18, p->meta).add(19, p->color_).add(20, p->trans); - //qDebug() << "place self done"; - if (p->type_ == ObjectBase::glLight) { - //qDebug() << "place light ..."; - const Light * l = (const Light*)p; - cs.add(101, l->angle_start).add(102, l->angle_end).add(103, l->intensity) - .add(104, l->decay_const).add(105, l->decay_linear).add(106, l->decay_quadratic) - .add(107, l->decay_start).add(108, l->decay_end).add(109, int(l->light_type)) - .add(111, l->distance()); - } - if (p->type_ == ObjectBase::glCamera) { - //qDebug() << "place camera ..."; - const Camera * c = (const Camera*)p; - cs.add(200, c->aim()).add(201, c->fov_).add(202, c->depth_start) - .add(206, c->mirror_x).add(207, c->mirror_y).add(208, c->distance()) - .add(209, c->roll_); - } - //qDebug() << "place" << p->name() << cs.data().size() << s.device()->size(); - s << cs.data(); - foreach (const ObjectBase * c, p->children_) - s << c; - return s; -} -QDataStream & operator >>(QDataStream & s, ObjectBase *& p) { - ChunkStream cs(s); - p = nullptr; - int ccnt = 0; - Light * l = nullptr; - Camera * c = nullptr; - //qDebug() << "read obj ..."; - while (!cs.atEnd()) { - switch (cs.read()) { - case 1: { - ObjectBase::Type type = (ObjectBase::Type)cs.getData(); - switch (type) { - case ObjectBase::glMesh: p = new ObjectBase(); break; - case ObjectBase::glLight: p = new Light(); l = (Light*)p; break; - case ObjectBase::glCamera: p = new Camera(); c = (Camera*)p; break; - default : break; - } - if (p) p->type_ = type; - } break; - case 2: if (p) p->accept_light = cs.getData(); break; - case 3: if (p) p->accept_fog = cs.getData(); break; - case 4: if (p) p->visible_ = cs.getData(); break; - case 5: if (p) p->cast_shadow = cs.getData(); break; - case 6: if (p) p->rec_shadow = cs.getData(); break; - case 7: if (p) p->raw_matrix = cs.getData(); break; - case 8: if (p) p->line_width = cs.getData(); break; - case 9: if (p) p->render_mode = (ObjectBase::RenderMode)cs.getData(); break; - case 14: if (p) p->mat_ = cs.getData(); break; - case 16: if (p) ccnt = cs.getData(); break; - case 17: if (p) p->name_ = cs.getData(); break; - case 18: if (p) p->meta = cs.getData(); break; - case 19: if (p) p->color_ = cs.getData(); break; - case 20: if (p) p->trans = cs.getData(); break; - case 100: if (l) l->setAim(cs.getData()); break; - case 101: if (l) l->angle_start = cs.getData(); break; - case 102: if (l) l->angle_end = cs.getData(); break; - case 103: if (l) l->intensity = cs.getData(); break; - case 104: if (l) l->decay_const = cs.getData(); break; - case 105: if (l) l->decay_linear = cs.getData(); break; - case 106: if (l) l->decay_quadratic = cs.getData(); break; - case 107: if (l) l->decay_start = cs.getData(); break; - case 108: if (l) l->decay_end = cs.getData(); break; - case 109: if (l) l->light_type = (Light::Type)cs.getData(); break; - case 111: if (l) l->setDistance(cs.getData()); break; - case 200: if (c) c->setAim(cs.getData()); break; - case 201: if (c) c->setFOV(cs.getData()); break; - case 202: if (c) c->setDepthStart(cs.getData()); break; - case 206: if (c) c->mirror_x = cs.getData(); break; - case 207: if (c) c->mirror_y = cs.getData(); break; - case 208: if (c) c->setDistance(cs.getData()); break; - case 209: if (c) c->roll_ = cs.getData(); break; - } - } - //qDebug() << p->name() << ccnt; - for (int i = 0; i < ccnt; ++i) { - ObjectBase * c = nullptr; - s >> c; - if (!c) continue; - c->parent_ = p; - p->children_ << c; - } - p->buildTransform(); - return s; -} diff --git a/qglengine/globject.h b/qglengine/globject.h deleted file mode 100644 index bfd9958..0000000 --- a/qglengine/globject.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - QGL ObjectBase & Light - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLOBJECT_H -#define GLOBJECT_H - -#include "glframebuffer.h" -#include "glmaterial.h" -#include "gltypes.h" -#include "gltransform.h" - - -class ObjectBase -{ - friend class QGLView; - friend class Scene; - friend class Renderer; - friend class RendererService; - friend class RendererSelection; - friend class MouseController; - friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p); - friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p); - friend QDataStream & operator >>(QDataStream & s, Scene *& p); -public: - enum Type {glMesh, glLight, glCamera, glParticlesSystem}; - enum RenderMode {View = 0, Point = GL_POINT, Line = GL_LINE, Fill = GL_FILL}; - - explicit ObjectBase(Mesh * geom = 0, Material * mat = 0); - virtual ~ObjectBase(); - - virtual ObjectBase * clone(bool withChildren = true); - void destroy(); - - QString name() const {return name_;} - void setName(const QString & name) {name_ = name;} - virtual void init(); - virtual void update() {} - bool isInit() const {return is_init;} - Type type() const {return type_;} - RenderPass pass() const; - - RenderMode renderMode() const {return render_mode;} - void setRenderMode(RenderMode mode) {render_mode = mode;} - - float lineWidth() const {return line_width;} - void setLineWidth(const float & width) {line_width = width;} - - ObjectBase * parent() {return parent_;} - void setParent(ObjectBase * o) {parent_ = o;} - bool hasParent() const {return parent_ != nullptr;} - bool hasChildren() const {return !children_.isEmpty();} - void setScene(Scene * v); - - void addChild(ObjectBase * o); - void removeChild(ObjectBase * o); - void removeChild(int index); - void clearChildren(bool deleteAll = false); - int childCount() const {return children_.size();} - ObjectBase * child(int index); - ObjectBase * child(const QString & name); - const ObjectBase * child(int index) const; - const ObjectBase * child(const QString & name) const; - ObjectBaseList children(bool all_ = false); - - bool isVisible(bool check_parents = false) const; - bool isHidden(bool check_parents = false) const {return !isVisible(check_parents);} - void setVisible(bool v); - void setHidden(bool v) {setVisible(!v);} - void show() {setVisible(true);} - void hide() {setVisible(false);} - - bool isReceiveShadows() const {return rec_shadow;} - bool isCastShadows() const {return cast_shadow;} - void setReceiveShadows(bool on) {rec_shadow = on;} - void setCastShadows(bool on) {cast_shadow = on;} - - void move(const QVector3D & dv) {trans.setTranslation(pos() + dv); buildTransform();} - void moveTo(const QVector3D & dv) {trans.setTranslation(dv); buildTransform();} - void move(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {move(QVector3D(dx, dy, dz)); buildTransform();} - void moveTo(GLfloat dx, GLfloat dy, GLfloat dz = 0.) {moveTo(QVector3D(dx, dy, dz)); buildTransform();} - void moveX(GLfloat o) {trans.setTranslationX(posX() + o); buildTransform();} - void moveY(GLfloat o) {trans.setTranslationY(posY() + o); buildTransform();} - void moveZ(GLfloat o) {trans.setTranslationZ(posZ() + o); buildTransform();} - void setPosX(GLfloat o) {trans.setTranslationX(o); buildTransform();} - void setPosY(GLfloat o) {trans.setTranslationY(o); buildTransform();} - void setPosZ(GLfloat o) {trans.setTranslationZ(o); buildTransform();} - void setPos(GLfloat x, GLfloat y, GLfloat z) {trans.setTranslation(QVector3D(x, y, z)); buildTransform();} - void setPos(const QVector3D & p) {trans.setTranslation(p); buildTransform();} - void resetPos() {trans.setTranslation(QVector3D()); buildTransform();} - - QVector3D pos() const {return trans.translation();} - float posX() const {return trans.translation().x();} - float posY() const {return trans.translation().y();} - float posZ() const {return trans.translation().z();} - QVector3D worldPos() const {return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D();} - QMatrix4x4 worldTransform() const {return itransform_;} - - QVector3D rotation() const {return trans.rotation();} - float rotationX() const {return rotation().x();} - float rotationY() const {return rotation().y();} - float rotationZ() const {return rotation().z();} - void rotateX(GLfloat a) {raw_matrix = false; trans.setRotationX(trans.rotationX() + a); buildTransform();} - void rotateY(GLfloat a) {raw_matrix = false; trans.setRotationY(trans.rotationY() + a); buildTransform();} - void rotateZ(GLfloat a); - void setRotationX(GLfloat a) {raw_matrix = false; trans.setRotationX(a); buildTransform();} - void setRotationY(GLfloat a) {raw_matrix = false; trans.setRotationY(a); buildTransform();} - void setRotationZ(GLfloat a); - void setRotation(const QVector3D & a) {raw_matrix = false; trans.setRotation(a); buildTransform();} - void resetRotation() {raw_matrix = false; trans.setRotation(QVector3D()); buildTransform();} - - QVector3D scale() {return trans.scale3D();} - float scaleX() {return trans.scale3D().x();} - float scaleY() {return trans.scale3D().y();} - float scaleZ() {return trans.scale3D().z();} - void scale(const QVector3D & sv) {raw_matrix = false; trans.setScale(trans.scale3D() * sv); buildTransform();} - void scale(GLfloat sx, GLfloat sy, GLfloat sz) {raw_matrix = false; scale(QVector3D(sx, sy, sz)); buildTransform();} - void scale(GLfloat sx, GLfloat sy) {raw_matrix = false; scale(QVector3D(sx, sy, sy)); buildTransform();} - void scale(GLfloat sx) {raw_matrix = false; scale(QVector3D(sx, sx, sx)); buildTransform();} - void scaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(trans.scale3D().x() + a); buildTransform();} - void scaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(trans.scale3D().y() + a); buildTransform();} - void scaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(trans.scale3D().z() + a); buildTransform();} - void setScale(const QVector3D & a) {raw_matrix = false; trans.setScale(a); buildTransform();} - void setScale(GLfloat a) {raw_matrix = false; trans.setScale(a); buildTransform();} - void setScaleX(GLfloat a) {raw_matrix = false; trans.setScaleX(a); buildTransform();} - void setScaleY(GLfloat a) {raw_matrix = false; trans.setScaleY(a); buildTransform();} - void setScaleZ(GLfloat a) {raw_matrix = false; trans.setScaleZ(a); buildTransform();} - void resetScale() {raw_matrix = false; trans.setScale(1.f); buildTransform();} - - Transform transform() {return trans;} - void setTransform(const Transform & t); - void setMatrix(const QMatrix4x4 & t); - QMatrix4x4 matrix() const; - bool isRawMatrix() {return raw_matrix;} - QVector3D inParentSpace(const QVector3D & v) const; - void transferTransformToChildren(bool only_scale = false); - void cleanTree(); - - bool isAcceptLight() const {return accept_light;} - void setAcceptLight(bool yes) {accept_light = yes;} - - bool isAcceptFog() const {return accept_fog;} - void setAcceptFog(bool yes) {accept_fog = yes;} - - bool isSelected(bool check_parents = false) const; - void setSelected(bool yes); - void select() {setSelected(true);} - void deselect() {setSelected(false);} - ObjectBase * selectedParent() const; - - bool isSelectable() const {return select_;} - void setSelectable(bool yes) {select_ = yes;} - /* - bool isWriteDepth() const {return write_depth_;} - void setWriteDepth(bool yes) {write_depth_ = yes;}*/ - - GLenum srcAlpha() const {return blend_src;} - GLenum destAlpha() const {return blend_dest;} - void setSrcAlpha(GLenum mode) {blend_src = mode;} - void setDestAlpha(GLenum mode) {blend_dest = mode;} - - void setMaterial(Material * m, bool with_children = false); - Material * material() {return material_;} - - void setColor(QColor c, bool with_children = false); - QColor color() {return color_;} - - const Box3D & boundingBox() const {return bound;} - void setMesh(Mesh * v); - Mesh * mesh() {return mesh_;} - - void calculateBoundingBox(); - void updateTransform(); - - void setProperty(const QString & pn, const QVariant & v); - QVariant property(const QString & pn, bool * exists = 0) const; - bool hasProperty(const QString & pn) const; - void removeProperty(const QString & pn); - - QVector3D pos_h; - - //QVector d_vertices, d_normals, d_uvs; - -protected: - virtual void transformChanged() {} - void addChildren(ObjectBaseList & list, ObjectBase * where); - void buildTransform(bool force = false); - void initInternal(); - void setSceneTreeChanged(); - void setObjectsChanged(); - void localTransform(QMatrix4x4 & m); - QMatrix4x4 worldMatrix(QMatrix4x4 parent) const; - - int prev_pass; // Pass - bool is_init, accept_light, accept_fog, visible_, cast_shadow, rec_shadow, select_, selected_, raw_matrix; - bool is_root, selected_aim; - float line_width; - QColor color_; - uint id_; - Type type_; - RenderMode render_mode; - Box3D bound; - Transform trans; - ObjectBaseList children_; - QMatrix4x4 itransform_, mat_; - QString name_; - GLenum blend_src, blend_dest; - ObjectBase * parent_; - Scene * scene_; - Material * material_; - Mesh * mesh_; - QVariantMap meta; - -}; - -inline bool operator <(const ObjectBase & f, const ObjectBase & s) {return f.pos_h.z() < s.pos_h.z();} - - -class AimedObject: public ObjectBase { - friend class QGLView; - friend class GLRendererBase; - friend class Light; - friend class Camera; -public: - AimedObject(); - ~AimedObject() {} - QVector3D aim() const {return pos() + (direction() * aim_dist);} - QVector3D worldAim() const; - void setAim(const QVector3D & p); - QVector3D direction() const; - QVector3D worldDirection() const {return (itransform_ * QVector4D(QVector3D(0,0,-1), 0.)).toVector3D().normalized();} - void setDirection(const QVector3D & d); - void setDirection(double x, double y, double z) {setDirection(QVector3D(x, y, z));} - - double distance() const {return aim_dist;} - void setDistance(double d) {aim_dist = d;} - void flyCloser(double s); - void flyFarer(double s); - void flyToDistance(double d); - - void moveForward(const float & x, bool withZ = true); - void moveBackward(const float & x, bool withZ = true) {moveForward(-x, withZ);} - void moveLeft(const float & x, bool withZ = true); - void moveRight(const float & x, bool withZ = true) {moveLeft(-x, withZ);} - void moveUp(const float & x, bool onlyZ = false); - void moveDown(const float & x, bool onlyZ = false) {moveUp(-x, onlyZ);} - - void rotateRoll(const float & a) {rotateY(a);} - void orbitZ(const float & a); - void orbitXY(const float & a); - -protected: - void transformChanged() override; - double aim_dist; -}; - - -class Light: public AimedObject { - friend class QGLView; - friend class RendererBase; -public: - enum Type {Omni, Cone, Directional}; - - Light(); - Light(const QVector3D & p, const QColor & c = Qt::white, float i = 1.); - virtual ObjectBase * clone(bool withChildren = true); - virtual void init() {shadow_map.resize(512, 512); is_init = true;} - void apply(); - - float angle_start; - float angle_end; - float intensity; - float decay_const; - float decay_linear; - float decay_quadratic; - float decay_start; - float decay_end; - Type light_type; - Framebuffer shadow_map; - QMatrix4x4 shadow_matrix; - -protected: - -}; - -template -inline T globject_cast(ObjectBase * object) {return reinterpret_cast(object);} - -template -inline T globject_cast(const ObjectBase * object) {return reinterpret_cast(object);} - - -QDataStream & operator <<(QDataStream & s, const ObjectBase * p); -QDataStream & operator >>(QDataStream & s, ObjectBase *& p); - -inline ObjectBaseList lights2objectList(const QList & v) {ObjectBaseList ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;} -inline ObjectBaseList cameras2objectList(const QList & v) {ObjectBaseList ret; foreach (Camera*i, v) ret << (ObjectBase*)i; return ret;} - -#endif // GLOBJECT_H diff --git a/qglengine/glrendererbase.cpp b/qglengine/glrendererbase.cpp deleted file mode 100644 index edb92b6..0000000 --- a/qglengine/glrendererbase.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - QGL GLRendererBase - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "glrendererbase.h" -#include "globject.h" -#include "qglview.h" - - -GLRendererBase::GLRendererBase(QGLView * view_): view(view_) { - white_image = QImage(1, 1, QImage::Format_ARGB32); - white_image.fill(0xFFFFFFFF); - white_image_id = 0; - violent_image = QImage(1, 1, QImage::Format_ARGB32); - violent_image.fill(QColor(127, 127, 255)); - violent_image_id = 0; -} - - -void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) { - QVector3D lp = l.worldPos(), ld;// = (l.itransform_ * QVector4D(l.direction, 0.)).toVector3D().normalized(); - GLfloat pos[] = {0.f, 0.f, 0.f, 0.f}; - GLfloat dir[] = {0.f, 0.f, 0.f}; - GLfloat col[] = {0.f, 0.f, 0.f}; - pos[0] = l.light_type == Light::Directional ? -l.direction().x() : lp.x(); - pos[1] = l.light_type == Light::Directional ? -l.direction().y() : lp.y(); - pos[2] = l.light_type == Light::Directional ? -l.direction().z() : lp.z(); - pos[3] = l.light_type == Light::Directional ? 0. : 1.; - dir[0] = ld.x(); - dir[1] = ld.y(); - dir[2] = ld.z(); - //col[0] = l.visible_ ? l.color().redF() * l.intensity : 0.f; - //col[1] = l.visible_ ? l.color().greenF() * l.intensity : 0.f; - //col[2] = l.visible_ ? l.color().blueF() * l.intensity : 0.f; - glEnable(gl_index); - //glLightfv(gl_index, GL_AMBIENT, ambient); - glLightfv(gl_index, GL_DIFFUSE, col); - glLightfv(gl_index, GL_SPECULAR, col); - glLightfv(gl_index, GL_POSITION, pos); - glLightf(gl_index, GL_CONSTANT_ATTENUATION, l.decay_const); - glLightf(gl_index, GL_LINEAR_ATTENUATION, l.decay_linear); - glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic); - if (l.light_type == Light::Cone) { - glLightfv(gl_index, GL_SPOT_DIRECTION, dir); - glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_end / 2.f); - glLightf(gl_index, GL_SPOT_EXPONENT, (1.f - piClamp((l.angle_end - l.angle_start) / (l.angle_end + 0.001f), 0., 1.f)) * 128.f); - } else { - glLightf(gl_index, GL_SPOT_CUTOFF, 180.); - } - -} - - -void GLRendererBase::setupAmbientLight(const QColor & a, bool first_pass) { - GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.f}; - if (first_pass) { - ambient[0] = view->ambientColor_.redF(); - ambient[1] = view->ambientColor_.greenF(); - ambient[2] = view->ambientColor_.blueF(); - } - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); -} - - -void GLRendererBase::setupShadersLights(int lights_count) { - /*foreach (QOpenGLShaderProgram * i, view->shaders_ppl) { - i->bind(); - i->setUniformValue("lightsCount", lights_count); - i->setUniformValue("acc_light", lights_count > 0); - //i->setUniformValue("mat", mvm); - }*/ -} - - -#define BIND_TEXTURE(ch, map) if (rp.prev_tex[ch] != mat.map.bitmap_id) { \ - rp.prev_tex[ch] = mat.map.bitmap_id; \ - glActiveTexture(GL_TEXTURE0 + ch); glBindTexture(GL_TEXTURE_2D, mat.map.bitmap_id); \ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view->feature(QGLView::qglAnisotropicLevel).toInt());} - -void GLRendererBase::setupTextures(ObjectBase & o, GLRendererBase::RenderingParameters & rp, bool first_object) { -} - -#undef BIND_TEXTURE - - -void GLRendererBase::setupLights(int pass, int lights_per_pass) { - /*int light_start, light_end, lmax; - light_start = pass * lights_per_pass; - light_end = qMin((pass + 1) * lights_per_pass, view->lights_.size()); - setupAmbientLight(view->ambientColor_, pass == 0); - if (!view->lights_.isEmpty()) { - setupShadersLights(light_end - light_start); - for (int i = light_start; i < light_end; ++i) - setupLight(*view->lights_[i], i - light_start, GL_LIGHT0 + i - light_start); - lmax = light_start + 8; - for (int i = light_end; i < lmax; ++i) - glDisable(GL_LIGHT0 + i - light_start); - } else { - setupShadersLights(0); - for (int i = 0; i < 8; ++i) - glDisable(GL_LIGHT0 + i); - }*/ -} - - -void GLRendererBase::applyFilteringParameters() { - /*if (view->isFeatureEnabled(QGLView::qglLinearFiltering)) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - }*/ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view->feature(QGLView::qglAnisotropicLevel).toInt()); -} - - -void GLRendererBase::renderObjects(int pass, int light_pass, void * shaders, bool textures, bool light, bool fog) { - /*RenderingParameters rpl; - rpl.pass = pass; - rpl.light_pass = light_pass; - rpl.shaders = shaders; - rpl.textures = textures; - rpl.light = rpl.prev_light = light; - rpl.fog = rpl.prev_fog = fog; - rpl.view_matrix = rp.view_matrix; - rpl.prev_view_matrix = rp.prev_view_matrix; - rpl.proj_matrix = rp.proj_matrix; - rpl.prev_proj_matrix = rp.prev_proj_matrix; - rpl.cam_offset_matrix = view->camera()->offsetMatrix(); - //qDebug() << "view:" << rp.view_matrix; - for (int i = 0; i < 32; ++i) rpl.prev_tex[i] = 0; - setupTextures(view->objects_, rpl, true); - glSetCapEnabled(GL_TEXTURE_2D, rpl.textures); - glSetCapEnabled(GL_BLEND, pass == ObjectBase::Transparent); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_TEXTURE_CUBE_MAP); - glPushMatrix(); - renderSingleObject(view->objects_, rpl); - glPopMatrix();*/ -} - - -void GLRendererBase::renderSingleObject(ObjectBase & o, RenderingParameters & rpl) { -// if (!o.isInit()) -// o.init(); -// if (!o.isTexturesLoaded()) -// o.loadTextures(); -// if (!o.visible_) return; -// if (rpl.pass == o.pass_) { -// //Material & mat(o.material_); -// QMatrix4x4 curview = rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_, prevview = rpl.prev_view_matrix * rpl.cam_offset_matrix * o.itransform_; -// //setupTextures(o, rpl, false); -// //mat.apply((QOpenGLShaderProgram*)rpl.shaders); -// glSetPolygonMode(o.render_mode != ObjectBase::View ? o.render_mode : (view->rmode != ObjectBase::View ? view->rmode : GL_FILL)); -// glLineWidth(o.line_width > 0.f ? o.line_width : view->lineWidth_); -// glPointSize(o.line_width > 0.f ? o.line_width : view->lineWidth_); -// o.update(); -// /*if (o.pass_ == GLObjectBase::Transparent) { -// glActiveTexture(GL_TEXTURE0 + 3); -// if (mat.reflectivity > 0.f) { -// glEnable(GL_TEXTURE_CUBE_MAP); -// //if (!mat.map_reflection.isEmpty()) mat.map_reflection.bind(); -// //else glDisable(GL_TEXTURE_CUBE_MAP); -// } else glDisable(GL_TEXTURE_CUBE_MAP); -// if (rpl.light_pass > 0) glDisable(GL_TEXTURE_CUBE_MAP); -// GLfloat gm[16], bc[4] = {mat.reflectivity, mat.reflectivity, mat.reflectivity, mat.reflectivity}; -// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); -// glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); -// glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); -// glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); -// glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, bc); -// glGetFloatv(GL_MODELVIEW_MATRIX, gm); -// glMatrixMode(GL_TEXTURE); -// ///glLoadTransposeMatrixf(gm); -// glScalef(-1., -1., -1.); -// glMatrixMode(GL_MODELVIEW); -// glActiveTexture(GL_TEXTURE0); -// }*/ -// if (rpl.shaders) { -// //qDebug() << o.name() << curview << curview->determinant(); -// //setUniformMatrices((QOpenGLShaderProgram*)rpl.shaders, rpl.proj_matrix, curview, rpl.prev_proj_matrix, prevview); -// } else { -// glMatrixMode(GL_MODELVIEW); -// //setGLMatrix(curview); -// } -// o.draw((QOpenGLShaderProgram*)rpl.shaders); -// } -// foreach (ObjectBase * i, o.children_) -// renderSingleObject(*i, rpl); -} - - -void GLRendererBase::renderShadow(Light * l, QOpenGLShaderProgram * prog, QMatrix4x4 mat) { - Camera cam; - QVector3D wp = l->worldPos(); - cam.setPos(wp); - cam.setAim(wp + (l->worldTransform() * QVector4D(l->direction())).toVector3D()); - cam.setDepthStart(view->camera()->depthStart()); - cam.setFOV(l->angle_end); - //cam.apply(1.); - /*cam.rotateXY(l->angle_end); - QVector3D rdir = l->direction * cos(l->angle_end / 2. * deg2rad); - l->dir0 = cam.direction() - rdir; - cam.rotateXY(-l->angle_end); - cam.rotateZ(l->angle_end); - l->dir1 = cam.direction() - rdir;*/ - //qDebug() << rdir << l->dir0 << l->dir1; - RenderingParameters rpl; - rpl.shaders = prog; - rpl.textures = rpl.light = rpl.fog = false; - //rpl.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); - //rpl.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); - rpl.cam_offset_matrix = cam.offsetMatrix(); - QMatrix4x4 mbias; - mbias.scale(0.5, 0.5, 0.5); - mbias.translate(1., 1., 1.); - l->shadow_matrix = mbias*rpl.proj_matrix*rpl.view_matrix*rpl.cam_offset_matrix*mat;//;// * mbias; - //qDebug() << mbias; - //glPushMatrix(); - //renderSingleShadow(view->objects_, rpl); - //glPopMatrix(); -} - - -void GLRendererBase::renderSingleShadow(ObjectBase & o, RenderingParameters & rpl) { -// if (!o.isInit()) -// o.init(); -// if (!o.visible_) return; -// if (rpl.shaders) { -// //qDebug() << o.name() << curview << curview->determinant(); -// //setUniformMatrices((QOpenGLShaderProgram*)rpl.shaders, rpl.proj_matrix, rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_); -// } else { -// glMatrixMode(GL_MODELVIEW); -// //setGLMatrix(rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_); -// } -// glPolygonMode(GL_FRONT_AND_BACK, o.render_mode != ObjectBase::View ? o.render_mode : (view->rmode != ObjectBase::View ? view->rmode : GL_FILL)); -// glLineWidth(o.line_width > 0.f ? o.line_width : view->lineWidth_); -// glPointSize(o.line_width > 0.f ? o.line_width : view->lineWidth_); -// o.draw((QOpenGLShaderProgram*)rpl.shaders, true); -// foreach (ObjectBase * i, o.children_) -// renderSingleShadow(*i, rpl); -} - - - - -GLRendererBase::RenderingParameters::RenderingParameters() { - shaders = nullptr; - cur_shader = nullptr; -} - - -void GLRendererBase::RenderingParameters::prepare() { - //proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); - //view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); - viewproj_matrix = proj_matrix * view_matrix; - normal_matrix = view_matrix.normalMatrix(); - proj_matrix_i = proj_matrix.inverted(); - view_matrix_i = view_matrix.inverted(); - viewproj_matrix_i = viewproj_matrix.inverted(); -} - - -void GLRendererBase::RenderingParameters::setUniform(QOpenGLShaderProgram * prog) { - if (!prog) return; - prog->setUniformValue("qgl_ModelViewMatrix", view_matrix); - prog->setUniformValue("qgl_ProjectionMatrix", proj_matrix); - prog->setUniformValue("qgl_ModelViewProjectionMatrix", viewproj_matrix); - prog->setUniformValue("qgl_NormalMatrix", normal_matrix); - prog->setUniformValue("qgl_ModelViewMatrixInverse", view_matrix_i); - prog->setUniformValue("qgl_ProjectionMatrixInverse", proj_matrix_i); - prog->setUniformValue("qgl_ModelViewProjectionMatrixInverse", viewproj_matrix_i); - prog->setUniformValue("qgl_ModelViewMatrixTranspose", view_matrix.transposed()); - prog->setUniformValue("qgl_ProjectionMatrixTranspose", proj_matrix.transposed()); - prog->setUniformValue("qgl_ModelViewProjectionMatrixTranspose", viewproj_matrix.transposed()); - prog->setUniformValue("qgl_ModelViewMatrixInverseTranspose", view_matrix_i.transposed()); - prog->setUniformValue("qgl_ProjectionMatrixInverseTranspose", proj_matrix_i.transposed()); - prog->setUniformValue("qgl_ModelViewProjectionMatrixInverseTranspose", viewproj_matrix_i.transposed()); -} diff --git a/qglengine/glrendererbase.h b/qglengine/glrendererbase.h deleted file mode 100644 index 7076d7a..0000000 --- a/qglengine/glrendererbase.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - QGL GLRendererBase - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLRENDERERBASE_H -#define GLRENDERERBASE_H - -#include "glcamera.h" -#include "glshaders.h" - -class GLRendererBase: public QObject , protected QOpenGLExtraFunctions -{ - friend class QGLView; - Q_OBJECT -public: - GLRendererBase(QGLView * view_); - virtual void prepareScene() {;} - virtual void renderScene() = 0; - - struct RenderingParameters { - RenderingParameters(); - void prepare(); - void setUniform(QOpenGLShaderProgram * prog); - int pass; - int light_pass; - bool light; - bool fog; - bool textures; - bool prev_light; - bool prev_fog; - GLuint prev_tex[32]; - void * shaders; - QMatrix4x4 view_matrix, view_matrix_i, prev_view_matrix; - QMatrix4x4 proj_matrix, proj_matrix_i, prev_proj_matrix; - QMatrix4x4 viewproj_matrix, viewproj_matrix_i; - QMatrix3x3 normal_matrix; - QMatrix4x4 cam_offset_matrix; - QOpenGLShaderProgram * cur_shader; - }; - - RenderingParameters rp; - -protected: - virtual void setupLight(const Light & l, int inpass_index, int gl_index); - virtual void setupAmbientLight(const QColor & a, bool first_pass); - virtual void setupShadersLights(int lights_count); - virtual void setupTextures(ObjectBase & object, GLRendererBase::RenderingParameters & rp, bool first_object = false); - virtual void setupShadersTextures(ObjectBase & object, GLRendererBase::RenderingParameters & rp) {} - virtual void reloadShaders() {} - virtual void init(int width, int height) {} - virtual void resize(int width, int height) {} - - void setupLights(int pass, int lights_per_pass); - inline void applyFilteringParameters(); - void renderObjects(int pass, int light_pass, void * shaders = 0, bool textures = true, bool light = true, bool fog = true); - void renderSingleObject(ObjectBase & o, RenderingParameters & rpl); - void renderShadow(Light * l, QOpenGLShaderProgram * prog = 0, QMatrix4x4 mat = QMatrix4x4()); - void renderSingleShadow(ObjectBase & o, RenderingParameters & rpl); - - QGLView * view; - QImage white_image, violent_image; - GLuint white_image_id, violent_image_id; - -}; - -#endif // GLRENDERERBASE_H diff --git a/qglengine/glscene.cpp b/qglengine/glscene.cpp deleted file mode 100644 index 1f51bc7..0000000 --- a/qglengine/glscene.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* - QGL Scene - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "glscene.h" -#include "glcamera.h" -#include "glmesh.h" -#include "qglview.h" -#include - - -Scene::Scene() { - root_ = new ObjectBase(); - root_->setScene(this); - tree_changed = mat_changed = lights_changed = true; - destroying = false; - need_reload_materials = tree_struct_changed = true; - sel_mode_ = smSingleSelection; -} - - -Scene::~Scene() { - destroying = true; - clear(); - delete root_; -} - - -Scene * Scene::clone() { - Scene * ret = new Scene(); - ObjectBase * o = root_->clone(); - foreach (ObjectBase * co, o->children()) - ret->addObject(co); - o->clearChildren(); - delete o; - return ret; -} - - -void Scene::addObject(ObjectBase * o) { - ObjectBaseList aol = o->children(true); - attachObject(o); - foreach (ObjectBase * c, aol) - attachObject(c); - root_->addChild(o); - tree_changed = tree_struct_changed = true; -} - - -void Scene::addScene(const Scene * s) { - if (!s) return; - //qDebug() << "addScene clone ..."; - ObjectBase * o = s->root_->clone(); - o->setName(s->name()); - //qDebug() << "addScene clone ok" << o << o->children(true).size(); - addObject(o); - makeMaterialsUniqueNames(); - //qDebug() << "addScene add ok" << o; -} - - -void Scene::assignFrom(const Scene * s) { - clear(); - setName(s->name()); - foreach (Material * m, s->materials) { - Material * nm = new Material(); - *nm = *m; - nm->_changed = true; - nm->setMapsChanged(); - materials << nm; - } - for (int i = 0; i < s->root_->childCount(); ++i) { - addObject(s->root_->child(i)->clone()); - //qDebug() << i << o->child(i)->pos(); - } - tree_changed = mat_changed = lights_changed = need_reload_materials = tree_struct_changed = true; -} - - -void Scene::clear() { - selected_.clear(); - selected_top.clear(); - emitSelectionChanged(); - root_->clearChildren(true); - td_geometries << geometries; - qDeleteAll(materials); - geometries.clear(); - materials.clear(); - emit __destroyed(); - emit treeChanged();} - - -void Scene::objectsCountInternal(int * cnt, ObjectBase * where) { - ++(*cnt); - foreach (ObjectBase * i, where->children_) - objectsCountInternal(cnt, i); -} -int Scene::objectsCount(bool all) { - if (!all) return root_->childCount(); - int cnt = 0; - objectsCountInternal(&cnt, root_); - return cnt; -} - - -void Scene::removeObjectInternal(ObjectBase * o, ObjectBase * where) { - if (destroying) return; - foreach (ObjectBase * i, where->children_) { - if (o == i) { - where->removeChild(i); - setObjectMeshChanged(i); - } else - removeObjectInternal(o, i); - } -} - - -void Scene::emitSelectionChanged() { - selected_top.clear(); - foreach (ObjectBase * o, selected_) { - ObjectBase * po = o->selectedParent(); - if (!po) po = o; - if (!selected_top.contains(po)) - selected_top << po; - } - foreach (Mesh * m, geometries) - m->setAllSelectionChanged(true); - selectionChanged(); -} - - -QString Scene::uniqueName(QString n, const QSet & names) { - if (!names.contains(n)) - return n; - QString num; - while (!n.isEmpty()) { - if (n.right(1)[0].isDigit()) { - num.push_front(n.right(1)); - n.chop(1); - } else break; - } - if (!n.endsWith('_')) n += '_'; - int in = num.toInt() + 1; - QString nn = n + QString::number(in).rightJustified(3, '0'); - while (names.contains(nn)) - nn = n + QString::number(++in).rightJustified(3, '0'); - return nn; -} - - - -void Scene::removeObject(ObjectBase * o, bool inChildren) { - if (destroying) return; - o->setScene(nullptr); - setObjectMeshChanged(o); - if (inChildren) - removeObjectInternal(o, root_); - else - root_->removeChild(o); - __objectDeleted(o); - setTreeStructChanged(); -} - - -void Scene::removeObject(ObjectBase & o, bool inChildren) { - if (destroying) return; - removeObject(&o, inChildren); -} - - -void Scene::clearObjects(bool deleteAll) { - root_->clearChildren(deleteAll); - cleanUnused(); - setTreeStructChanged(); - emitSelectionChanged(); -} - - -void Scene::selectObject(ObjectBase * o, bool add_to_selection) { - //qDebug() << "selectObject" << o << add_to_selection; - if (!add_to_selection || (sel_mode_ == smSingleSelection)) clearSelection(); - if (o) { - if (!add_to_selection) o->setSelected(true); - else o->setSelected(!o->isSelected()); - gatherSelection(); - } - emitSelectionChanged(); -} - - -void Scene::selectObjects(ObjectBaseList ol, bool add_to_selection) { - if (!add_to_selection || (sel_mode_ == smSingleSelection)) clearSelection(); - foreach (ObjectBase * o, ol) { - if (!o) continue; - o->setSelected(true); - } - gatherSelection(); - emitSelectionChanged(); -} - - -void Scene::selectObjectsByMesh() { - ObjectBaseList csl = selected_; - QSet sml; - foreach (ObjectBase * o, csl) - if (o->mesh()) - sml << o->mesh(); - ObjectBaseList ol = root_->children(true); - foreach (ObjectBase * o, ol) { - if (sml.contains(o->mesh())) - o->setSelected(true); - } - gatherSelection(); - emitSelectionChanged(); -} - - -void Scene::selectObjectsByMaterial() { - ObjectBaseList csl = selected_; - QSet sml; - foreach (ObjectBase * o, csl) - if (o->material()) - sml << o->material(); - ObjectBaseList ol = root_->children(true); - foreach (ObjectBase * o, ol) { - if (sml.contains(o->material())) - o->setSelected(true); - } - gatherSelection(); - emitSelectionChanged(); -} - - -void Scene::clearSelection() { - selected_.clear(); - selected_top.clear(); - ObjectBaseList ol = root_->children(true); - foreach (ObjectBase * o, ol) { - o->selected_ = o->selected_aim = false; - } - emitSelectionChanged(); -} - - -ObjectBaseList Scene::selectedObjects(bool top_only) const { - return top_only ? selected_top : selected_; -} - - -ObjectBase * Scene::selectedObject() const { - if (selected_.isEmpty()) return 0; - return selected_[0]; -} - - -void gatherMeshes(ObjectBase * o, QSet & ums) { - if (o->mesh()) ums << o->mesh(); - for (int i = 0; i < o->childCount(); ++i) - gatherMeshes(o->child(i), ums); -} -void Scene::cleanUnused() { - QSet ums; - gatherMeshes(root_, ums); - /*QMapIterator> it(geometries_used); - while (it.hasNext()) - ums |= it.next().value().keys().toSet();*/ - for (int i = 0; i < geometries.size(); ++i) { - if (ums.contains(geometries[i])) continue; - td_geometries << geometries[i]; - geometries.removeAt(i); - --i; - } -} - - -const Box3D & Scene::boundingBox() const { - root_->calculateBoundingBox(); - return root_->boundingBox(); -} - - -Material * Scene::newMaterial(const QString & name) { - materials << new Material(name); - makeMaterialsUniqueNames(); - mat_changed = true; - return materials.back(); -} - - -void Scene::removeMaterial(Material * m) { - if (!m || !materials.contains(m)) return; - ObjectBaseList ol = root_->children(true); - foreach (ObjectBase * o, ol) - if (o->material_ == m) - o->setMaterial(0); - materials.removeAll(m); - changed_materials.removeAll(m); - mat_changed = true; -} - - -void Scene::makeMaterialsUniqueNames() { - QSet names; - foreach (Material * m, materials) { - if (m->name.isEmpty()) m->name = "default_000"; - m->name = uniqueName(m->name, names); - names << m->name; - } -} - - -ObjectBaseList Scene::objects(bool all) { - return root_->children(all); -} - - -void Scene::removeLight(Light * l) { - removeObject(l); -} - - -void Scene::dump() { - qDebug() << "Scene" << name(); - qDebug() << "Meshes:" << geometries.size(); - qDebug() << "Objects:" << root_->children(true).size(); -} - - -void Scene::gatherSelection() { - selected_.clear(); - ObjectBaseList ol = root_->children(true); - foreach (ObjectBase * o, ol) - if (o->selected_) - selected_ << o; -} - - -void Scene::attachObject(ObjectBase * o) { - if (!o) return; - o->setScene(this); - if (o->mesh()) { // search suitable mesh in this scene - o->mesh_ = attachMesh(o->mesh()); - setObjectMeshChanged(o); - } - if (o->material()) { // search suitable material in this scene - uint ohash = o->material()->hash(); - bool need_new = true; - foreach (Material * m, materials) { - if (m == o->material()) { // already exists by ptr - need_new = false; - break; - } - if (m->hash() == ohash) { // already exists by hash - need_new = false; - o->setMaterial(m); - break; - } - } - if (need_new) { // need to clone material and add to scene - Material * nmat = new Material(); - *nmat = *(o->material()); - nmat->setMapsChanged(); - o->setMaterial(nmat); - materials << nmat; - } - } - setTreeStructChanged(); -} - - -Mesh * Scene::attachMesh(Mesh * mesh) { - if (!mesh) return 0; - uint mhash = mesh->hash(); - foreach (Mesh * m, geometries) { - if (m == mesh) { // already exists by ptr - return m; - } - if (m->hash() == mhash) { // already exists by hash - return m; - } - } - // need to clone mesh and add to scene - Mesh * nmesh = mesh->clone(); - geometries << nmesh; - return nmesh; -} - - -void Scene::setTreeChanged() { - if (destroying) return; - tree_changed = true; - foreach (Mesh * m, geometries) { - m->setAllObjectsChanged(true); - m->setAllSelectionChanged(true); - } - gatherSelection(); -} - - -void Scene::setTreeStructChanged() { - tree_struct_changed = true; -} - - -void Scene::setObjectMeshChanged(ObjectBase * o) { - if (o) o->setObjectsChanged(); -} - - -void Scene::prepareTree(ObjectBase * o) { - foreach (ObjectBase * co, o->children_) { - if (co->isHidden()) continue; - switch (co->type_) { - case ObjectBase::glLight: { - Light * l = globject_cast(co); - lights_used[l->light_type] << l; - } break; - case ObjectBase::glMesh: - if (co->mesh()) { - geometries_used[co->pass()][co->mesh()] << co; - co->setObjectsChanged(); - } - break; - case ObjectBase::glCamera: - cameras_used << globject_cast(co); - break; - default: break; - } - prepareTree(co); - } -} - - -bool Scene::prepare() { - changed_materials.clear(); - foreach (Material * m, materials) { - if (m->_changed) { - need_reload_materials = tree_changed = true; - changed_materials << m; - } - } - - ObjectBaseList aol; - if (!tree_changed && !mat_changed) return false; - aol = root_->children(true); - if (tree_changed) { - geometries_used[rpSolid ].clear(); - geometries_used[rpTransparent].clear(); - lights_used.clear(); - cameras_used.clear(); - prepareTree(root_); - if (tree_struct_changed) { - tree_struct_changed = false; - cleanUnused(); - QMetaObject::invokeMethod(this, "treeChanged", Qt::QueuedConnection); - } - tree_changed = false; - lights_changed = true; - } - mat_changed = false; - return true; -} - - -void Scene::destroy(QOpenGLExtraFunctions * f) { - foreach (Mesh * g, geometries) - g->destroy(f); -} - - -void Scene::destroyUnused(QOpenGLExtraFunctions * f) { - //if (!td_geometries.isEmpty()) qDebug() << "destroyUnused" << td_geometries.size(); - foreach (Mesh * i, td_geometries) - i->destroy(f); - qDeleteAll(td_geometries); - td_geometries.clear(); -} - - -QDataStream & operator <<(QDataStream & s, const Scene * p) { - ChunkStream cs; - //qDebug() << "place" << p->name() << "..."; - QVector geom_ind, mat_ind; - ObjectBaseList cl = p->root_->children(true); - geom_ind.reserve(cl.size()); - mat_ind.reserve(cl.size()); - foreach (ObjectBase * c, cl) { - geom_ind << p->geometries.indexOf(c->mesh()); - mat_ind << p->materials.indexOf(c->material()); - } - cs.add(1, p->name_).add(10, p->geometries).add(11, p->materials) - .add(20, p->root_).add(21, geom_ind).add(22, mat_ind); - s << qCompress(cs.data()); - //s << cs.data(); - return s; -} -QDataStream & operator >>(QDataStream & s, Scene *& p) { - p = new Scene(); - //ChunkStream cs(s); - - QByteArray ba; - s >> ba; - ba = qUncompress(ba); - ChunkStream cs(ba); - - QVector geom_ind, mat_ind; - while (!cs.atEnd()) { - switch (cs.read()) { - case 1 : cs.get(p->name_); break; - case 10: cs.get(p->geometries); break; - case 11: cs.get(p->materials); break; - case 20: cs.get(p->root_); p->root_->setScene(p); break; - case 21: cs.get(geom_ind); break; - case 22: cs.get(mat_ind); break; - } - } - p->makeMaterialsUniqueNames(); - ObjectBaseList cl = p->root_->children(true); - int cnt = qMin(qMin(cl.size(), geom_ind.size()), mat_ind.size()); - for (int i = 0; i < cnt; ++i) { - ObjectBase * c(cl[i]); - if (geom_ind[i] >= 0) c->mesh_ = p->geometries[geom_ind[i]]; - if (mat_ind [i] >= 0) c->material_ = p->materials [mat_ind [i]]; - } - return s; -} diff --git a/qglengine/glscene.h b/qglengine/glscene.h deleted file mode 100644 index e9e39c8..0000000 --- a/qglengine/glscene.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - QGL Scene - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLSCENE_H -#define GLSCENE_H - -#include "gltypes.h" - - -class Scene: public QObject { - Q_OBJECT - friend class QGLView; - friend class RendererBase; - friend class Renderer; - friend class RendererMaterial; - friend class RendererService; - friend class RendererSelection; - friend class ObjectBase; - friend class Light; - friend QDataStream & operator <<(QDataStream & s, const Scene * p); - friend QDataStream & operator >>(QDataStream & s, Scene *& p); -public: - explicit Scene(); - virtual ~Scene(); - - enum SelectionMode { - smNoSelection, - smSingleSelection, - smMultiSelection, - }; - - Q_ENUMS(SelectionMode) - - QString name() const {return name_;} - void setName(const QString & name) {name_ = name;} - - bool prepare(); - - Scene * clone(); - - /// Add object \"o\" to scene and take its ownership - /// All materials and geometries used by \"o\" tree - /// copied into this scene - void addObject(ObjectBase * o); - - void addScene(const Scene * s); - void assignFrom(const Scene * s); - void clear(); - - int objectsCount(bool all = false); - ObjectBaseList objects(bool all = false); - ObjectBase * rootObject() {return root_;} - void removeObject(ObjectBase * o, bool inChildren = true); - void removeObject(ObjectBase & o, bool inChildren = true); - void clearObjects(bool deleteAll = false); - - SelectionMode selectionMode() const {return sel_mode_;} - void setSelectionMode(SelectionMode mode) {sel_mode_ = mode;} - void selectObject(ObjectBase * o, bool add_to_selection = false); - void selectObjects(ObjectBaseList ol, bool add_to_selection = false); - void selectObjectsByMesh(); - void selectObjectsByMaterial(); - void clearSelection(); - ObjectBaseList selectedObjects(bool top_only = false) const; - ObjectBase * selectedObject() const; - void cleanUnused(); - - const Box3D & boundingBox() const; - - QVector getMaterials() const {return materials;} - Material * newMaterial(const QString & name = QString()); - void removeMaterial(Material * m); - void makeMaterialsUniqueNames(); - - void removeLight(Light * l); - - void dump(); - void destroy(QOpenGLExtraFunctions * f); - void destroyUnused(QOpenGLExtraFunctions * f); - -protected: - void prepareTree(ObjectBase * o); - void gatherSelection(); - void objectsCountInternal(int * cnt, ObjectBase * where); - void removeObjectInternal(ObjectBase * o, ObjectBase * where); - void emitSelectionChanged(); - QString uniqueName(QString n, const QSet & names); - - void attachObject(ObjectBase * o); - Mesh * attachMesh(Mesh * mesh); - void setTreeChanged(); - void setTreeStructChanged(); - void setMaterialsChanged() {mat_changed = true;} - void setLightsChanged() {lights_changed = tree_changed = true;} - void setObjectMeshChanged(ObjectBase * o); - - - QString name_; - ObjectBase * root_; - bool tree_changed, mat_changed, lights_changed, destroying; - bool need_reload_materials, tree_struct_changed; - QVector mat_map_changed; - - QVector geometries, td_geometries; - QVector materials; - - QMap> geometries_used; // [pass][mesh] = ObjectBaseList - QMap> lights_used; // by Light::Type - QList cameras_used; - QVector changed_materials; - - SelectionMode sel_mode_; - ObjectBaseList selected_, selected_top; - -protected slots: - - -signals: - void __objectDeleted(ObjectBase * o); - void __destroyed(); - void treeChanged(); - //void treeStructChanged(); - void selectionChanged(); - -}; - - -QDataStream & operator <<(QDataStream & s, const Scene * p); -QDataStream & operator >>(QDataStream & s, Scene *& p); - -#endif // GLSCENE_H diff --git a/qglengine/gltexture_manager.cpp b/qglengine/gltexture_manager.cpp deleted file mode 100644 index fb226b1..0000000 --- a/qglengine/gltexture_manager.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - QGL TextureManager - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "gltexture_manager.h" -#include "gltypes.h" - -QStringList TextureManager::search_pathes("."); - - -QVector3D colorVector(QRgb c) { - return QVector3D(((uchar*)(&c))[0] / 255.f, ((uchar*)(&c))[1] / 255.f, ((uchar*)(&c))[2] / 255.f); -} - - -QString TextureManager::findFile(const QString & path) { - return ::findFile(path, search_pathes); -} - - -GLuint TextureManager::loadTexture(const QString & path, bool ownership, bool bump) { - QString p = findFile(path); - if (p.isEmpty()) return 0; - int tid = textureID(p, bump); - if (tid > 0) { - //qDebug() << "[TextureManager] Found" << path << "as" << tid; - return tid; - } - QImage image(p); - if (bump) convertToNormal(image); - //qDebug() << p << image.width() << image.height() << image.format() << bump; - GLuint tid_ = tid; - createGLTexture(f, tid_, image);///currentQGLView->bindTexture(image, GL_TEXTURE_2D); - tid = tid_; - if (tid == 0) { - qDebug() << "[TextureManager] Can`t load" << p; - return tid; - } - qDebug() << "[TextureManager] Loaded" << p << "as" << tid; - if (ownership) { - tex_ids[bump ? 1 : 0].insert(p, tid); - tex_im [bump ? 1 : 0].insert(p, image); - } - return tid; -} - - -GLuint TextureManager::loadTexture(const QImage & im, bool ownership, bool bump) { - if (im.isNull()) return 0; - QImage image(im); - if (bump) convertToNormal(image); - GLuint tid = 0; - createGLTexture(f, tid, im);///currentQGLView->bindTexture(image, GL_TEXTURE_2D); - if (tid == 0) { - qDebug() << "[TextureManager] Can`t load image"; - return tid; - } - //qDebug() << "[TextureManager] Loaded image as" << tid; - return tid; -} - - -QImage TextureManager::loadTextureImage(const QString & path, bool bump) { - QString p = findFile(path); - if (p.isEmpty()) return QImage(); - QImage ret = tex_im[bump ? 1 : 0].value(p); - if (!ret.isNull()) return ret; - ret = QImage(p); - if (bump) convertToNormal(ret); - tex_im[bump ? 1 : 0].insert(p, ret); - return ret; -} - - -void TextureManager::reloadTexture(GLuint tid, const QString & path) { - QString p = findFile(path); - if (p.isEmpty() || (tid == 0)) return; - QImage image(p); - createGLTexture(f, tid, image); - if (tid == 0) { - qDebug() << "[TextureManager] Can`t load" << p; - return; - } - qDebug() << "[TextureManager] Reloaded" << p << "as" << tid; -} - - -void TextureManager::reloadTexture(GLuint tid, const QImage & im) { - if (im.isNull() || (tid == 0)) return; - QImage image(im); - createGLTexture(f, tid, image); - qDebug() << "[TextureManager] Reloaded" << tid; -} - - -void TextureManager::convertToNormal(QImage & im) { - if (im.isNull()) return; - QImage sim = im.convertToFormat(QImage::Format_ARGB32); - float sum[3] = {0., 0., 0.}; - llong a = 0; - const uchar * sd = sim.constBits(); - for (int i = 0; i < sim.height(); i++) { - for (int j = 0; j < sim.width(); j++) { - sum[2] += sd[a] / 255.f - 0.5f; ++a; - sum[1] += sd[a] / 255.f - 0.5f; ++a; - sum[0] += sd[a] / 255.f - 0.5f; ++a; - ++a; - } - } - float wh = sim.width() * sim.height(); - sum[0] /= wh; - sum[1] /= wh; - sum[2] /= wh; - //qDebug() << sum[0] << sum[1] << sum[2]; - if ((qAbs(sum[0]) <= 0.05f) && (qAbs(sum[1]) <= 0.05f) && (sum[2] >= 0.25f)) /// already normal - return; - //qDebug() << "convert to normal"; - QImage dim = QImage(sim.width(), sim.height(), QImage::Format_ARGB32); - int tx, ty, w = sim.width(), h = sim.height(); - a = 0; - uchar * dd = dim.bits(); - for (int i = 0; i < sim.height(); i++) { - for (int j = 0; j < sim.width(); j++) { - tx = j - 1; - tx = tx < 0 ? w + tx : tx % w; - ty = i - 1; - ty = ty < 0 ? h + ty : ty % h; - QVector3D p[3], res; - p[0] = colorVector(sim.pixel(j, i)); - p[1] = colorVector(sim.pixel(j, ty)); - p[2] = colorVector(sim.pixel(tx, i)); - res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f)); - res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f)); - tx = (j + 1) % w; - ty = (i + 1) % h; - p[1] = colorVector(sim.pixel(j, ty)); - p[2] = colorVector(sim.pixel(tx, i)); - res.setY(piClamp(0.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f)); - res.setX(piClamp(0.5f - (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f)); - res.setZ(1.f); - dd[a] = res.z() * 255; ++a; - dd[a] = res.y() * 255; ++a; - dd[a] = res.x() * 255; ++a; - dd[a] = 255; ++a; - } - } - im = dim; - //im.save("_normal.png"); -} - - -bool TextureManager::loadTextures() { - QFileInfoList fil; - foreach (const QString & i, tex_pathes) - loadTexture(i, true); - tex_pathes.clear(); - return true; -} - - -void TextureManager::deleteTextures() { - for (int i = 0; i < 2; ++i) { - QList texs = tex_ids[i].values(); - qDebug() << "[TextureManager] Delete" << texs.size() << "textures"; - if (!texs.isEmpty()) f->glDeleteTextures(texs.size(), &texs[0]); - tex_ids[i].clear(); - tex_im [i].clear(); - } -} - - -void TextureManager::deleteTexture(const QString & name) { - for (int i = 0; i < 2; ++i) { - if (tex_ids[i].contains(name)) { - GLuint id = tex_ids[i][name]; - f->glDeleteTextures(1, &id); - tex_ids[i].remove(name); - tex_im [i].remove(name); - } - } -} - - -void TextureManager::clearImageCache() { - tex_im[0].clear(); - tex_im[1].clear(); -} diff --git a/qglengine/gltexture_manager.h b/qglengine/gltexture_manager.h deleted file mode 100644 index 95af8b9..0000000 --- a/qglengine/gltexture_manager.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - QGL TextureManager - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLTEXTUREMANAGER_H -#define GLTEXTUREMANAGER_H - -#include -#include -#include -#include -#include - - -class TextureManager { -public: - TextureManager(QOpenGLExtraFunctions * f_): f(f_) {} - virtual ~TextureManager() {} - - static void addSearchPath(const QString & path) {if (!search_pathes.contains(path)) search_pathes << path;} - static void clearSearchPathes() {search_pathes.clear();} - static QStringList searchPathes() {return search_pathes;} - static QString findFile(const QString & path); - GLuint loadTexture(const QString & path, bool ownership = true, bool bump = false); - GLuint loadTexture(const QImage & image, bool ownership = true, bool bump = false); - QImage loadTextureImage(const QString & path, bool bump = false); - void reloadTexture(GLuint tid, const QString & path); - void reloadTexture(GLuint tid, const QImage & image); - int textureID (const QString & path, bool bump = false) {return tex_ids[bump ? 1 : 0][path];} - QImage textureImage(const QString & path, bool bump = false) {return tex_im [bump ? 1 : 0][path];} - void addTexture(const QString & path) {tex_pathes << path;} - bool loadTextures(); - void deleteTextures(); - void deleteTexture(const QString & name); - void clearImageCache(); - -protected: - static void convertToNormal(QImage & im); - - static QStringList search_pathes; - - QMap tex_ids[2]; - QMap tex_im [2]; - QStringList tex_pathes; - - QOpenGLExtraFunctions * f; - -}; - - -#endif // GLTEXTUREMANAGER_H diff --git a/qglengine/glwidget.cpp b/qglengine/glwidget.cpp deleted file mode 100644 index 921652b..0000000 --- a/qglengine/glwidget.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* - QGL GLWidget - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "glwidget.h" -#include "qglview.h" -#include - - -GLWidget::GLWidget(QWidget *parent) : QWidget(parent) { - view_ = new QGLView(); - view_->setFlags(windowFlags() | Qt::FramelessWindowHint); - container = QWidget::createWindowContainer(view_, this); - lay = new QVBoxLayout(this); - lay->addWidget(container); - lay->setContentsMargins(0, 0, 0, 0); - lay->setSpacing(0); - setMouseTracking(true); - setWindowIcon(QIcon("://icons/qglview.png")); - connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked); -} - - -QColor GLWidget::backColor() const { - return view_->backColor(); -} - - -qreal GLWidget::lineWidth() const { - return view_->lineWidth(); -} - - -qreal GLWidget::FOV() const { - return view_->FOV(); -} - - -qreal GLWidget::depthStart() const { - return view_->depthStart(); -} - - -QColor GLWidget::ambientColor() const { - return view_->ambientColor(); -} - - -bool GLWidget::isLightEnabled() const { - return view_->isLightEnabled(); -} - - -bool GLWidget::isGrabMouseEnabled() const { - return view_->isGrabMouseEnabled(); -} - - -bool GLWidget::isMouseRotateEnabled() const { - return view_->isMouseRotateEnabled(); -} - - -bool GLWidget::isMouseSelectionEnabled() const { - return view_->isMouseSelectionEnabled(); -} - - -bool GLWidget::isCameraOrbit() const -{ - return view_->isCameraOrbit(); -} - - -bool GLWidget::isHoverHaloEnabled() const { - return view_->isHoverHaloEnabled(); -} - - -QColor GLWidget::hoverHaloColor() const { - return view_->hoverHaloColor(); -} - - -qreal GLWidget::hoverHaloFillAlpha() const { - return view_->hoverHaloFillAlpha(); -} - - -bool GLWidget::isSelectionHaloEnabled() const { - return view_->isSelectionHaloEnabled(); -} - - -QColor GLWidget::selectionHaloColor() const { - return view_->selectionHaloColor(); -} - - -qreal GLWidget::selectionHaloFillAlpha() const { - return view_->selectionHaloFillAlpha(); -} - - -Scene * GLWidget::scene() { - return view_->scene(); -} - - -void GLWidget::addObject(ObjectBase * o) { - view_->scene()->addObject(o); -} - - -QByteArray GLWidget::saveCamera() { - return view_->saveCamera(); -} - - -void GLWidget::restoreCamera(const QByteArray &ba) { - view_->restoreCamera(ba); -} - - -void GLWidget::stop() { - view_->stop(); -} - - -void GLWidget::start(float freq) { - view_->start(freq); -} - - -void GLWidget::setBackColor(const QColor & c) { - view_->setBackColor(c); -} - - -void GLWidget::setLineWidth(const qreal & arg) { - view_->setLineWidth(arg); -} - - -void GLWidget::setFOV(const qreal & arg) { - view_->setFOV(arg); -} - - -void GLWidget::setDepthStart(const qreal & arg) { - view_->setDepthStart(arg); -} - - -void GLWidget::setAmbientColor(const QColor & arg) { - view_->setAmbientColor(arg); -} - - -void GLWidget::setLightEnabled(const bool & arg) { - view_->setLightEnabled(arg); -} - - -void GLWidget::setGrabMouseEnabled(const bool & arg) { - view_->setGrabMouseEnabled(arg); -} - - -void GLWidget::setMouseRotateEnabled(const bool & arg) { - view_->setMouseRotateEnabled(arg); -} - - -void GLWidget::setMouseSelectionEnabled(const bool & arg) { - view_->setMouseSelectionEnabled(arg); -} - - -void GLWidget::setCameraOrbit(const bool & arg) { - view_->setCameraOrbit(arg); -} - - -void GLWidget::setHoverHaloEnabled(const bool & arg) { - view_->setHoverHaloEnabled(arg); -} - - -void GLWidget::setHoverHaloColor(const QColor & arg) { - view_->setHoverHaloColor(arg); -} - - -void GLWidget::setHoverHaloFillAlpha(const qreal & arg) { - view_->setHoverHaloFillAlpha(arg); -} - - -void GLWidget::setSelectionHaloEnabled(const bool & arg) { - view_->setSelectionHaloEnabled(arg); -} - - -void GLWidget::setSelectionHaloColor(const QColor & arg) { - view_->setSelectionHaloColor(arg); -} - - -void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) { - view_->setSelectionHaloFillAlpha(arg); -} - - -void GLWidget::viewDoubleClicked() { - if (view_->windowState() == Qt::WindowFullScreen) { - view_->showNormal(); - container = QWidget::createWindowContainer(view_, this); - lay->addWidget(container); - container->show(); - } else { - view_->setParent(nullptr); - view_->showFullScreen(); - lay->removeWidget(container); - } -} diff --git a/qglengine/glwidget.h b/qglengine/glwidget.h deleted file mode 100644 index b72265d..0000000 --- a/qglengine/glwidget.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - QGL GLWidget - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef GLWIDGET_H -#define GLWIDGET_H - -#include - - -class QGLView; -class ObjectBase; -class Scene; - -class GLWidget : public QWidget -{ - Q_OBJECT - Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) - Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth) - Q_PROPERTY (qreal FOV READ FOV WRITE setFOV) - Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart) - Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) - Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) - Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) - Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) - Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) - Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) - Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) - Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) - Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) - Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) - Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) -public: - explicit GLWidget(QWidget *parent = nullptr); - QGLView * view() {return view_;} - - QColor backColor() const; - qreal lineWidth() const; - qreal FOV() const; - qreal depthStart() const; - QColor ambientColor() const; - bool isLightEnabled() const; - bool isGrabMouseEnabled() const; - bool isMouseRotateEnabled() const; - bool isMouseSelectionEnabled() const; - bool isCameraOrbit() const; - bool isHoverHaloEnabled() const; - QColor hoverHaloColor() const; - qreal hoverHaloFillAlpha() const; - bool isSelectionHaloEnabled() const; - QColor selectionHaloColor() const; - qreal selectionHaloFillAlpha() const; - Scene * scene(); - - void addObject(ObjectBase * o); - QByteArray saveCamera(); - void restoreCamera(const QByteArray & ba); - -public slots: - void stop(); - void start(float freq = 60.0); - void setBackColor(const QColor & c); - void setLineWidth(const qreal & arg); - void setFOV(const qreal & arg); - void setDepthStart(const qreal & arg); - void setAmbientColor(const QColor & arg); - void setLightEnabled(const bool & arg); - void setGrabMouseEnabled(const bool & arg); - void setMouseRotateEnabled(const bool & arg); - void setMouseSelectionEnabled(const bool & arg); - void setCameraOrbit(const bool & arg); - void setHoverHaloEnabled(const bool & arg); - void setHoverHaloColor(const QColor & arg); - void setHoverHaloFillAlpha(const qreal & arg); - void setSelectionHaloEnabled(const bool & arg); - void setSelectionHaloColor(const QColor & arg); - void setSelectionHaloFillAlpha(const qreal & arg); - -private slots: - void viewDoubleClicked(); - -private: - QWidget * container; - QGLView * view_; - QLayout * lay; - -signals: -}; - -#endif // GLWIDGET_H diff --git a/qglengine/icons/add-type-camera.png b/qglengine/icons/add-type-camera.png deleted file mode 100644 index 13b55886bebf154e159c7b28a546517bd96b4600..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14827 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 R#ozz{002ovPDHLkV1hwxS~vgz diff --git a/qglengine/icons/add-type-empty.png b/qglengine/icons/add-type-empty.png deleted file mode 100644 index df5f5b3ab51cf1bac86a9b2d2ed72afb1975838d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10989 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 b>AC+0M4087lq_tB00000NkvXXu0mjfl1S{c diff --git a/qglengine/icons/add-type-geo.png b/qglengine/icons/add-type-geo.png deleted file mode 100644 index b983991176c58b64ff1a3cd3326fe80f9d9fd648..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10226 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 diff --git a/qglengine/icons/add-type-light.png b/qglengine/icons/add-type-light.png deleted file mode 100644 index a896c1a43ce58ebeeec35cc6e98df586dfc6e032..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14284 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 diff --git a/qglengine/icons/application-exit.png b/qglengine/icons/application-exit.png deleted file mode 100644 index 8adbcba957b33edb54413f3bc520c42c50134006..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32537 zcmX6_cRbbq_kZ1iYhBmK$i)>!b}8BS+8G&9nYpq`%1C5id#^|&+)_r#$SU(%QOGKh zb&ZS=GP=0<-Ou;;$9>%Uc)ahu@7F!A^E%IQ&f~_J8tbt#on!(4ut-%W_eT7rH8?bwte4kCb{U!Kh}M$vFKkdlBD}{ zus1k#QO)m9uO&ukue)nSL2B$~SkSzP&{%>h_?wpU!)qRrniABQEW$Ef?Cp_~T1v@R>`w`s#nvu0EILRICmDaQ&H|N=KWpxtyHM zZSI*Hmh;2X6w5f1-C3Ws3tOHyse6xDyU_ZhqYIGnAl{2WQe^9c#jV23QU5z^RUO80PRt?3V?{0mbwYj02XVU<2S9tzYLZWo8mDtCP z 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 diff --git a/qglengine/icons/collapse.png b/qglengine/icons/collapse.png deleted file mode 100644 index ec329aa1243e2708a027e7ba414374e1561050b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13144 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 diff --git a/qglengine/icons/configure.png b/qglengine/icons/configure.png deleted file mode 100644 index 2a819572c7bcc8f25e768bfcd8c9ded46763853b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32993 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 diff --git a/qglengine/icons/dialog-cancel.png b/qglengine/icons/dialog-cancel.png deleted file mode 100644 index ace88ab0b4ad7d743e0173d7638eae6b807afe7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45200 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 diff --git a/qglengine/icons/dialog-close.png b/qglengine/icons/dialog-close.png deleted file mode 100644 index 6072634c29af12ad1fefccab20f4940c7d56379a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39321 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 Zw~$@LQ$lmWGh0-nthuQLb7CE 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 diff --git a/qglengine/icons/document-open.png b/qglengine/icons/document-open.png deleted file mode 100644 index 63380e488e814f13da2c451a95966598e21a5e15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8621 zcmd6MWkA%=^Z(v)$k8EY5+tNcxnGUF~{Fy;oA!Ry|iY5^(?}zfbLB0K#Qi0C-P}1Q^z9aF84n008&1|L;jw zjkr!bkH-yG@bpQzI>{|;yN;M89vZao_V?{>?oGcK`@D4>UT?>#2H3Z4jdddy{fazy zF9J8%==BrXJ9Fg`mp(~Ez)C0r?)lNjhilru4>9;Cnwbp0I(F+ite%Kd9<*q!`qAHy-h z&sY)L1SjIRr~TX5U9LyeK~lQI0BajS6I9kEjcE3OZKG?J9_~~3$Yv={ocG1sNX`tG%^t~Oi745 zE(*Pft-WjLd$9tTPo(^6{{}`S1@QUUC_Kfdmx=53gp7eIsT*|;;MRg?m#Kt<*hpxy zBjX%jW+29^?R|@H<$p>n!dCcwh!n+L-zh+ARtrc3d|(|nP$N*>fr#1N>_)Qi!mOaH?@P6Dy)a+24_ojnOy zg&()P{&5S-v78$Y+87e#0r5Y&xE}!_Ch{|ii~_vEAkj%Foj$M|qCas_%E~MR_?ULf zI+}WCywQwm00ckO<$d^A=?_r~_ih5)<24D6|_jkT_Lca4E*5)KT6^ZJh?VL+pVvKrL7vmgK}FK0|^ z1};tk2Q1c?CM$5gd*cMqJT_*>=#TH$r{Usr0NR*FCl;y!gfmXiXS}{KG)t5aV$hYD ze9jFbkSxohzm>@_xDZKEW|Cfvr^ughrXY?CfQsEPdt3p`11xx}N8bo%!s-4|M-SmN z^$q<0zF)m)AVe*AVnrXPXbWMP(X+1ql)40d1AOw}-G6$J$?L5UXll_1Sc}IJAgOPl z9N}VR{EZOp_X)~t;cTWG!alWS5c`xUmR)~ZX9gZi2#ts^5Ez4(^jH*@^9~PSdclCm zo3K#O7~siaeVP8628Bb474db9xb^f;9j;&%6V|}H9*{RlFpy*8_#uDmyI~O*{VcA> z6}%3OTbEK*0;}IH5LKecH_VKjfgCg2_Ki=C21N+@wx@);8a&6MO#9hc(00j>SsnT( zAa(rTKP#-wqxvgwo2&usEDPN*vu()dvDdJe?IDFNDp*5CH+Y?3q9_QdT2&!fmj_Ss z4!#OtP6?)`lD4k)!xVP9M==TBG*D7XhVogHr%uy+db(8ywYt{gd58 zg+oVJrqQ1gW<1P~(E5rH>=HpL-MU=n$ryS~Bz)Bfu@`J3}^Vty%^U#w!C0f;p~-pk+p;Bcw+gmUQ1)+ZQH6G-81 zJD)SW3NVDqPD2Dozgn5yT9>6*g1#lcQ&e+?c+ieYfl5wO;=sqT%ye$^Vx#A`UrbYJsO)CXZCRwkcXPd{ z^M$$5LYJ63G%)eq3tpI@!Z*0!`X%qJ_hbZ}KYZqlYq^h_J3@c^l?@)=y!yzTf3}4Z zKeX53D2tb7GcdM#+UotzSwW=B903;IT9KawX@1N69u!dU`FU^|IjnkncH1tML*Q)d zvuUM?&$^zPuX)|qJ+S%iw+ttzyenD>gHMoHkofZ)!$ zJ#3$WYVRO$;#=Ex^6ULOGfO?Qig;5L%N6IhI>i{34FGd7k3?pL)|c^xJ9Z8hsWt|< zfkL<-*3(m+>eZB^R!*@;fhYxoAMqb)mX{m8O&?zkz>n##9(R@vyW+kv&QbZ2ZM5@> zKkD6;-rcM$ZD$)8Kwta9vMrM;XYYMlBcxx-UUw8YXXNN~{K_x4_32k+U+U(uk>y9A zHCuRV&+xhT$IC)Htw*^_(Dv^_UHAOfn%Q?4n%Lp#Q_h7JOm~|7GbMKF`Zl?4(rsl* zrndEbIi@Hji@HW-T}Lxv`pJm>e%MFx2im!d5WgB`#4}(^nCGXht}b!#npT#-QU6NQ zNpmGPa);F4r{E5Ga_g0iu~H~+SE$sUwWw>TSmd2YxxGidh$eq1I1yYfGn<$1W&Wi4wYF!^{;9wR?vQLTsBBPrNsJfc@K6z9}zBDXiLucxOeQlPkF*2v45po&-q)RUgg-C zg%Uq?)0tfw>!^KF_R^>Z2BmeiCJpfBTad4=?(MzO+UCXMvvILrlSs09x+6z#Z^0Wf zQQGB&l_}GPb9cLBI>a9!0Vo!v#K@AllpgIz6(7b_8u@$frR!&KAhtK~%4A2FiA=kA zjCA#7^o&iO#rl2@&4LO=>|0J`Dq(Vl?99~QxM|0j>87*v)fs~oR*^oh0W*6`d7^fC zWwodhyI|gCeO4BfS7YC@1SOG2AY`OoqzWh^!Qn{5?==N;p8+@ zrENNyKl6Ck7>tOf;TaHOp|T_jx5`( z*-k&ksp3p@Eg^i@pqK>H;-ilPdNJiHa#Lu+45Rgg1D%=WUS*60~u9kZ}O z@~@+MgJOw$Z17A*#aEzSoCTiT3u4XP92~dukPlP30$yczc7%E_R<@8H63px*JgS}Q z6VNdWoaAKwqvZ(c^7Df#&5{{ArrSP2yFa!$ekVI?VDh}<&fqu&Ja)$?jul!3zfO{^#7LF<^)R8Y}AeVE*0ORcSmT~E(MVd3d@1rCN%dvx(lRvZ5FE&3*v zi4@p4k2h)l2ypAGj;>_Nn3PNpK|N#Ptw^YUn+gS+n?U+r>spIBJE!5@^*>EL2-iQ7 zP`Fbg@-h%kJ#12UaT^P9^zpiF^H%wtM_WZ@0c2i9_}MX&i)tP(plB_9R8`5V-x?`C zbv|}vxYT#>8T5GDjc~pBw(@NFelb1o#T13ED<2n>;m`u|K!z1eQu_L{tp6FFTC-#{ z{Og|McQCfZw(6wLzx$dlxORK66>W>RU zSTV-NI2;KzFe^^9cHCOwa{lw`P)OzWq^bMV@FY!TpqqwUh19+5eksVeQAm^~CA3{X z6$CwFCdX`Y8;_4&SV~{4tJQxYINGQ?l|48bfSe@YowZkG?ECGiQ?ku)E~LknX`JZ3 zJRo5OTY4RE&=RJEU=c(V*y`qwFb4@r9SrG|Umc0){=RyTwf5IjV=nhY+^a6h%-{B( zsJk+m28r%xsUVWEyB?PulY~Sa-3@g; zMb=nins}HctE|-M0_1`E0GylopUuihR3A)SI$E@#rZI_yj=Ru)I`H7VMf zT95jqg3isyB5{e$JCIu1LsYuIi+rw>fSPs?I8|2rd)TS}GcPsN=q+6wruwwXQsjwC z8@KDGc~wgDjV?|3P!qknzzGjQyqiiXWH4?hxakcPm@M0K#TQa>O*;|MKI>v5cQcsC ztdKLWlS+x-nmb$Jz0U8>-$*IOWk|R|j`@mA{+)RPu!zZP(vsocjIWXACXAIEUHdt74^9%TAJlC!!a{!s+}1I%IdnVBIm&H0wyOAc0?EWy*# zb+ujw&vP(DFr(8Cp}9CWZK>C09*|_NA4JnyBO_!e4z8jGj><}})qaadO7>WQ=bs;VYg zYepk&hcG6|@fWe=+?~(qHi$lNG2>%?yyr&V%+{vunz}rpt{WL)Hn)PSXFD4oY@bBc zDf#u1)gR;^t2>TgfAz`DsiKvWKhe|-D?lYK#Rdv7=lyB0f{#8pt?jsEk-A>+qvuu2 zgDay0on7yDz~T7ORYR5J8`A<3cPajzR2rQF+Jt!aTZ`|rBtCY)fJ+nWu35JB4QHv# zegjiCZi=#k&=+|}H+E+#7EL+ptf%1B{iXwjY~pQ_e;lYjJMv`-bs^c|+Y~VI5G?xx z%HyDJ&O>X*tFL+0F*Qg)-fveArhO|B3#dS0Zzf$pVeFG1 z&%b=c0kN-Hb|WWwtnP)eKy99Dmy%^fEN!4;sz{R26jgZ$?3AE2W{o;2w5+>OEk|6#*A3GQqbSTWcv+GO4Ejl z6bD1Qc9wTf&(eW12xKXXG&e#Qm;lk`d3iubx`6k(=pgl{Zx>yKig9#el7AWJ12Q(m zcFnSH?j>fTF>9gi)nd(%$v6Z%La+MaplAdH8{WJ3e$b)alVy57#xBWj#o7w)rJ5t< z=jA*U65>@vXngc+E2b7^dow#yp;+~Tcqmj;1S%uXg8_mBpb6vw4>?Nrv@|p^)4V(S z{=cMdzX8RPDPHrj`!~zmM>W$MF`<^)Md*j^^&!`mA?33+&os!P24E~Azv4!8h?q+* zBl$?>Fc7(3(DLF8{p*CP)$(_w@k+YxMZU*j%Vn^3d%TqghA-6$@h-(h8gdv_S<_hD zrSD)~cpzVwTK%cYng6tZ;!)1NJ>={07dVeM4i#=&YYV4N(HV$$Hm&o0kB|&B003OS z2~Xz7{N_FRIsQ5=H-X%WVyc9vb?_+hsk_2yDLMQ&Yy@v}a)_!XN?ZBqM>e11cnYhB z$?48;a_~|^4%9c#xad`RCaMw-oP|9KC@S6L7QxG?7%n{DEbeenoxUpvJZgoGw{jEu zTlJ!Td)fDM5O&1U1!ScMN7%%l2v7h)q4FEi4ySinPJD+dVU97T&)gf5G`GqRdqh;P zczvPv%*27!%(^{e#B>qQ5AH&hR%V@^F68&ED>fl_S?FxsJmae8g-Cq-ao}Rg`Xb5~ z7B`CHq4Q=>$|GKLw+eCq?snh|`MA5HPBG7p_^;!EUnYKJQ8|Sm%i`r}p$%e;&m%S{Nt&SFDeU*PP zeaK8AS3=CNz|n^f;XsXu_d7nD`RaYTFsL8Zow$U&@n@m08yTXk z@*@Px&6v&ocKxnUL~L0F|KHIfsSdkWBiee?r~PHp))tNP2Zs=|B6hTzR&CsPN1=KL!1S40JuDJjon%P_|ggo1)FyCT@;< z>8zGrXzYJ>E01b)+zr=hnwf2RYdzZJnYPXnbs7iZ1QhRCo9g$Rh{dy37&?oMpnBb9 zosr&Ws8VAQrDO(GyZl09r@dP}F~wzT1T&XW5vd;T%FIPPFGv47E)4W^6@fn>uXs2l z9)g4x4Dwz^dBU*#+!UTEBD+Z_YSh=?D|aLIYqX?n2R7=8Q^D%v0|Gw_d5R4@58f&; zO@`E?W8^eLt|96zX5IC?+W5uGV9XR;hp$%18 zA9Fc zf;o4K4w+prsrgxIT@afMPr+L)G~gtJYA`L4Z3m5EDwO4)#Ps=%=;zsboyEe-_dd3@ zTqa8f{`5EbkXu*VNTEFa@Ol6{T`&r$QQyrbTPL*HA(moaV!5}-WHy*!ExG)6!<=9y zQC41d2k-N*oC}dP`!|En`M&Mji;`kUkda%=xR_@FB*?k7k-2dxjwRX~Qxwhz8yS+J zzsFlC>)*?^UM`UGsOq1s@$v`Q-Wd)FL5&fMhdR^)HG1lZutO3X7i-7(IQ*4^Al{e+ z3t4?f=BGf`+tka9CDW)ar$meBj+UW_F#LgLg^Ge0WE}B*vV{N)=LsGaR5arheRifp zi;cgRh26q%$wo5cD|}wlJ2NJ^`9#~Sy$wn9aDo2OU>`9pM)|cmG4;poC*oPcrlVB} zbE&#a_7}CAJ2`I>Pvk2V-aqfuKjXhEv$PXLM;8!Kpe1II05JH9^V*v4Rq3ISEzLOA ztSgN_-aiz2b8zx_J|^@1Dc=j(+uKFxdEfXJjw+nphVZxg0kBv#!~i`Fzi{w_rQ9+W zf*2E@w~G=rzG|>@uaCQrcr$97#vZ>m33i&$c*qhFo)tVB6e0nG#Zta|P}X7pGzc%Y zY)Y6be*5-^W)H=Dju&Sive}C739M1;q-C}Im^4dMoTnJ^H__C3AxbZ{f}067XW5R0 zHm9nDi#vYc-#bf2>m~ZmK3l%4&IMlS9C%1q57aJ%TxXl$w%h&XRU+>f(K09j6gE}_dD{sEed z!Jy~R1!j(R6Y=@b5p@kLko2BM9y=6nPiPkZ+1uv+p5}K>6c9@J-MOhhv+%_PAu)6u z5^(Etn2mc(BRfWY1KCPBc5TK|-}zS7mpkm_Da;t(zKz3(`7u3uzNi7+adQuvcH zoK;<40%AW&7o>fMl&R6s!Etr;mzTR2iqNxyc~j`-h=9=(Z({v4(tVDi=86)-fRI4H zi2`6F7qDLlWVQzk+F zv---{OFon?C^>m-y4)Y(yK?L|^!k@U)%vArQq{uo^%&32dwEYXx_Jmzc1i0m;l2#h z%+a4O8_-Tecw2tebMFXEHRpvHE0Yd~(>@*dNg#fJ75n;QgkVYE%|MmF!_jvg1h%bz zVXB~D%O=$>gV26pFgd;9(VO`6)xm5((wH|u*a6n|%L*oA)GwFgCi?)tYtXc}&D55Z2jVTQt~i)3(sdA>UwhjdM} zMWYV60E>rcLhnLUl7Q&(YE**ELTb}K2W~i#pQJ;sfa%L`OdpV_+=?WAk|Cw-Ds zs3I!#;yXjQGCoq@O%4tg)ZMqa-iVE^XTToi|K0!l*z};ESDFeCdtLQeV?;cOmFW7( zgT@(FL}yl`>g-mEEo`Ky-hO28V+uDKFvJOmUVA?I{_3s$%e8g3Du)w)cgMD1&>G-8 zNNV`Dk?M|6F@5Y$jp9JzB!r4R#F-W;*<>0^tfo?O#9vVcaH#!bGtoAqTi(U%U$pud zmyF)PrVsDk@amz(cGwt|_=Pts9i;q^XuWN+R3NqPnB*kH+*Zrj_W~b)me8pvS?S|X zkFLIh$Xv{V4+V*#uQG1ojp z7^v^_*$2ODDkCsg!Bd}(zEoowEh$UqFU{Ff)@Sbw8-`=Z0Bvyko^;holHb+smvO90 zS9#x~Mu`17^dz_0Il_%1g_TN)_TjP@)R_5gK{Cuv^3mAiZi7hvfCXz8<942m)!$zm zxmgZOu3Hh_tf{zd;maAOFoPrLSCl`I)staTZ#}&xqWG6q6&%_x?XgdsndBAWPIl{6|aZHUg9t)aCQ!(69dw3_H&E diff --git a/qglengine/icons/document-save-all.png b/qglengine/icons/document-save-all.png deleted file mode 100644 index 73405f7b1085a7c9c351718a1f07ba7e7302b789..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26721 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 diff --git a/qglengine/icons/document-save.png b/qglengine/icons/document-save.png deleted file mode 100644 index aee3e22af7b53836812f8d83e0edeff787e2fdef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22676 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

#LTh$(1r~g>qHU4oRx!1ACkLe zWy&&xX3vRN*ccE=W+!;prt zq>veB4nkE*mK07d2`woME2?tjxuU1P9Y}seG)tBpx2Ht2oY8pAh0<)yMG@GJVac6C;It)ZRLMk`uh9tS+Q#69ekUX{G-wgDBoAuF2Qn( zK)dtX=A3VE;^s)2^g0<$Ug%AgIyq!A7BrhopFX{jgP_pd+-z}^%4%zC%QZAKWcaxp zKUUBG_~~4hTOJvZEWiOqmIzLWI;9X^7t4`SQ`|R(Lvcz%6mcHXcEUistW(m$ad8gA zLUg=m$GMkv;)wt8v@=d38B*Gb{i3~ujqVxI64}C%9O4vl5inwnP!E|Um=h{W*nc_CRexa|gZv>8EUY%*eELboE%wlK` z+p=Yg#eXdxHa|ExSm5Uh5QdkWA`Uz^#dj-zJ7L5M8P75}hiM9hXSNc9f>pYsR% zw6v#xqtX#bj^}3uP)k77HMo`hHao}b$RABp_40flq@!dOSMKbL88aH;!<{f;LZ-E~ zH8XMI#5xXvIu3(+{s%C~2?B6&+N)6^8NvWQBKV*fqxzk36*B8+55&VT_zU1D1r-2r zLE*$jW%tA*N}DAb?+Js)EQbz^2J#O16^YT#LU7FK8E84-+>e7Or-h2`q*EjcjY*@3 z4~@)_WXbWUf;&|tyiU=+GQXgO-t_Qyk5U5~Do+S#IrAp4c%IX3FEdZ`0bxztDJjZNh&Pb)btk|AsLO}rk zqoum4E{^ww$|h|K3jv-3bCj7Xykn)5SpYmv!MU!d)R#U!rFG!cap|F=GZGM#dB}l< z3jiqHhlhtPey#`>0tY~z17LW=h7BVdH*Or})^L;SOA0#8zwz`UhoGB zj3qfJHg)ddKK&h)!9Y~}rUs+kgH_gm{Dt?XwGt_&n;ZIu&t@72}=Ju zuIyQ^^mW_{0Ohae`|y`V=L?5|Fa|gf>i9S3n&<9KI|>iba1_r~XjU@c-8`2JgN$pY zQ^j_w5bkqyN`ArwJ8YpK)&z5_0#1H05W{K)>~rNPU^b}f?`~inhFAzZAJp6z$`2*5 zlRq&1b9f#;DCe3vXVO%UDG#@RFu*ttIPjX56W0AOizROml_%K)QElzJp3IQnn z;XG6k@;uB42f)a>b?b%z0ALMp2o(8qfWIIMAgmrlt^71y3QcMW;2&+?8&T}*9Dk7w z2i83_<=lX*90C*u^f$-K>;5tTg7WLRIY&VN0Gavo=eI&t0L*@<|8wPU1O?_LaJIX< zTUY^L0f;HX9Sgv&4cJOXnwC)ET?J*NN>EoP+8Z;ZBZ`}U_y}pK&WQ5z4?0Wy3J420 zUO>es(D76U+!v7XxDjnLgxA?s&xqtzSOXYNV-cWb;!$W!&uJ9^r7Tb@f>sZhS7|(E ze#uy1sNi|HXZYjFJHnMb?^Fj|0Km3W4S*_w001aHw*ZFMtXTsvC_vQ!Ai>kf5DP%{ z-Nr4Jv@L@G6&V#9Edy#HP)O8tLJ(P0WTn%D$<_c>^g6PQe>&w44FLFsPAuHi&%Wg? zZ|MXJ0GxeJ-M@~1^z~o`K*J&TjCXBe#j}PudGONNbz=mD>fN})l_5(UVvH&>wGj^qFbXrnT_WQ+WS(*kOkzs1^VWI27PdSO)MdlZitz=tDqdz)~OL zu~G@^xwuoeb`_cEJ~+k13NFOCXJN-1{NQC}2NN7ka=vZXX^3M`QNQ=pXR∓pp;T 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٦sES)bG z3pFu!;36pj<_?4-ZUD=?BqVU3-%ux8{{Hq(shv9bP){G5y;q)YOHH3CzsutO21PpC z*ub83)!&TIPIilu?CVDnfX)Sow(jyic6p2p!u)v_@RQFEa_AWWFxgL1RaE_bScnJ| z$?u~_C}5VDTJmJfF*5? zLPi3l1gePy77+;)UWo+$#^BfPe{4#RNA{E5^xA2dg2muXcN^lu7K1n~871=ZMU&HL z5Cf(FS^coVZ%(vl{KwEh??-nN_$y0uzZ&OENLg5s_U(~zZ(mE7>)^(v^FC}g8;#wA z6M?*pc#A&B7fS-nSN!TPUWtG zDVGnYo^MCl%4}qoBw>d6*X@~@@SwYA1X-EMNKK8$`Q`yW|KP?IrMN?}$}`Zf0F*7@ zFh~RtB)L3JYNoCtU;hbi?VGzt@tbE)l6$jRM-H;ozt}c}hn_i(?-Ds^z}FEBuXJ=~ zqrGb|bm+AM=T@(-e_B~`huKnz11v-&aIEo`&;*MK%nMgbHZ3&2BEHsgMXm26J00H5%|gS2mBH%g_prEX(Kz;nSEGc5%rwm^6RP| zaHc1_c|cDg00Rsf;JM`I{=OX83oF)sHt@^ui5&Q9(2vdY8729Ba+DudLwGi;Z#O22 z0nenQxB4pZPn-nGa+;*!s&w8+4Gq=Oz<>Yut&^ho0R6s90!sho6PPF@VAhd91(Co4 zMG06{5+K6lF5aTLzbW{6S9<)8JB$t0B>7{4e3*bSE+u01y`t5m%KdPVO`9i}?QzMU z8yW2X$nJxu8_LQGzExb9K8kSYt88%B=$QY}ilU^?W~anu9X#K2gnX&o^8A#7NET@( z3AFT#;{FHs@HO?+?cJN}aO1U+NjkePyD-o;jzwEp&OQ~1Ipt_Q`Xu6$Goxhxkb7F3 z^aR){*hag>jLcN0_Ws$II=PBieAE2d7q3^&XPTsYN9PbyQ{p)Ru9>j�o?yj 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 diff --git a/qglengine/icons/edit-copy.png b/qglengine/icons/edit-copy.png deleted file mode 100644 index a8178caadb5061e9a75b9ed798ce89490c1d1b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14072 zcmZ8|c{r5e+xGK}kr~PwikQh-%94Z%GeXGPLLp0w5LvQsGb0Hpl*(?V4JG?pmKh;r z-}g+&8Z-96EZ_8dzxREQ@B4?x;h4Fe`&!QHJg@t{V=c`M4{(cd0|0Qq*hv2h0D$aA z5PW5#2&rBBt9{3}YwkuX?l90@9* zBKZg<0(t>=TECNUJ;Pat-EaTkZB8$)Cr5$p>UVz8MkGBv__UyhPVSBTxOZwz>f|kB z*GXHGO4~)x@^6meHvTIe>Gme~tgNl>O=?MulwZF$*g-ijZ{aD?9w(~&;Dm&~Jc<3V z87mJcJB;4Y0)tk2e@wwiamnf;7Jx%dS#c1AI`#3nEFT!uOPwk)9n1vM^|{(5u283% z&ZNG&Fcznf=;P>e@Y_42V1ztWS^ejSA_Gm~sMup=+VET;nKUW!*x{(3;hZ+DcK9T4 zmZT&3_|(y7r!63t$g}v-);N0u6?0gNm(yhpvns()5Y(5Nz$nhqMP3FCUN7;jOcUJ1Dd18gNnF`oRL+~421o=-lL z53t|f7L-5+t9>^5&*vb0!eRA`FX|q`}GNK%IefdUa$zH3h8P#URWk7 zj!MRNhC*7Z%%K2D`QB0RWPH4fsk!+t+d#RRAmf+u@$rQva^T;)N5Q|(;!-e6Lo14LjTylTvcEIyuWkD!_Tj5Gbx~G zI5Iwd#%NkuM*ey$yyxxg=axU+mSNldU2jFx{X0cEHpG)#@98eBtjxYW6PyL~HXZ|? zagq_5elfC* zVmZb}=4}w`m5UnQEKH|4v~2Rhr;QLuw_t-6js$V#N9$1KImQWtg@UV@DD`DoT^^|r-1vHQF$Rwl!fk`cOyE#&t*~ww&Aof~Nra>R*!3x) zV^mM^CLvtbAumoGr_=WtjmtxoKM(|(>0e*5E;$`XYUahM6UKLE*tUhHp(wb;i zUS{ye+>fU|MVnawAy)*!`N&DRe7rbK_I_v*K^bb?#(>spYi9v!AD|GUhmhGkiul0p zz7B?hEnr%{>aI8VFfoT+h}y@afT;{z@Zz2gLD66-*+#Kt@7Yx8B}&Uq=l9iD$D~5o z9*FgUXkzHJSJ!7gQ?7s5d;nlBcPIbZspKS|>z#(9O`Zt?i>wAkD8X@31N0EK%!7>D z7!syJ%YMz_f*{>Vf^d=+Ew6v~oKpceE&E7Br$3`Z@a;zu+fT190ADl0g;VI+9gGVy zFXR=SwH(P4qlH&%3SnYr!Ho@=4V4}2A8;})R%lgOL4f|zl_3`4$TOc4fd!6jK?(Br z;K**~qB&{)a~>0z2(?;&Nq@Vhoh&W!b<#Zo2ZU&`Bh?B`?4>ueUXMXeEj&QS;NPA?PL-)Qqx#!n#rD30sK(s!gj(C2e2 z(fIh?OUI#3r)l;aY#)rxuUdp8!4Gcv1-3z{D(<$x4Z*(>gEtSiY<{eli&D&wj8UmS zD5`zN9FP~xz|ozpfNH{^G6yZVoi4RZw+doD$Wym8PB@Cg-uW#>xWU8k&andf?l5>$ zynC}r*NyWo|40hI>%w|}&0$%8_3($9izPnw_}guL~rB@ zfZQ~YSAXpHe9g;G9-k7oa_DbueN{%MXm_odm*jCJBuD2H=)=()u`l>`v;#X(OI5K6l|EcZ%-U;MMin9clO8HC~Iq|$?sWBZv3 zW*95dYXiaHm9BIp37?{GxGSBCz^!l+4!|_0AtP+|cfcT)pQY`Tk}gX&-s^nuW#s3J zk#@HXAm{{Iz`J^p�>MAUWL+x;WeO@P#PMzBc4c`l&nn(ot9)yPBX=b`>6n?Mm*# zQ9pvm^HfXA@&!LI^1hVkOsi-2^t5V$&z{K`UJH0lAZbSd_WZQq@>*jTGGn;6({#tS+8GngmIKJDgCF5AoF?JgJcl5;oRIqQxm znsXF2w;qI4{Si@@20|PlxqHZ&XHWrVfEKWP6cGfAB*ZGjeq2Zql#{Gzo55+3hpUUTSgBInw3KJCG8M$%#yaawi zh^K9dm&nPSyPsP=;0UjLA^aJ4E1}Tt!V5tB4KVvUN+}cg;-s1G?wT zqB$Xu`AgEk+r!-k@`S5UCr+A4@9qyAUbH3~O;H)1mU#obv&I>??(3JqeIv#_yXgWW z@KTfSt&Lf-Va@dW`9-B+=U63hL(>&Zxk>wQ5K<&SA9Q6vNXn4i&rgF!oYLCoU zV)GBU6VwV<0~EZKMQYI6AQ)Xd?$ea}`R*kBRA9C%un+F44L*yPGrXc-Dw;27w0*62 z3(p3Fvf9|GB|%uP%xl0^#j?oiC}39?6XQ_*57(r9I&ilxB}o^KA&?Vyw5bPhm~ViC zhy=vDSe~#jkYFNbDAOIZT`Vmm~-U`@;k?v8e0XoD#G?}~N z_^C@kMHq^WyN4k~aQesljFNUn#%P^{uJTh6@K6>XdQ;J07O7E74?Ye}gfml?DjpFZ z=Cj{W>5+rEuk~KtXBk1D1Lnuv@#vXqN)^F9cRc9W5&}8Yaev?btCiLrOM!LYw~e!G$mLA(dx!*@=A&n$(J%0_Ka?0_6mfgl0aoj`&hGLawb z&cLaObvw%wCZL2KK2n-OgtvvWt)mdlO5{p1a5T;oK=8109131zmlQ-8p(>ZG0KH6{2PeBRdwrvRy_V9Js0m3t4>^1k=$o`DMm#QsIyFu^ zLg`O88Q*OuIf&NBO@Xw@;`!@C{`+r#zq$t}ouQupys15(^Hdf5aFX}_(sjhP#mFM+^kc)iuHQ5)yZ4s`_g%~o0^~_vsjZYNy7?yA{G^|+ z6}7>fNTF_aU_rY7c@Fl1ta47dQ4>vpsAR68J=o{iE{UkqP$xlpFzJ^W1JfgvwQ_`m#(j-aUPq6B29zuodFN3 zQ*sW|w5fTmp>p6!o2fFPqBc%Q?!ZDa$dt;$q}Q`urnD~JD1aN@UnL_2Tn`5Zh0yut zL_>>o(S$^fChz9CK8$)D89df$gL$ zIsH;z=ewf@aMBj#L}93tGB|UJp-poSE?im=fM0kG%;vOnIh9uF0@+K9cpUZ|$K(^W z-0Z8Sc}74#H@Sq5bQW^Vs=>mSI%K0_4~fd~Jhhx>ouAgbe;$se{d38JAgMK}RasfL zVa{ham^vopayXdEMs^T7iZ!j2wgmH#UfYvejimiLSO4sJ#1%fJ2SJK(z|Vqh3k~XC zIjj9ohY-30YWaD=(dRYpa9H-!z!83n%-cL*3#H%fr>PJdB0em5fi(NmJ7eI+LyVaq zdScQ-j&})8{&2|<`8!P@aZcvRxq3>3qeI;~Kkme&N!CU`98zS}Ff_o~A1I(?aScYU zS?}~6<#JMFdnq3fNntKSG0EIMsW0_`ej)FX66enI;Icf9+YEc1G}%e&O8=o1f7${N z5x^~NV)!uCeFBF3S-_$k?n4&tjUA`KO8%6#GqLX@&A)dJPLN|$frkxZb-W2gce5uI zP3}^)S%3!;;86=37@c&cRzqXHY=lB`BY^uoOp#QkQkhu4#C5A3wxcw_AgbMJ!MW*N zTP?8P2$1KLcXDWUl-Ohja1c$R>WqG|qm2eC+_C8-N`#ksLN<)BNO{xG^<4sz3z>P7 z!mNlSN}%zt9PJ@R47*leNpl3myMJSwTxoF)?ljw;+Gz!jBXMG8SU%?3uZ5>F0>D0w z2%yN{-VoRN1Z(pE+^N?KTV@GqkgHfAq2Nk_l1_C1U^e>CJqy0QzvisQq4buSs|Rl&D;vy&Rabi}}_#zYh#r z_EMzfDOCl>);D_Hd<=LL?{B0G1wbv6xA5^~jnz6el`$uH{ zMLvHE)Hhch{|zVXgSZ+lQxs^wt&oqjou8Ama~DsR{th&8dq?Zd3ty<^!Fh+hIjlo@K_P@* zh5VIwo0%s<)9jAhGuG!9L<6pg=%6P~C?c&5@!}sLN*Z`*xAr4h}o{6p4R=oyd)41?B1lL9lG_g_` zJ$_vZw<2i{Id=D$TOiwl92oO{=_bDmn|#dS-A9QhsX3t5iI}cd%F{8qk7wfO&Z>_QQG=_Mh(>IC$}YMZB-YXkdrKgHuS@E zWCohr9B%nzjZ5*ma}+$J!pce7D*V1N1Y$3fbF2I|9ZhCs6!IjG>d zSHDSFz~eyYrlyC2XyIAn3AB>kUOIqv5Ipvd;hzUgy}?;DAN&@wd&9-cOHGmx$(Wc7 z>lMNYL!DxGDD_=pxMW?gN6_91AGb?wg&v$SqYh!wM$n0HMh5gdudam0a?TLd3YXLN zfpBWFNfn~$ufS~jMb}{7l%%$ihK_>YE>f-*LwdJL*Ua|bRamqsuPiL!TfdjDp4 znb)0nmmZ%C zOb7DwaD|^lHfH-vu*cRH8;^^QqUX8Qk1!pyP$d zc}(7(UK36clxXYFKN28-Cbds<&T&vj9rFQUPOJzuP7v@vD$*yLmDFd_e0%5)l_nv_Sxy=v;uph(z38<$lyx%q4{kN2oX<;VL- zp+|O5r-&WOqb=nt6lDlg?TV4q6D_kyV?`KHm12!M52wLY#wIrl0#|3X!cGH-Im3$= zhkra5A4$N{uQdD>t>=?RM&L6Z7aV|GI;N2Y{0#b0QFRTC80yct1d(cK+VvL%8^Lo6 zI=Ym_aVP z!M7tpv1TubD+00Sx}s-@Okot{bL8F#I4K7hc3{(uq!Shj@3R*#V&{6J`0IhOlWiB& z7MdzTddk>N`0xn~zzN%av++;iH=2LdP1g|lkpF2%z#(kapdyf>^J^ek4K=_J;36qk zY$wApnQ}T;7pPD&^|V6Qr;0rJh^tLv{N*Q8hXB!KA=kbZ0~uhHi`qT2FXu=FAcNyA zJu-BRp-R<*xaCVG&LV_JtWo#E(n|HZ0RZ)dOA2T-c)-XedA&O@>1XpW0myb^5HBs` zttjj=K1?r@jUJ5^k{5ehJbs=hdg#j7*><Lm&~YG-qgD4P&Y(3aye6 zJoS8itmR5pBWCkwVYVi{i0^{R+Z`(qpM1#lSulIFKxHc6F9$0nY*}!Gzg#dElO!A3 z?+zE=(E>b9SbwqXv=HO(ueV6UNn)7f?PRr=4%A->fOeqDf3)YM8W{9)($)!=yM=b+IIH?SW2kl0`5~x`80yv> zh`l))ml$DeoG!zjR@W!EuBEEBW3848?{B%BU1@>fM))8kq!>RydUX+yBPkDV>rwH~ zv=|_*`J$LV^Y@*Gzpn|MsB@~L^Api%vY|hklP;(0_4J_MPvRJqyu`ZHm3tqX`3?J$ zBN3v;uFqL^LC<#|UHMAfnN7dim-3oxwaRKqT5W0XwmfoisOtj<#JUt`=` z@3vU!8d9=Nj`)`e(f^r`f

  • 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 Hdh~w)Jq`wb diff --git a/qglengine/icons/edit-delete.png b/qglengine/icons/edit-delete.png deleted file mode 100644 index 38f11cd5f521da653ebd61cf861f6581d9531a0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22776 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 Of$REadNn%e$o~NX&zs2r diff --git a/qglengine/icons/edit-find.png b/qglengine/icons/edit-find.png deleted file mode 100644 index 140e58102a8c8325000261e28ec5122467132104..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43469 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 diff --git a/qglengine/icons/edit-rename.png b/qglengine/icons/edit-rename.png deleted file mode 100644 index 4b47837baa0108c5e764dbd4fe91e1e610fcbe19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4859 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 diff --git a/qglengine/icons/expand.png b/qglengine/icons/expand.png deleted file mode 100644 index 6a963b61b699cf104ab82038abecb820d64d3a26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14692 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 AIRF3v diff --git a/qglengine/icons/go-jump.png b/qglengine/icons/go-jump.png deleted file mode 100644 index 7437eff297aa1c839b925e550834c62da0a5fd9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7200 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 diff --git a/qglengine/icons/go-top.png b/qglengine/icons/go-top.png deleted file mode 100644 index 489674e3379516967efab01f8f70d1b88c310517..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31581 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 z 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 c=q1H>%XXYC2ZLL0Q{+&TL1t6 diff --git a/qglengine/icons/group.png b/qglengine/icons/group.png deleted file mode 100644 index 510863717246e781e945bdbeea62aa909fe111af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12826 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 UHS}5)et8B^kWrPck~9nXU*m;Ov;Y7A diff --git a/qglengine/icons/layer-visible-off.png b/qglengine/icons/layer-visible-off.png deleted file mode 100644 index b1f04a9dc0f93d75609741ef3866e72c9835a6d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53079 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�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 y81O@hb{ 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 S#c{9z0000B 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 diff --git a/qglengine/icons/object-flip-horizontal.png b/qglengine/icons/object-flip-horizontal.png deleted file mode 100644 index 2c0579e0b0080b3d3b5f6874d4f1a78fd71fbb17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25165 zcma%iby$;c*!HtAVDxB2fdNv|NJ@=HX;ezOLsC*|2uLcZASt1wbVA9s?btoE*%%D+0~a?uH|4DgVE}0GZUsIU2wsWp)V=?(4+wuyEo3@&R2!F@&Pp z8iq)*!(!++bhx*+0xuq@O$H^Xg;X0?SsF*SAksXrR0cDfG2$_v%dr@_SJ+rJb_5~4lbkRQ)QtxUf8x1daTn|zz2;Z6b!Sgh-g z;p1R684!kJkd6LEli*i&VI=b?^sfy0_A4d8Al6~$RBrz1l{AYe_`xyP7j|$L;<2|~LX$COZ`TH9y!^e z!)AdlIFc8v3?0d8^yN3&*>#oQ8ZWH-r30M$`?!;nTFzXI@UNpwGX( ze!CrvPI3dIcj4fgo0Be`3-zm|K``DinxTxkK)xm4v!vC|&-})Zh(KQMNVRvCk6#}R z)UxXkss7*Jfrmb|7BDDpYqar0ULK_KZ+*!GUXF_cX{d?)kE}vonQHm7<2E|FYFAh- zS-f2^-mbHl@(SU_yK`gZOyZiFYX9Yq&@UeV*em(1gEMGNC+f5w9E%Dbd@Z>lt#S)W zi2s+!=E$dK26Td*D~l%bTYbGG2D*T3ysNkSF!FO`n{r*@>NUY_i?}np6i58#+YDtl zdr3!m@$y>^Lz(s=V=Br(hZhcbAd{Cd7$Z5oNB6&nL`lH3_O6iB^dC9Ht0u>Lz73ANoEQWI8*`4JfH)6s8xU)X)FR7TVKd}G*EN&SfbNwz3+N3ZK^nAvSV?1RnY~&vCML@u0d}Yn zp=n9Z#~BCLBB&@Ofckslt%Oe-XYNjfsK$TK|w?QZb0H3 zi@=>RX`9K~%#YkZLfcv5*}9{po;B9p>+CEE2NOvsRWol>7K zDHktnk))9T2Vj0()s^+JJW!i5FZ7xiVQzjW23Y9-`H1%x1XZ%Q+yzPg5gdA6!i`LGe3%7bPm%5N1uo!O%aMC94Pl&MQWgt> zt%CWNPx8UF=n8Qp5KsNMXsFaitSk4Za+dLLFk!*#Dx(Tg=ilW91||bMNHzx@fR8Yl z$0|MxSX!sIViTIF!70WWf9dhvUh;#&7CUWK%j#MV2ax1MAUe(>ovaT;?0dah6JMup z@_aTPsr6+^;n=*SXVg*IcXo$&c0!vaco=Q&BJ0KP-qE`{zRPd<5O5OOh~Fs-Xw4z4 znWs1`XPyZe#2!NCO4 zCr_6RsFYA-d&l0HYU)Bmv!)b7Np(eXrNKr`fs~)2`u_dF7xg#eou75nNmfkOs1~?U zG{PXdStu;M%|mY~j!g316eSXBf46T_+)Sj&&bI}ThOc>eyJ8OKFH9#oBEsX{XSA^!P*i4^&uS+_Ui`YaEAyKMg4(i)a-5NOpLR4 z!8s=b?kx)&I4(|m8cCxEXtY5P?`-iAB9e5XLFjf6ym=YyR5?*avMT$-^tr{&UjpHs zFsvB93;P}=wVWMB8}&T^`S?e{Xs64B`a+1LI|l^L#>X!K-rUOa)X`(hF1%L1wptTb z`&P0x`m)ZS8iD!tp?p<73ScnA2Xa`EMHq9^_(6>jF+c(;t{Wy^pJSc0AacOBAyFir z9Wr(g7@mwU2f*sxE`SpK{5w)?%pgqzeb`;R8y;YE&JqMz@<0%Rcxfzt{?xErzLrQ! zBLdZj?Waq2bKbOZQRD4^K5!3z1?M->9-5iDd^M^dpR0Gt&zvsO$u)$cF6KUe0w{w? zkcNI)=FG^?jL281&!`wNZHIRnSpH<#%?K%LtpBU}b}c+UYCewN2PWhcPBid7(zva{ zOoCvl%=qbW0t{ip{)_+yxvsGLkr?*~yj>gC&bMijO4|WzPA4-_Gwa_bOkNx6HTPc2 zTs}3Kh^JmDX9z!X&64808RDYAUnA4wVqG0yX>I#ToV`(|&xRqQ@2$JUhVcnWUTp&4 zEYU_19!5qak>KRGa{E5872Z;1eR!-zY1T$;S`F`9CEj8AQY-M8{y$5!JR{o_>@Pp1 z6+QfLjiQj698X#P@g}#Wi0DFDhFcSM$3O=#q5?JLS%YZLV1QqXNYEPR*7LPQitx+f z;Jj^f{4HyK`#^h;=nuZeMd7>XxXU%Q+clY1-H&M5*r-^;F*X8Ca|~c38YGQ>>&~~c zGn;Rkin0_!VCj4809Bi^+jq5Ucten!dlCGnjMvW=#Zz6&ewxx656l*C(`4Y|dZ84W z=>Ke|OM72^K-*;xYN=$0d9*jY-ISB^z^Fz8Lk4<4x!K}fYYJi_`!+}5n-&H7UXG^>DFO7Y=@-}!@!7$c*%2_FcYq0Gmk_07h0v_PW z+p_-8pXk0-f}(ut-{%so(3>%W3M3Ppsz|wGcsbB>@m4RY9O>a^ZCeE@yL}Bo0OQ*t z`hlMh@F{?rTPJhLjIQ^>^jOtoATRgo-yu1#6)OmquFZu6w(o^fg94LE5@k$^J9{Mr)%T^Nm*S|vK9)sq9St=SU%4CsEH^c0G^ zwFvPl7$-4$s{I@|wU7i*evoAK*?nEl~B zPu%0fp6@srVTz2sND~|ZAv^LFSP~@tX>)#JBF5^C@2xQe6cy4l4>^)Lqo&A<1(3L8 zYp%AgWn9pYn$?)@g;}I3lyzCWa{ut1P^5DV-YDYb)nsqrDX*|ju`Ub3$Hx#AXBs)yr0EVJ;&pAkgvJaRzv=LnU$2NvnDb7e^^9|k!#W>@Grvw*t ze@O@(FvlTmW>4w)sY8^3m+U-1c>1s{zG;(Mf8c?6|Fc+p^AE8U=!q9C;NSo^rUhsL zt(lCIB=b2c^Y(w%t8Z_%N^})-_#mVa6AR9duLy3n3>K&0=To?d&G$bxf%g;BUYB6) zYxLUTkmTG^ZXjwXpr|;ht^68nlMO3ym}}hp%CO~a)YeFnS3x$WICaV2Y`yk(*=KPB zF$xJ^A(QM_^7wji!nYv;MevM|kFNo-?2iqeS{JgDg}krqw5|@j(YOb(=Bt5NQ$s|8 zks$(r&X{Q?5{|H0+LRB%WjF2pDX0e(Zzz-#Zs$tX&~?LsPw65y<66+Jhi&2)%geCI z(ie~Qr%fB*Is+bu#&c^3uGawX>jw!BffrX&r-wuZNcw=aHVU2PBVs>?yH!R=_#@o* zzw^Uwp)ZE`z3|P`O8Zwd?;)!#fRk`JR@IN|)=LxmWKN0bvR-USiiaZ4Tgr`mr}29& zw9|o~ne*ajy|d}{pw|94M~nv|l@etB`+Js~|HgY60uvW61}A=_ia?xf=%F7#AjSmA zBfuXd*4~CeTgyx$iUV-KqF?aX^m|&QV!4t2XAgyKX$ zNc6pu;v42gT14gZ@@E(Mq@Wp5P=SUZ=!qns1kg-jExALe?|t)>fbV9R(gJblKAYPo zOI;j{?IzjpoUkw|g#Bl4+A^z&xl#66&Dww}o1XmCK*O9TZ?%6#7Qj>%nFfHX*_?V? zGl84TIt>D!2>T8~-D2KE^Q*_-7WoVf88$iyqzH0;|6gOsX-ln6!UVLDWoDK~3v2!J zS#kSmUs_pqFgTFbQ?h&W+C|vWlhgvOeJpE}6L#ijT$kw#L^H>7YWIl~H zOdApJ&oz+j_>qAAY}S&X?0qKtbdWR%0Bh*tF9ljFu(_w8WS$P;4Z%zpTpM?OI=ZdE zH}FW6yXKOoDnO1}bEyzt@0=kq~Zp zUbGa}j^R`wXFC6-IRIiB6#ae1L2*le^hA;XZr&hsvs%+KSWedk2PibPw6y%CA!6G+ z?^25l3*+-17r$li^nb{MjJE{m^_L|8)kLU|p#`jeryHO;gPmxe@ac$C?P4~FQb!>m zF(=;eB@7p52#y5At@mcmKtx6DSBV7$(1bg--#_6w6 z<9|y$NzQyQotYgHO@386^youM3Z%t9^n1fXK#2h}6zR|x-~xm$>Hrn@2?#80smd9; zFq;PiRPUr$8Z-7Am zMZxVJQRj<%vb7W8b03OOSiX~D=;<#uP7BL-_)&s9k@?@87}O^CqeE_#;_1+bmdz_F zNEA?87y3_DS>ck6oqtZx!8P!jHiE-*=)ebaHdTglIMjh?D`w0%qj*hq*9R zJ;!aN6ooaL>vL{R8&Q>sfbi_v@TPrz&}hOK-*Z!&=mu}fE!%Un0PYWUtA7SQjH(w@KS4lO z6bV6^tK&cc1VtM-@`&9PLhVL9bUR!+1-F0jp;iJyM;h0?CoX}rHzQu$g{P?Es|;%U z*SeJ&)Z6XVe`63HpeU9Y%+vo1MR52Uk#QrJhV6F1RiQ7v1YP$0TZ1OY_f79P3F0~j zlG<5+Df8oDEx3}InVGU>jveEYPEj#3PdWM|&ux0`S$?bOX_U`Up7jkd^|~ zdtHF@tm#7^GC%qp#q`19xH#AcCx^+6{Ge62XzPN0dev>vJmV^j&y^5P^~BxiDU7&f zrlh;ss}?^`p^w)!CIXumOV9TEfBxJo5R-VhTXA;3*HqW+7ngf`Au7Wwk)F*?qKi+S zUL8SFViEZg6CE)x$}3xp634c)nC`Wi^ErhmZ2XdWC(yWt$DCMK=9aUw+?FE}3Lfz5 z*xG`(m)gtRmO8ySg@lB-MMXu!&i4q7A8~=;jYJ}aQdxlcz$6Aqa76wn@%}UJs!Oix z8JVp9hyHvD!d1VDWGqf4oXlU@z>vh)hm6goe-WM z<))_@kQK>CnOa03{g7iQNc*2SsLh%*B)PH+!VUUr=bz+Q(HEO?l|(DPpMTUj z>L^s)koFQQ1DBM_fUkj{6v(XS9*ghPM^J>pnr-WxH0zcaf z9S-Bc@7FI^W7ebyN2BO?>PN2$+Zl6#AOm)cR$wP+dml0157(p}7pR+N17?`!k z&#hP2mDitEFPwxb^JP7`K)i0xKZCRnX0sI-kZaU*_h>ZZB}`)kW*i6ktNANA+=?*` z4rWZ7feB(ML0~4y=VzZxunNU}EeTuS<~_W1F6k+uOseSN6cWM(h={Q=fUV+p21D1Q z;8DQIo;U?c&?X94+M9j#fLXueZS{$^V8rttGo7MktjuBH;h_9w+bK0H_sYl2Y4Maj z1;PXo*_%=eJY^CbnZFBH2~&}o?qoFC)YvHM|OM1(jPwWq;{tJ)p# zJWpl@-9%d+im#RzEKw=2|FCBfadInqZ0~dre6(mh@j$-n;!+FzQyfIjrclYPtSd%7 z+4Jbd&A)~&&ZK&>%Z7(+iVWDh5fjBF>VOCIVl?}5^WmZtjXyZ{u^YHYa~=l@y5121 zzkJ8!_U-xQhRJH5BFnuM2QK*83Ztj|aTS(dP3k}EEDv6CRH|8R76zRR=(6YTT5(_| zPtsoYHj|)!3=GpvL6V;_^@)R9B#@hxvrnGPUqmEA{;0itlInPr;9_2TIq1p7 zx{g)*zaCh-18kqS4l>q>E8DQMg=Oq2zD?cCbo=_MIOiot!F2E6j#A}l(gFQ-y6<(4 z!<``;r1STm(*3%5v8l~(16ip9Y5)E8N*9Q2;U|MCgS^W8YKJ82;IZ zCD#pn+_CuV)8kN$Uq{4uyWa+V9CJMGyEn5WaiI7F{#SuIj2$rkK3lhC)f{q3YTN#G zn+Iva2pXF_H_--YgTEz@7OT^G(8X4}J=_t}T4Rbz?tbum^&$haH#TpjbBKApE?s1#iIeA{m2ao*fY&ajmgmQO&)g~V)T=2z;S9~BKanxr}f8o`gQ{OOAj%sPS5z&)6FIMH_*nc2S_c;eJ8K-fg zwtny%nA89`U%LzWYR2DxcFxwio!xmEa0O={m0*7*-j@ z09d-*`jVJR+QIPDDr*YGrhj~yrdMy$cqrp;)vVV1KKXsV^_Hij{AJmaPaJp3EwH8z zivqFoWc0WlMNX?y4pn}#@E#HM!D}R>xwsj_48T+U#0Ry%Qy1lC(AkT>Vow( zC4K?pba-gyT%-OCTm3aq+s$9x)8nxe#(NPyPet!{@hgRLJBljg{>6aG%Rz24eRZhy zOkmqiw*W*FL-1fHXLoshBaJRLp~|T3V(IH1zW6^dIaZ=Y;IuGPI*d;z5_tUCfSVLT$kB0vj)=brJGw8mmf&k%5LIbwqfdLh>R-DKZPExP;-M2y!F{qo>%Xx z=`54IXc3@RMt~NP83PnZD14T{npSox8GuqSSIU*8Ot%})COYfF=U)62YJYEQCzT=i zrcw9s%<4Gp`L_OFlDu$S{!LBd+YP?WB)M_c$%N>3ciJk zh`a+9QIh~ki-M|i#?=6Mvz|PTt~Ig_$B5|zl0W$Az0nS)tb3Xq^z8m+cgnBNhfa#} z%`>FpApJRHDXti?@m|GY<-KbA2zPPj4Ajm}Q+Fb`sk|;O$c- zJjfZa>8Yw~&kHxeQV$V*Z15wPEAuX_J3%C1Juq3B>8%VaQsF`$Bvp&qszvV(gaBEAA!o z5|PBB3Jy0FhW!MS98(;@$eU{_EQ2Th2Dn$*u9T}#g+yc>_N?j6-LOld2Ui-X@G}*N z7KI&G0cci_X^@7G;JKG$MkKxmETFo{!&R~#Be_k%0b#opbC$!z^8-5MR>{SF}*oIA7{Z$TfcQLbo`MCx*vcG^v(2XRkCNl+!F*$k7TFl-c%R;#Q0;tXo^sIcZ}*{_>%;b;IW;Wp02G0>)=jm z1&a}tftvm>2yuA&sc+VMY0Z)+GynrO*vlP5B23|O(dd4SKwQ!!bgEs?S+id<{jQi# zxtO*Jj)x*<|Hg)aHP0JCfsbCpP-tT_lg0O3)5q-^pU)s_*(c&^=W5ms7paTkkNzQH z%2Pg~HLX-wr(E2sXER2LU|3P*iTOD~zY*)3TnWx;7Z2 zQ-3HZc1=G7kH_bzK{}+Nm1Rt~FQzJKFUvYG^Nse>8=t{2)|;@U$KiBVB*aOE8bIhZ zW%g^S#XuL!keb^iMipO+FtNS4i3bUjr!eqL`?Vek2yJ=m(prlZg#LQcWI`6QU&vtO zDFS+oR)M1*jm09>!9AiSKJU4{T^EcBac0_l-iC%9ueVjU$2TOaJS8dw$-gB3`n(3d zhVFhc71xQY8&xReQ(RluOAKoofcdb6Q+S11WJ$UUp>Hk})0u&e24V)mOxj*ZvTqbu zwYR7$fwK)g{hODHoO#OVQg!9dsBz_!`FAWqQ(+EbE|`B$X=#kY8-%axSPqnw$xo<3 zVhtE??Bgp9Cx-iv=s{=uSr3>M#}Ss9LKZn=a?^^Xmjs`F+>Q$D$fQ!lG_5o)`=^8(03xJk}tK{gs608iPh%zkzBcSKf0S{>hOGGP5rR zxqlS;6b{e6C}orb!$0dnR~pjH7$iV#YgMLb`o-7p;fiAvp*|cd?|{p)$MT{sKUyq| z1NP)~ZeM`+DbI zc{ZKu<%7UQBz7cApBw%27&KlTA7|tivFO1peLYxKzZ)n_Nu7SN{@rPL{Fz5@oS_on z;^MNIn8>fVN|jH}K4HJPc^AS;%_%D@oAf+Q*oyGGHeizli-G|| z+V+wlC@7JO8L9f0`X~TUMp&TVVfxr$J}uZh0qsX%!*%#&YoWT~NeS1y5S#SQt-Gq7 z=0yX1;tSuJ+}B;9bOJrHtFAk=6No6 zSt-S)x5#I#cUpDkAlzrdY;A3`Gtf}tx5@P+)q9+!N3{4>;F<<}6p+rx2SL2Z|8Mp- zrS47UA^Y(BCfaI#ud9~%lM2`sVl6>Zt@|&kz;dF|{6PSp#vgNZVzX^S(fl}@^~eT{ zg7+9QR%PX?1w={U6%5Ra#Sf+xZ%wn6{}MKt2dKkhR1Q48+4j16t%B!sqEhL#fft`Y z0=6)A;AJ!2EMOkJWtDZULtErbi8dU+ftcq_9vB|S=;xnk#l9+Mz2hlLQX|U!xLi%7 z*Nl+;x2>4z@T=<3<=N~w{%=lN9z9eXh{!O@nSIX1!y+bqQmFOVgEpH-Qnwmah;HuQ ztqu+9_qEJ7>EUGhv$e&@Ku3r6yC|gwut)PkrecR|i;R@AAfOYkBQjdETWkl!@{P`j z`lBrJsp+Vr1+s0yPnggJ|5|1tHi@Q4hWm7}*0k(AZxu~eEc(=ndG8jYgyI*M(0jK2 zmY`>#h?QIxvK%sxoJ)}}c z%lf8q1R$^_!w6~<-~sL$5SN$%$&!T0R(F0Kc=u9h+iOM5t43u(@1H#GP9!PsQlQCt z^;orJEJC$ag{~$~w(j)Kd3i|8eV*kVctiUxT~`HZ;OXFiAmHh_6gTSkh)t{cdSW!8 z#c%2+?0X^}YzVy~@1S(Mm_HVpczpQdwkPmOR`JJBWck|TJDeC;pLCx16`#QaD8jZa zrH98FY=U)-IT2;J!jQtoMxtmg|D|6!v;zlqnsIg+>XaC}KCn45x)pUm7bmhc|L#89 zA>*9d6C@$4r`j)xa;uIfOiv`)=pcx1R?nBI&RJzf8x%=7{vJ)dKM3Cq)38yE;{wXD zdOcZbK`ybQxQ6L*3xe2OMT46lvYGFN zhz`pBZr>aeqPTd-o5=ePk646+$dJG}7bFa01hfFZwcuJUTl1Ee3-DH~8}7g$V%rjK}d>^R@4?W)lf2EW&KWLK_6vxcCAh@ zmR1h1O6x$y`^-=e7Z3Tg|GS2&9_b3_-K;<=goS=X&#ic{#+QY=K9&{hr8y%Ojn#5bIingfG zr7&suOK`Lt{+t3(RKF%9b3B|1Rl%R*y2k}>K)(twS`Vl#23a;TmkJ}tZ^bHsa|BBB znt_R^<<@^>>yy|ehCg3N{Uh$*%9z|bdw#O7JL7dByC}3PIO>(xLk)ObcOnO~TbZ@y zzqz9<0v46ta1w;RlE4twElBO`^8D@mP5y`wBoaTU28@0?nnK?ZMA7%aK`wX5PKtm$ zH;DeyNWebH(y4PpC(oTjR%vfg2zq~+G)cXX9Xx#Ha79ca7~r67wqq%u51i?oJkNrm-}3^u-blt(rfnPVCx%xe<#Y{;44>G zEIsifI#59o}H^#RNUUVGzL#lTcuNRV`uj;8&;} z9?>CcS9p_EDYdYX+=5ZVNDo!Zpf{9|&e;RH!a}Yj? z91TA?Og3l|N?L9>i@rGf=u%?v8L#d}vgfW2FO~<2*-3d{b47-yz*)oJiDRgZtr~^>6YIw1ekbAzqSoRcX^H4qN593mXZxe|n($k0%uS z@+1Uz(~u6#@awN@5orOK!gn8^U`;)L3xTU02Y(ABOMxIF_0O~v-NN1-Y4y$V)q@-? z>oG2Djct4@^Y3&he!#*!+n%6PZRT-uL>-G8q4qdg-`kQlxaFlV?Bn(g=0_<^U{nL{ zQJYJ5JdgU#Qo9v*WqX*neKpnb)t66<2eYBEKlLz}e-G%JNsw*?+alrE@{%(#P6(_F z4)DcNSUWcw<@lVWq-_<)67kL#c8 zN@HKuMqAeD6YB|wL%gtZ&j@&BAS=Sv40Qt)AiC6yyK$3U8c#}Y;zKZ7B=1#3zveE{ z=?7lXM^8+Kxk&dWSr5Jq?-~u(^%^7sp~>+KGvoU1N{UX39SUhv$F8b(Y=2momJ^_J z#Yaf3YfjDIK~UL0^3paC=eZckk?lCA@ z9(!;LdPenr65XL%TZE)sr$8!PWmnEzr|3< z{HoPg`-57iXA_^4@T#+$?++WTnkd2rV2a^Oyowe0cpfYSS-yX-0kGQesEDd7EYEo| zi+r?Fe2*K8UVgTg*eK*i$(sc>%Z`p8u_IHQRSXv;6PU^Sx*Cp|mlZC0{g0~z{*@%p zxXR$6sHi`l{f?>Ds=?aAeYmc}>%a!xEcQAYeUjPdC;0K>~4gnY7J1NCV;eqDGvBVoIjvmn}9b!~C>;WeF#C zBPwLD#;vfkGp_2r4^|P&EQ7(2rN#EW!g?5EsI>$28$9D*XWnAZ=^nm$F9(mB=IP}c zBMnCcJ^G&$t+LJ^5|&;@)?D%DFF_DV0wy9`qiccR5M6hH(JZ(Q@|SSK`7Zp3ZKZqX zddrtUc{4(c5}%*IjA5SAE=1YQh+B96v@V;MIeRv}2&yWx2_m@{YX)YL_R=&C3BDiX zf@gI0eX#H3VMH$18f!TNXO>-NH>vO(B%UW_BCwAoI{K^SE|*WoUOWr%-a|6iskj1@ zV|2;T4l&EfqYp=&RG$dgp3heJvNx$tqM;*QsR9YE*wkbb-pLF^jK8_WTH)i*XyRI&7)<}`mVudr5q#gZYS3k z#}-NwN{=WTQYpLK`LczS8+}&RL7aA4ehwrTsGKw|FO3BASA=Pvj?66>+Nd@2rz z@zJ=r``nDgkp^jPIpeK^vJK{ZhOijod?B*Wpd%;(7NxN@oOP*DQgxejK{Ui6B;+l^ zqB)&TksVo6RsSxUe!r{<^S6eOm(bF`WRq)q)@JHziDKBwy3dLSwRyO+G^aMq8v6s& zyq9{RVuX%Jd020=g34!Gd*;>?&y#RL&NPi&cn&AS*DneXv*+S;^9Sf39)Uhm2pMOh5xZf~WxKP4hz_rfIYzHJ0{c9a5G zc7>9h@i~5s$mDf10oUK@PBOd{HBVq@PYIUx`^JL0o6QCH;{J50cd{iQ3>vGAbp>yC zh$#pum4f=+fvSIj$;*p<90a&MbTWz1S(2?JVF+F&t}?Y4(>WIegfu@kq@!b0FaLLr zJ#9}@q|(_THW&C6p%nSLT}8b~)RT#kw+55OZ>-Bq^l-kj>0WrL2yIuRUDU2w6flx4 zGuX^{H1mqEE`V_`k{BulLg1&3#Bnko6v6xHco={$pT#ib3zL$dOf}7@A8x_WNAvP4eTqrPhiv&m;g#Dpk3BPp<4ZV@c&GJx zxyC;Ir*AGb8s1{YXKxtd?m-&UO}`1w%QA8X2xLaWQGIy6A3l0=k$n{LWL7%cw;Bv? z%WE7WP@9CIj#j(*ZPYS{&UbgZFNE_mC8`J(TjV*(PD`*LMUCoqVAbfR9gmflytmek z7gZXJz7tb{id&FpX6FQ=X$6SbktFFrpd?@{5()C9fEa$mNk|X^R!0%x6~a0^?n340 zWzWje?u84z!(~`LdL?J0opM|70s)iwkMW3ohn^)q9mjKC_RYe=+8(MsM;cL`(rsiU zplpTE*SFa2fnyt?A9n|zeQk35^WDnPvE#lJ=X8dH)sr3OcGFf8;EsLsUMn#;!SwPw&)Y%d}1^1UTB1hDmOK0uw|1AyrUyH2_d!+vQ5BZIpHsXOiWSF~&ahhD)2&gg&WqQNtikZq`CmBR z`w&*0mbW+4t{8r!w}K)WuocGIZy~syKFA-QZw4WwAqGnS(K5Rc8#15LHs5Km5(O*; z1^*J=IY~(VuZ>_oJawX`+ab)OM)p`Uh=ZQ!i4{LdywCN%o9FNis90FGOIU*i#ST7v z-fn#4&-^wgz{@9oldr-B0;l&>257Ip8Q>atPc6tBuB)4Vnpa=>8AjQ)XP(xK5Qg`}^)Grm*N7WEsTMp!gA2&4is4 zC$v55CPmZ?Z~y%b%=kZmM)TkwiK@}^#KuJmSv2Lh6^aGzsY|7Ibq6$S=vxh_TknR+ zqIU}jVmrLAw!B)Tj{Ij=`S`vv;}HwIwrtx-RvGwk)i5nLN5wZ!4C>~22WloFP`hoF zlX_P#er2$7%gwN@8FSk!6VEfAmd`Sjt#>RQo(+#*R!5|0{t>b7Khj0pFdmJ|9U=I~ zn!LL|+i_s1PtYnRr&KdXjM}G>c)9V`EppI;eAh?)6;)$Fu(+`{GH;Z?8zB=kcUi`P z_R(XP_FCH6DfF?p6j^%P7qgqBtz)B*odt|3eQaxi=7k4$ykz^{5zf_A*_9KCY=fj8 zlWTAozPYJAq%*-PF1vjR<&eHi=`=n!XDaHu2w&3tk2thi(~&ol%UBOzL4~1Y8;K3B zBgHX<;8{2J_OPD)M(M#A7^?KK90fq60{mJ3t9NeY!b;})#JaKMt)l{dvCzBBUu=OZ_`y%Z+gm2(IALgD#gzI8>xwS+4=SDt6*+0UE z(xybA3v0q%h1$O#DGLz{MYk0!{Lo+^r%cF_DK?2GjwE{X9K?Qwx<-kMyNolr0fGr{ zCGe-MN~B+7r}QSF_lPH&8MM;6E9bdXZbdNM7}ioD7$%_HQ60oW=ImGYjbUo(F=e$w z6^s3hYN>kl8(7zIqoKVUbm6yWsB*b{($c5s1xX}dDT`d6xGd1gkBDKcwt^J&xcXCk zRQ>wqHq74J4ER|{%7a8|5$A_*YEIvW+juv zubt$dZ&RE8jB^Hf^iJBm{isoo+Jcl&o}EsECi*g_R!*d**K08Z{zr?7{>fG*c*<@y zW-2i2V@e$t=Qk1KB9Lb18dJh8?b~P(hcLzSA;tV0N^OQpY3r%;S_}HFw4$e!^xQL; zMa!ekecXvBb3SYE^5Km`a?*%Uk|r>X?Kzr`ODn?Tl6khh@s*(*n0I2BcXL+MM$e~t z7Ljsbl-kLkY?=FEzcQEQJ!e?^vXTZkn=23MVa=t@VNY3fnkUN@ETMhhPL4GR|-Qz@lMU3Meza~-pl zIP_=RP`Lf-DDI~0<<7yul>Xh`7AeA(0&>JF=s$42(*?C3JjKe~;c5XLpw~5~n%6YAK7}DzDmw#YfwQ zbVZamz2cOC$yhj1Q&_)_0_xuo$V_mDe5SYFM_s=KB z$Z?0{#s_!Z9_-Bb2BE(P!6&q2pQbe)_uqj=namQd$TUkID$={{VQ9V6(AP5?)3->v zbLm_qf%0r;Zs1k$a`n^?sxwaSww9WB61hc@*RFs7bM+>@ZysG(51e56_?TQ761|dA zwhIf2g)e6$uEt8a|e@=aeihoyx|-1-w|aoVWr;7Q^`G` z^*py|Mj?cYGhKhTo&TEkx8YqgY7m%7l*!7!V2#f~!=gow#G`q`F>N&ohVWkgviml6 zX;c(L&nTRH3Fu}^4>XUWpvaXRspo#j`?%Nu{$-yxB)%O|KmK`hM4Jg4pHl08y#e&2 ztj-iKa$o3H`-SJ1?~dJdl>IqRHS>}3Yp%xWk=+{t>yMF6WtWkTftVWeNJ2H+Max$| z1F1;vD1;IgwBMx8SyU}{wv1{vs7B7(=~y%WrzSXNUZWVpwDIQtmCxHE~XRsTZ3ATL?I!uS+MmQ;t z=DlTkebFbKRgyo0^GRx_gs3p$)%qf}xy_NYbY3yehxB7S=-PVprN+>;vZ$seHfY`6 zl(OuyBl7Uy5T%kg9UF-Jw&aNo=43g)H%RgA?}}$ln^ytGSa4$04Mj8cWFy1RYf32) z3}4#SxlR912WK4>Ro8{_nPFfC2Bf>C5eZ@F7)n3{LAo2HyK4rJ76f0B4k@LP?$QB4 zLQ;B=25F?@8^8PSUH6`I&)RFBbN7Cp-wnxfV~esG?3G8yEQc#_7N`CfN_L@a>tyn+woyf==EGEKyMuJ9VNC`Dt8Cdzhw^n=&(!!6{m0p(kmL{t@Mr+ z6dGVmK2)r+hQ}yv=;&Odu;xC~#xBb$%BY*CZ&qH!V`Uf-HvRE20Oq+2fRzn z{Gt_Z11|w^@@gQD4*(sL#oT=zH6t~P?yWQU`cOeF9@ly%7%@%$S3YT~=p9rSY(`fw z3r|nYm9vcHzgTK+2T5(otlP{OgBTdTg2(W{5~|$TZ0ho>+}GpV714pQ|AIEL&(7(q zW~Xr1PIjiKHfd0Y5;g$>IZ-|#S=H~Fe%|>#`lM}c2^A%1R>Qb6BjRlWZ{iXjUR=iF znEoI`&A4gt;EU(EgI$Q1A9w}wTW89$qs0NUDf$KHL&V%zp(I9qB6x49Ty~jA)P4RS zyeoAS5`XwDeCGW2>3tSI6^I5--c?`KE)sfm3eYRpPno{^Ru&zMzE&~A22duTKZ$X3 zp>51}f5B1Caa5arKVVUmzAK8gnel<-k|QqVJ8;HPlJUE?LY#4mdOBj_70#ZjLRn@I znV&1J<-t$zFXJiP%P`{ZifwoRE+R}^eao)RNdrhJ&@(iP-Ndu9%ytO|mzqM{H+vdx z+rTHeea`@FDoGVP9*A+3;cVC6X!>f%sLTu{Sh&Xl%DZp<`Sx#jC6K`Zy=uKH>1}Ta zMQ)|pW;8O@Qb8pb9D(0GwY7Zj#);OAR`hz2V4w>GH2^XrF7hX776F} z%ZZwYoE6^#2E@O+^C2G!wS7Q@8he`0tlYeji>wZp0flgE6Ej>56g1rW3J^2v{}b)5 ziHF36wTq0(-7_@bUCjwDoGWxQxR4e%$f4+fmeP?~fcZX8*XJPHxJF`+&%PS5D9nl! zAM!15IDkux>Ub)s*qe0Ga9}@>rH=AIZWj=q=MxdqCa@^efCyWr8uQzQBcjfdr%q+6U^}3-V|%;(F(k7uQ%y6pH!%-NABth0RhVp=jy9f>Ij(jS-U7g=fn>#<@wMG(c) zo8&Ra*&qnuT2rc9_Bo#4ix`^A{H$fdp_BN&g+4VxA zr{F{rV^%U1r51lda_aV=u8bYXWv~`FBA1F&?3drc0}x4~I34xB{|U2P1I>Lk>Kvtt zfAzPA=yUZ>V3QRqvc6tKU0+|;Q}Z*r)$>cczmt>2Cz>6T1$5UZsxS~7gn-IQIgHdZ z_k}X2gULJ{UB89Dsj6f_a*AcH_Y%~n0_|vo0Kijr!5}8VFDF8z*?tk^v?Ct{KM>1@ zrr&z$r00Pj#W@ks;7 z;tj$Cq~6N%WE2Zivzv8cZ|bx!k3U$2@TK~?mAj<{!defs zl?_o;PY^c&01*)hlIHBl?oMINWMUNkIyv&Bm{YKPNJg-qk9Mt^_fIO0s(K+s(9OV?9;<7`sWfhYZa4T2 zc*n5;&^BOoKxxa-f9pN&v<`hmr~xlG_(7E;-b@e`#ZRa9LNOqS-W}s$3idiaLYsB> z-d_vFIDdJ`Q^f;e=*YxxO!DuR9(Z|~p@9OJMgo;T@oZ0`i9(J}SOtR@Uvxrn?wAEN zv-|=SciQNdrB7xfda<*K8x3dEZ=ZERH{2ss>jCF=N=gsxs5{behToHE={^U1{F({h z?M`7+2~2+Z2aG_fVeD`A!@4cB8iJiO%ybeUPVE!A@6=BwoQS*SUK?W0SM0mDhi;gb z=y?@`yVAy{%lLgH$ZNr%m%89e1&h=2*9}B z;#;l_r1&R%JfsyEmN^#zFiJJf1n<4AQ+8t|DRFDiFHegiVD22YYU_NMDq*S8TAcqB z5CLc#P8V{`+J|ki10q^&gb!FmfxrlYb2E1!&ym)LBhBC!5!D;3js%-elt1iPSkBz- z?|%ZqUYaP*%QRRPyevLf7>1{FoerK%-QcY~P}(P-4*M%+c=mZmVGJkPMRl>_Z;RqH zK=WBRy}M-1Z#4s`(RL};I8o55~QlNZ9}pk~YHhza!?IL{UX0VkTyFguC#ipKyq4CJ5+B@G#=uq9m-Vic_rjW)cFP zuhc6zxb?n)d{PjYEg%QayCdI6yL>qz=n-C>iChR-D#br%o)yHfR*up?`6rt9aeaqR zruX0Wr1!jQ6S6dSr{bEfpz2L+CbTrnwKB~aqL7Vi?FwkAMyanSIa#}1&ws5Lj7xE) zQ+fo%a3b+P=u4TJ${ei}azcL$?*=8d%F`W8CdP68DF;U_tAz={y(fGNbB> z?RRAcU7Wff2 zN%rEWfQ$G=`{AJSUr7qOZUdp2K67VTEexybZpulXQn+=qb~~KNmz{kx^>~;CW(q)zGIy zb=W_~Xkun_d;lzCPb~Uw9 zFaRZ&wBL+>*s%}8X3r7A$6^NcVaUAOz?(mmW_CzZ9p4sc-LofPPkovvtBm(Flqrh* zoEwq%5@rwNlpQHHw}GVf880&U8(NeH416gf1_k#NEdG;3^qixaWrA_rrMKDOU#=;{ zaIVT_>qfrtf~v47xE@=IUN>|s)BQ|{#fd$FB^3GQmy}m`s3&2~%2v@Hahdk=7Da^K6J! zf+}Lr@KDWFz)Y3haFuc10)ahjpUHgwJGy$-NzOVFcoqLK+*!wdnF{3FXr^if&>Kc5 z&gW)6xZ12vWNyKz*LVvU1bSyG)n4{!L~0(B;c5Vy_wJwYAIG(eypTQ;Z@%7_itNxG zsM+L8G^>N@vlCmK(~*;~%r~>&*1#B`P4FX&Bq)RCG9)BaSxbxA8GJsa6v)Gx(>`7a zjLHJ=fhba~EuVWOl4OxN$M;c6pUT#KODw+w19erSSkQzm4ed;;j16f9MO=kE0zT!wl`2fwjt?I;*BzJ41i3hO$w^#SR8c-D}k#h9%dV(#fkqBn=%KbKQ9&WSD(z-m=vwWNfke^!X z-fU+((S4WU$Zy9s`Q4zsLSTcq~AkRG&@+?=xf%VHCe4V@|uQv59BydAv^02!f zr@Dp=tPH@K^Y)?=f`L-FAgr<5clhtT z6V8g> zoOtN_?})RSsmNWmUhKHk&NB^Qn#{Bt=q|GxHN{Q4T#n>rZw!*?(c7)1s?gf)(sv>l z6d#8xS4{WUCdnu&;)Xl!EVnaoA_ey#d#D z`;xZtXnR28IHm3$QKUw>3^nvK2=eDbWjm8;5G{DKsZ=z9=H=h)79pO7Tet_eL%Cui zXsNJvX<};=)<+O>jc2xI$rJ20W{O1bBr^o$ej)~R$U&+puUs{N-4sD~OekpQX|8Da zJ#m2Zo52u4l1@L{TO{SF!$h2RA-bwZpq1lMZpDF$(|u8q(o}nVIc?3Afv(jkEr|-D z$&|Efc!>!wfZ+*ZA)xr#^TsH^K#b;G!)se-e=*wZkKs#vpktWBWMh$$4P0@CIdGbW z?}8I3m@5{7mU6p%=udxd-KZlv;r>%1aWgH(yB_}j#m={D4Wq*OEL%M;Tir_(9CytD zyhc|6&sm#$eZdwKa%$|skszhIwMJU&84)OBjhjtMnx=DYm3-fVv zI?)f|#(2GsGLG6;rC;SU4kWv#CnO-9za#ZFUWmL_c#dbQo|rJupv+I1&hYN>XUgxL zn82g8NRPeXr0*evYkf!(U;-Cu*ECV}QIh}jyMe^cjKBeSWU}#Neh%<@$MzonE5Ew8 zU8jLV9IUEV5Tq~_!YhA=L$w7jf#H>7TKE~n@Tzu@g*EDmaaQ~=JTupTC>=nBN$|J+ zMjknU>A^u@U7UYynaQ{t;@^bldv!6Y;14EqEbWMfT#ne3*Dly7ch+ZW=N<92_t{TX zSJz56&p=q1on?%awmj9*EC1yVRe!VV{Zo1ic7w9x&1!^J(#8o<2m>pV%`>974s!t- z<`IdzxPLfe?`OSW-Gyv3$aYXtlO#Bt*(h(WM@}4pEq|REzr#;?8k6yUW7=dlVl(f6 zN~?3l1DS9@@~BciNzW@oXb+N3>0 zU)Ba0(x3w}%-xPm7ZnzBr7iwZH0D*Fju!*TjLk|{!9!if8P=IK9^MXiF| z**QNql&j5W(DeU!duw$)lYN|-QXGH$#sT;stGMKG*ec`W5uVmiwpgIZat{~2g= zIYN|;WO{Yy!XzL4($LLCK@gp4iii2*gK$lj1{q6&PLTsoEP=$t?-+tFf&1(1q7``m zDGf;U?@$yqe_j~i*yy*?lo0Ls5A zIGXQA4F{@J`{IZ!X`jIS2j$MB(3V&>0mNli+*3c~kBxBzaCHNW@Whkm99Nr?%r zKMx-FYS^;T+8x(HN{1eIlp9bI4*Xv)t`Ze^ji0_V;X9PvH<%b>g7k8 z&&-wD*uD2=YsaX0TLpp2v4Oom%D)Bn5|ZST0rE{hxX@3M5y)=Yb-dC)Qi@^lWqDfy zn1HAI=BCXtX${D4t8INRT|T|XkvjLpu9MQwh0|Xpoet@vh`z0#Hf<}Q9JKn$+Pj?Y z(DTJ|_>gtv%W@Xpo#dEoe2e?l=OZJKh|^Utf?s+td1?_CVz%h<D?jr93FcDSVL5Bdoa#F zT);ybVf!NI>19i8(*1 zN2K`tEdfBaw(Jb7ufT69%q*6{cQQR@?A)beVESBRDHa`atWT>;hJVtoT_i3JKmXZ# z-c;&sz2PDgi)NNpjs0r3k$cbV5<`hd9Sjw zf@Qz;RjzYng0#Np84X=eEifEw7jcBGnM2q<)TQ*VKx>buU*hdg>35=m!-t}|{=|2I zKif`_gWffnB!8{%TXnx3W0l{6rnY-})dd2Cs%IV30X-%YL8CEaiWjL^gZw7WO!Y|MtpOHvnrwb?R07l* z`Vxg>l&Wz?;NL$#v`l$W|DSMOlt!Bti_v!qY(#ohe>6~yef!SiKtJd~G1Vr1<-;3- zrOud9)5NCl;uq&{X+dyDke8xm$P$x@_5QL^%3bb92HK?N3v?M+&};3N6fQ7~Nw!j& zE)ECeV7-^#OF;A+_RcLyag6X1&a6^tpTmZK?w1Ap)`Cn;E0&1;5>TXexOHAESavkZ z8qo=LpScs}nO#pb_jlRg3z60>XVrQS;GQ|-!dsRxA<$fZKXkR?Rn(QA3NW=V)Wrvs z-zQt43@O%L_j+Eh@KRsuJ+D=;YLQwc7+j=0h^=&*(q$`~oXZ5iD+zox0>fnqxaho8ThimDyMHkwmGV& z&EfvgCZG*`z<)0#li_65YL{KfDC@7@9Yx7vHU1k{Xf(siPCZ)fhbIWfxYi&6Zw%iV z0IOf4dJGlwe9MWFIYOuRM$HMGH5&_^r4Ld?v8>`4Fz=L=;}?`Ev)p?d2C5x{J9nut z!=nM$kC##%9sKSjSTp8xqVX-^vQ1fKetm?S*MEhHP#r06jGFByQcL%EdDs!| zPOo>r2Re=Jf2*vXCG%jqUn%E2bb+GiK#ozLC&9m6rK-PfFh6)@C$V-$Qy4!o!eP`1-U-kQ~bL#rMSJlo%%v2$zgd!tw+e$)7JIo=d`|y zGw@knU@RfZHgrKJ;2iug9MQN~XXEnnX-z_85DFiop1r9EcvT;$wF(jjgKU@6vTIwI zJvP{EMdcH=x|#FvAHG9Q32-e@AIf@KP~^{c5R)$TGjlG*>_3hZZjm*{#0$5K;)oMR zop|KMOr$9Hl4vR(qpzWmbg&m=YRnLPvM#v~ObQ+F{_|{gk;?>(>mQ^rzAxVM4szFL zy)u`2vly8A#B)<1V4RJ+wF5V{rp1Yh>~ZUAtRu0)3#Ql~*ZMw8JfhlwE+(@)W07Fh zQ^~y#tkNyqrSTCoPAkOO&&@$HPnEWo{5fKBZH&b4!YK!$7*h6H4pcaf7A+MKfTj+6 zHkfQ~?+kX=VL~~ALlm(R`@5dDHv*#q4mxdeI4)T3>oh3{^hs<2mfrpwRcdWVEV$5)@d_WK!&i`ejBDC=YVD$k;cUMa;RJvQqp&0y?9(jB zHm+a1RzR5qj)`98sZYVFV{%6=8lxk;4vB{_;eQbQF%sKt||Gu>#84!k6m@_m>zdV7xj4dE>XBL-XTj#ROH^h=pjZ~0et?-CFPQIcT z5u!i%A#O;fQu`vlWS^A(IQ~8U^Zq5d+s(&#Id$UQ(s@oxd5wvmdDZsNY;Uii!7){8 z6(cN94i5z4MD`h4x=(J*RR83lK~^8Wh#{ZQNyL{)pv42yj3wf2H*y*p`oGFbeXa>$ z&{$zv5|O;qADlwE4;0JO~;CA{&dF2&Y zL?TY6#{qq#L+wJ<*IsA*AJutIP*cwUr@^6=FisrozX4kRtspJm5A_<$ z(pN&@-;a&#D`tDX^R%&r9^i%io4*^jfv*pPozd~FYFui7sDVB*f)aL$MF+D;EWMWo zO5m?ilTj0r+z+~=OYUPJ;tFLQBm7tYDypmMcDIEE!Rq28{Z9W{Qa#dK-5UZ1^q yCd;&aE!2$-KD^$DpjFq6Q1W+-DV@YPAvbd99!^fjV@D+b_EJ;URH{<2jQAgd1txa@ diff --git a/qglengine/icons/object-flip-vertical.png b/qglengine/icons/object-flip-vertical.png deleted file mode 100644 index 7a9ee825bbc766c7ee1fd58c5f2df47be4260058..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22264 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 Wd*!~GJg8_3+`DsMtxUx%F#be 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 diff --git a/qglengine/icons/transform-move.png b/qglengine/icons/transform-move.png deleted file mode 100644 index b20fc4482967538ec7b1cfacd6c9af1884fb78d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24712 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 diff --git a/qglengine/icons/transform-rotate.png b/qglengine/icons/transform-rotate.png deleted file mode 100644 index 50631586fc018fb27a37f45fb1c5cf94e9c2b234..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20621 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 YEi!afq-Av(#0&yw&)8rq&ApQT2Lyk6+5i9m diff --git a/qglengine/icons/transform-scale.png b/qglengine/icons/transform-scale.png deleted file mode 100644 index 9ff1d443b084bc2d22ea8687e94e0afbb02d9fce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8092 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 UNR*#30pO43MLo5=^929@0rbsTIRF3v diff --git a/qglengine/icons/type-camera.png b/qglengine/icons/type-camera.png deleted file mode 100644 index e7fcde0b3f98aa9add014848aad1b6a46f0c20d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33163 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 VBc=Sg2vDX$m-Vme6<%}*|3B}Wpxpof diff --git a/qglengine/icons/type-empty.png b/qglengine/icons/type-empty.png deleted file mode 100644 index 337f0dec34d2ebebd19f4a0047cd574584d706f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2071 zcmV+y2qkIJ-^$KNKzAHxM zdB*!Ldp}oP`GIFjUmpDMEw`OmH-JC<{;8=wd#?MtbD7PYJtLtki7_tgW47812DbW~ zX7A`X$S75cR>7s0UT%WP$rq0A*?-{XXb}RPwyYpWgvi8UVMq|mt9V* z!i7TRf7pypyTd!2m4beTkq$7nr(s zFW2mzTJ}Hh{fad2g9pGl$N2a-*X*7mrO5GP$A->d`4K6UQleZean224nX%*QodEpn z^;7)zH@_xU6|Gi_&=}lL$%hYpA9cz{Zn=#suDpsJJ9cv9uYVa_V+=~~M+0C6J_NEM zgUu3SV`BjP>DgznlyJ^bRjX$%RmGC==Vzbc6L($3*!VahctmtybcNta$wu*j5xgf2 z@jz+}2AG?jC8o6%ytij(dvq#GUkCLd19Lw*g+lNo%Z38zal8toH3EpbG%i$OC4fdw zO-@WQbLPxY88bWvydO%TE`ToBwMq`>94RGK74MfkU}lVuZz9IX!omVCz4%YEETbs$ z5j{`_YzY4*CntK(|DHQfUKDEr(Dw7a=kc*|M1-;|DNE1HnU@KrN1WoE!^}pD0keb; zVMP(CCrnICOmNf99|EA$USM%?u`Xz=EMWaLV{&qWs;cO8+DuGLa^R*9^5aK;$in?+zXti1ttua)j;iB-32fo>xxZPgh@t^;UiOESs6th%=H0vDz zQc9#0i7|5a>xJSoLKI5N79QdF=3E05)&lf;b&K<{d9_%I3{m0C?>1PneyX1%zaS$E@1}(b7;A z2rxZ!x|bI7EGOF9(rBLLy#hFM_RNLr#z<;3CQ=*@pnFzORSdge|1OI((_Xy9P$4>8 zFeVuVz#2SYeUj5<4j+6Iu(I;b!@4EbaM_YPNf>g0bw)l9tj@h|Fbg6|2!TA$*|zNx zf}if~rbs`6I)l~rCobN0Nl$jGDAv@ST0+>mve24?*peX#P6ek9=Nwt)m_2t6fZOl* z7)5KWQKT7}I-DxbY5nXn%o44l;MUvk0AO}@7MEo>SI?)a2wJD>WdB_d_ly=noI@3y zD58prB3gUk=+Ps5^w!(BVgHTXu)n^#`O5wGp?TIjG8$l^;yd4caM>DvJNg`%b0jm& zq)wrlkR;9eu~+#=01#_qRdFhaI#i`Gz6PM8Jo&`05D~7s{(3ID=pypGAj>l{m-WSf z^}vMSnR|PVBS)U&$tRw`Ifo=8H2@?DkyO)Enq)Gh5)ag=_k8v}_JB$AKTx_^v3t@ojQR-R8j+Srsd*QJ1SUYNLs%Qhq8Nx07e~}W zBHHY#_IAEYD|NN;+KUTWdKU$SS``S0)pDZQVKYTF5tASdz3Nn1VJIw6tlMa7}n5-8Vz5Rv*eqw5K)(`Yh78;V%0=ZliCSaV;@AsSH=%xYPk ziFR}H`T*ql7)6%jeFO+HtrOEJ(5 z&PGDV7^z}KY%)w0BdMz2W31}$tBS?NMfUC8VXwA3Pp`X>&Cf3!EK4tYrlu^<3#wRA zdXEnkA%teJxK!u>QR>X(99foA6a__5kma>_Q&(RprY@yYs^_U9z6ylk@jg(63g>dJ z*|po+osOKJKYwtfpP26a_?^45+&y&et+x)md3J`E@u0s+n)x$@c1u&d2-{|z>T)iHroGZ`w!j%jH{#X+-Cp)002ovPDHLkV1l&% B>KXt5 diff --git a/qglengine/icons/type-geo.png b/qglengine/icons/type-geo.png deleted file mode 100644 index d6b825ca09cf86103dc4d334e5fdd26b6e8162de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5538 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 diff --git a/qglengine/icons/type-light.png b/qglengine/icons/type-light.png deleted file mode 100644 index 53011730f14d49e03853ff037e4893d588770d8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2899 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 diff --git a/qglengine/icons/view-refresh.png b/qglengine/icons/view-refresh.png deleted file mode 100644 index 66f0cebe10de3813d2c7d752637bd45151e56756..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40505 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. -*/ - -#include "mouse_controller.h" -#include "glmesh.h" -#include "qglview.h" -#include -#include -#include - -using namespace QGLEngineShaders; - - -MouseController::MouseController(QGLView * view_): view(view_) { - app_scale = 1; - lastPos = QPoint(-1, -1); - cur_action = RendererService::haNoAction; - sel_button = Qt::LeftButton; - sel_mod = Qt::ControlModifier; - mouse_first = mouseSelect_ = mouseRotate_ = cameraOrbit_ = canSelect_ = true; - grabMouse_ = mouse_sec = selecting_ = customMouseMove_ = false; -} - - -MouseController::~MouseController() { -} - - -void MouseController::resize() { - mouse_first = true; - app_scale = appScale(); -} - - -void MouseController::mouseReleaseEvent(QMouseEvent * e) { - if (cur_action != RendererService::haNoAction) { - mouseMoveEvent(e); - return; - } - bool add_ts = e->modifiers().testFlag(sel_mod); - if (selecting_) { - selecting_ = false; - canSelect_ = true; - view->renderer_.mouse_rect = QRect(); - view->scene_->selectObjects(hov_objects.toList(), add_ts); - return; - } - if (canSelect_ && mouseSelect_) { - if ((lastPos - downPos).manhattanLength() < QApplication::startDragDistance()) { - if (e->button() == Qt::LeftButton) { - //qDebug() << hov_objects << hov_aims; - if (hov_objects.isEmpty() && hov_aims.isEmpty()) { - view->scene()->clearSelection(); - } else { - if (!hov_objects.isEmpty()) - view->scene_->selectObject(hov_objects[0], add_ts); - if (!hov_aims.isEmpty()) { - view->scene_->selectObject(hov_aims[0], add_ts); - hov_aims[0]->selected_aim = true; - } - } - } - if (e->button() == Qt::RightButton) { - if (view->renderer_.edit_mode && !view->scene()->selectedObjects().isEmpty()) - view->context_menu.popup(e->globalPos()); - } - } - } - canSelect_ = e->buttons() == 0; - emit view->glMouseReleaseEvent(e); -} - - -void MouseController::mousePressEvent(QMouseEvent * e) { - downPos = e->pos(); - if (cur_action != RendererService::haNoAction && e->buttons() == Qt::LeftButton) { - return; - } - if (selecting_) { - selecting_ = false; - view->renderer_.mouse_rect = QRect(); - return; - } - if (!QRect(QPoint(), view->size()).contains(e->pos())) return; - lastPos = e->pos(); - downPos = e->pos(); - emit view->glMousePressEvent(e); -} - - -void MouseController::mouseMoveEvent(QMouseEvent * e) { - QPoint cpos = e->pos(); - if (cur_action != RendererService::haNoAction && (e->buttons() == Qt::LeftButton)) { - RendererService & rs(view->renderer_.rend_service); - ObjectBaseList objects = view->scene_->selectedObjects(true); - QVector axis; - switch (cur_action) { - case RendererService::haMove: - if (cur_handle.testFlag(RendererService::hmMoveX)) axis << 0; - if (cur_handle.testFlag(RendererService::hmMoveY)) axis << 1; - if (cur_handle.testFlag(RendererService::hmMoveZ)) axis << 2; - break; - case RendererService::haRotate: - if (cur_handle.testFlag(RendererService::hmRotateX)) axis << 0; - if (cur_handle.testFlag(RendererService::hmRotateY)) axis << 1; - if (cur_handle.testFlag(RendererService::hmRotateZ)) axis << 2; - break; - case RendererService::haScale: - if (cur_handle.testFlag(RendererService::hmScaleX)) axis << 0; - if (cur_handle.testFlag(RendererService::hmScaleY)) axis << 1; - if (cur_handle.testFlag(RendererService::hmScaleZ)) axis << 2; - break; - default: break; - } - QVector scales; - foreach (int a, axis) { - QVector3D axe_vector; axe_vector[a] = 1.; - QMatrix4x4 axis_mat = view->camera()->fullViewMatrix() * rs.axis_mat; - QVector3D center_screen = axis_mat * rs.selection_center; - QVector3D axe_screen = ((axis_mat * (rs.selection_center + axe_vector)) - center_screen).normalized(); - QVector3D mouse_vector(cpos - lastPos); - mouse_vector[1] *= -1.; - if (cur_action == RendererService::haMove) { - double len_scl = 1. / QVector3D(axe_screen.x(), axe_screen.y(), 1.E-6).length(); - mouse_vector /= QVector3D(view->width(), view->height(), 1); - mouse_vector *= -center_screen.z() * len_scl; - axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); - QMatrix4x4 pmat; - foreach (ObjectBase * o, objects) { - pmat.setToIdentity(); - if (o->parent()) - pmat = o->parent()->worldTransform().inverted(); - QVector3D dv = pmat.mapVector(axe_vector); - if (o->selected_aim) { - AimedObject * ao = (AimedObject*)o; - ao->setAim(ao->aim() + dv); - } else - o->move(dv); - } - } - if (cur_action == RendererService::haRotate) { - axe_screen.setZ(0.); - axe_screen.normalize(); - QVector3D norm = QVector3D(axe_screen.y(), -axe_screen.x(), 0.); - axe_vector *= QVector3D::dotProduct(mouse_vector, norm) / 2. / app_scale; - foreach (ObjectBase * o, objects) - o->setRotation(o->rotation() + axe_vector); - } - if (cur_action == RendererService::haScale) { - mouse_vector /= QVector3D(view->width(), view->height(), 1); - mouse_vector *= 3. / app_scale; - axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector); - scales << axe_vector; - } - } - //if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) cs = Qt::SplitHCursor; - if (cur_action == RendererService::haScale) { - double sc = 0., max = 0.; - foreach (const QVector3D & s, scales) { - double v = QVector3D::dotProduct(s, QVector3D(1,1,1)); - sc += v; - max = qMax(max, qAbs(v)); - } - sc = max * (sc > 0. ? 1. : -1); - QVector3D axe_vector; - foreach (int a, axis) - axe_vector[a] = 1.; - foreach (ObjectBase * o, objects) - o->scale(QVector3D(1,1,1) + (axe_vector * sc)); - QCursor::setPos(view->mapToGlobal(downPos)); - } else - lastPos = e->pos(); - emit view->objectsPositionChanged(); - return; - } - if (selecting_) { - view->renderer_.mouse_rect = QRect(downPos, cpos).normalized(); - return; - } - if (e->buttons().testFlag(Qt::LeftButton)) { - if ((cpos - downPos).manhattanLength() >= QApplication::startDragDistance()) { - selecting_ = true; - canSelect_ = false; - } - return; - } - QRect g_rect(QPoint(), view->size()); - if (mouseRotate_) { - float dx = e->x() - lastPos.x(); - float dy = e->y() - lastPos.y(); - if (e->buttons().testFlag(Qt::MidButton)) { - if (cameraOrbit_) { - view->camera()->orbitZ (dx / 4.f); - view->camera()->orbitXY(dy / 4.f); - } else { - view->camera()->rotateZ(-dx / 4.f); - view->camera()->rotateX(-dy / 4.f); - } - emit view->cameraPosChanged(view->camera()->pos()); - } else if (e->buttons().testFlag(Qt::RightButton)) { - float ad = view->camera()->distance(); - view->camera()->moveLeft(dx / 1000.f * ad); - view->camera()->moveUp (dy / 1000.f * ad); - emit view->cameraPosChanged(view->camera()->pos()); - } - } - if (customMouseMove_) emit view->customMouseMoveEvent(e->pos(), lastPos, e->buttons()); - lastPos = e->pos(); - if (e->buttons() == 0) { - cur_handle = 0; - cur_action = RendererService::haNoAction; - Qt::CursorShape cs = Qt::CrossCursor; - if (view->renderer_.edit_mode) { - uint hid = view->renderer_.rend_selection.id_hover; - cur_handle = (RendererService::HandleMesh)hid; - if (hid >= RendererService::hmMoveX && hid <= RendererService::hmMaxMove ) { - cur_action = RendererService::haMove; - cs = Qt::SizeAllCursor; - } - if (hid >= RendererService::hmRotateX && hid <= RendererService::hmMaxRotate) { - cur_action = RendererService::haRotate; - cs = Qt::PointingHandCursor; - } - if (hid >= RendererService::hmScaleX && hid <= RendererService::hmMaxScale ) { - cur_action = RendererService::haScale; - cs = Qt::SplitHCursor; - } - } - if (cur_action == RendererService::haNoAction) - cur_handle = 0; - view->setCursor(cs); - view->renderer_.rend_service.current_handle = cur_handle; - } - if (grabMouse_) { - QCursor::setPos(view->mapToGlobal(QRect(QPoint(), view->size()).center())); - if (mouse_sec) { - mouse_sec = false; - return; - } - if (mouse_first) { - mouse_first = false; - mouse_sec = true; - return; - } - lastPos = g_rect.center(); - int dx = e->x() - lastPos.x(); - int dy = e->y() - lastPos.y(); - emit view->glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers())); - return; - } - emit view->glMouseMoveEvent(e); -} - - -void MouseController::wheelEvent(QWheelEvent * e) { - if (mouseRotate_) { - if (e->delta() > 0) view->camera()->flyCloser(0.1f); - if (e->delta() < 0) view->camera()->flyFarer(0.1f); - emit view->cameraPosChanged(view->camera()->pos()); - } - emit view->glWheelEvent(e); -} - - -void MouseController::leaveEvent(QEvent * ) { - lastPos = QPoint(-1, -1); - //qDebug() << lastPos; -} - - -void MouseController::mouseDoubleClickEvent(QMouseEvent * e) { - if (e->buttons().testFlag(Qt::MidButton)) - emit view->doubleClick(); -} diff --git a/qglengine/mouse_controller.h b/qglengine/mouse_controller.h deleted file mode 100644 index 2c93986..0000000 --- a/qglengine/mouse_controller.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - QGL MouseController - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef MOUSE_CONTROLLER_H -#define MOUSE_CONTROLLER_H - -#include "glprimitives.h" -#include "glcamera.h" -#include "renderer_service.h" -#include -#include - - -class MouseController: public QObject -{ - friend class QGLView; - friend class RendererSelection; - Q_OBJECT -public: - MouseController(QGLView * view_); - virtual ~MouseController(); - - bool isGrabMouseEnabled() const {return grabMouse_;} - bool isMouseRotateEnabled() const {return mouseRotate_;} - bool isMouseSelectionEnabled() const {return mouseSelect_;} - bool isCameraOrbit() const {return cameraOrbit_;} - - Qt::MouseButton selectionButton() const {return sel_button;} - Qt::KeyboardModifier selectionModifier() const {return sel_mod;} - - void setSelectionButton(Qt::MouseButton v) {sel_button = v;} - void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;} - -protected: - void resize(); - void mousePressEvent(QMouseEvent * e); - void mouseMoveEvent(QMouseEvent * e); - void mouseReleaseEvent(QMouseEvent * e); - void wheelEvent(QWheelEvent * e); - void leaveEvent(QEvent * ); - void mouseDoubleClickEvent(QMouseEvent * e); - -private: - QGLView * view; - QPoint lastPos, downPos; - QSet keys_; - QVector hov_objects, hov_aims; - Qt::MouseButton sel_button; - Qt::KeyboardModifier sel_mod; - RendererService::HandleAction cur_action; - QFlags cur_handle; - float app_scale; - bool grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_, canSelect_; - bool cameraOrbit_, selecting_, mouse_sec; - -private slots: - -public slots: - void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;} - void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;} - void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;} - void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;} - void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;} - -signals: - -}; - -#endif // QGLVIEW_H diff --git a/qglengine/openglwindow.cpp b/qglengine/openglwindow.cpp deleted file mode 100644 index 8b29356..0000000 --- a/qglengine/openglwindow.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - QGL OpenGLWindow - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "openglwindow.h" -#include -#include -#include -#include - - -OpenGLWindow::OpenGLWindow(QWindow *parent) - : QWindow(parent) - , m_context(nullptr) - , m_device(nullptr) -{ - setFlags(flags() | Qt::FramelessWindowHint); - setSurfaceType(QWindow::OpenGLSurface); - QSurfaceFormat format = QSurfaceFormat::defaultFormat(); -// qDebug() << format; -#ifdef QT_OPENGL_ES_2 - format.setRenderableType(QSurfaceFormat::OpenGLES); -#else - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { - format.setVersion(4, 0); - format.setProfile(QSurfaceFormat::CoreProfile); - } -#endif - format.setDepthBufferSize(24); - format.setSamples(8); -// format.setStencilBufferSize(8); - setFormat(format); - QSurfaceFormat::setDefaultFormat(format); -} - - -OpenGLWindow::~OpenGLWindow() { - delete m_device; -} - - -void OpenGLWindow::render(QPainter *painter) { -} - - -void OpenGLWindow::initialize() { -} - - -void OpenGLWindow::render() { -// if (!m_device) m_device = new QOpenGLPaintDevice; -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); -// m_device->setSize(size() * devicePixelRatio()); -// m_device->setDevicePixelRatio(devicePixelRatio()); -// QPainter painter(m_device); -// render(&painter); -} - - -void OpenGLWindow::renderLater() { - requestUpdate(); -} - - -bool OpenGLWindow::event(QEvent *event) { - switch (event->type()) { - case QEvent::UpdateRequest: - renderNow(); - return true; - default: - return QWindow::event(event); - } -} - - -void OpenGLWindow::exposeEvent(QExposeEvent *event) { - if (isExposed()) renderNow(); -} - - -void OpenGLWindow::renderNow() { - if (!isExposed()) - return; - bool needsInitialize = false; - if (!m_context) { - m_context = new QOpenGLContext(this); - m_context->setFormat(requestedFormat()); - m_context->create(); - needsInitialize = true; - } - m_context->makeCurrent(this); - if (needsInitialize) { - initializeOpenGLFunctions(); - initialize(); - } - render(); - m_context->swapBuffers(this); -} - diff --git a/qglengine/openglwindow.h b/qglengine/openglwindow.h deleted file mode 100644 index 2110b7c..0000000 --- a/qglengine/openglwindow.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - QGL OpenGLWindow - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include -#include - -class QPainter; -class QOpenGLContext; -class QOpenGLPaintDevice; - - -class OpenGLWindow: public QWindow, protected QOpenGLExtraFunctions -{ - Q_OBJECT -public: - explicit OpenGLWindow(QWindow *parent = nullptr); - ~OpenGLWindow(); - - virtual void render(QPainter *painter); - virtual void render(); - - virtual void initialize(); - - QOpenGLContext * context() {return m_context;} - -public slots: - void renderLater(); - void renderNow(); - -protected: - bool event(QEvent *event) override; - - void exposeEvent(QExposeEvent *event) override; - -private: - QOpenGLContext *m_context; - QOpenGLPaintDevice *m_device; -}; - diff --git a/qglengine/plugin/CMakeLists.txt b/qglengine/plugin/CMakeLists.txt deleted file mode 100644 index 22bcdc5..0000000 --- a/qglengine/plugin/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -if (DESIGNER_PLUGINS) - if (NOT Qt5) - message(WARNING "Building ${PROJECT_NAME} available only on Qt5!") - else() - project(qglengine_plugin) - include_directories("..") - add_definitions(-DQT_PLUGIN) - add_definitions(-DQT_NO_DEBUG) - add_definitions(-DQT_SHARED) - add_definitions(-DQDESIGNER_EXPORT_WIDGETS) - find_qt(Qt5 Core Designer Gui Widgets OpenGL) - qt_sources(SRC) - qt_wrap(${SRC} CPPS out_CPP QMS out_QM) - qt_add_library(${PROJECT_NAME} SHARED out_CPP) - qt_target_link_libraries(${PROJECT_NAME} qglengine) - qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION QtPlugins/designer) - endif() -endif() diff --git a/qglengine/plugin/qglviewplugin.cpp b/qglengine/plugin/qglviewplugin.cpp deleted file mode 100644 index 97db1e4..0000000 --- a/qglengine/plugin/qglviewplugin.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "../glwidget.h" -#include "qglviewplugin.h" -#include -#include "glprimitives.h" -#include "qglview.h" - - -QGLViewPlugin::QGLViewPlugin(QObject * parent): QObject(parent) { - m_initialized = false; -} - - -void QGLViewPlugin::initialize(QDesignerFormEditorInterface * /* core */) { - if (m_initialized) - return; - - // Add extension registrations, etc. here - - m_initialized = true; -} - - -bool QGLViewPlugin::isInitialized() const { - return m_initialized; -} - - -QWidget * QGLViewPlugin::createWidget(QWidget * parent) { - GLWidget * w = new GLWidget(parent); - if (m_initialized) { - auto axis = new GLObjectBase(); - GLObjectBase * obj; - float al = 1.; - obj = new GLPrimitiveLine(QVector3D(0, 0, -al), QVector3D(0, 0, al)); - obj->material().color_diffuse = Qt::darkBlue; obj->setAcceptLight(false); - obj->setSelectable(false); - axis->addChild(obj); - obj = new GLPrimitiveLine(QVector3D(-al, 0, 0), QVector3D(al, 0, 0)); - obj->material().color_diffuse = Qt::darkRed; obj->setAcceptLight(false); - obj->setSelectable(false); - axis->addChild(obj); - obj = new GLPrimitiveLine(QVector3D(0, -al, 0), QVector3D(0, al, 0)); - obj->material().color_diffuse = Qt::darkGreen; obj->setAcceptLight(false); - obj->setSelectable(false); - axis->addChild(obj); - w->view()->addObject(axis); - auto cam_light = new Light(); - cam_light->intensity = 0.5; - cam_light->setName("Camera_Light"); - w->view()->camera()->addChild(cam_light); - w->start(); - } - return w; -} - - -QString QGLViewPlugin::name() const { - return QLatin1String("GLWidget"); -} - - -QString QGLViewPlugin::group() const { - return QLatin1String("Display Widgets"); -} - - -QIcon QGLViewPlugin::icon() const { - return QIcon("://icons/qglview.png"); -} - - -QString QGLViewPlugin::toolTip() const { - return QLatin1String(""); -} - - -QString QGLViewPlugin::whatsThis() const { - return QLatin1String(""); -} - - -bool QGLViewPlugin::isContainer() const { - return false; -} - - -QString QGLViewPlugin::domXml() const { - return QLatin1String("\n\n"); -} - - -QString QGLViewPlugin::includeFile() const { - return QLatin1String("glwidget.h"); -} - diff --git a/qglengine/qglview.cpp b/qglengine/qglview.cpp deleted file mode 100644 index cbff22e..0000000 --- a/qglengine/qglview.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - QGLView - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "qglview.h" -#include "glmesh.h" -#include "gltexture_manager.h" -#include -#include -#include -#include -#include - -using namespace QGLEngineShaders; - - -QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) { - setIcon(QIcon(":/icons/qglview.png")); - deleting_ = false; - timer = 0; - need_init_ = is_first_draw = true; - backColor_ = Qt::darkGray; - hoverHaloColor_ = QColor(195, 140, 255); - selectionHaloColor_ = QColor(175, 255, 140); - ambientColor_ = QColor(10, 10, 10); - lineWidth_ = 1.; - max_anisotropic = 1; - max_texture_chanels = 8; - lightEnabled_ = true; - shaders_supported = false; - fps_cnt = 0; - fps_tm = fps_ = 0.; - fogColor_ = Qt::darkGray; - fogDensity_ = 0.; - fogDecay_ = 10.; - hoverHaloFill_ = selectionHaloFill_ = 0.15f; - //lmode = Simple; - setFeature(qglFXAA, false); - setFeature(qglAnisotropicLevel, 8); - setFeature(qglEyeAccomodationEnabled, false); - setFeature(qglEyeAccomodationTime, 16.); - setFeature(qglEyeAccomodationMaxSpeed, 0.2); - setFeature(qglBloomEnabled, false); - setFeature(qglBloomThreshold, 0.9); - setFeature(qglBloomFactor, 1.); - setFeature(qglBloomRadius, 8); - setFeature(qglMotionBlurEnabled, false); - setFeature(qglMotionBlurFactor, 1.); - setFeature(qglMotionBlurSteps, 8); - setFeature(qglShadowsEnabled, false); - setFeature(qglShadowsMapSize, 512); - setFeature(qglShadowsSoftEnabled, true); - setFeature(qglReflectionsEnabled, false); - setFeature(qglReflectionsBlur, true); - setFeature(qglSSAOEnabled, false); - setFeature(qglSSAORadius, 5); - setFeature(qglDepthOfFieldEnabled, false); - setFeature(qglDepthOfFieldAutoFocusEnabled, true); - setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1); - setFeature(qglDepthOfFieldFocus, 1.); - setFeature(qglDepthOfFieldDiaphragm, 8.); - hoverHalo_ = selectionHalo_ = true; - fogEnabled_ = is_init = shaders_bind = changed_ = false; - rmode = ObjectBase::Fill; -// sel_pen = QPen(Qt::black, 1, Qt::DashLine); -// sel_brush = QBrush(QColor(170, 100, 255, 120)); - scene_ = new Scene(); - connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); - connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed())); - connect(scene_, SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*))); - default_camera = new Camera(); - default_camera->setPos(QVector3D(2, 2, 2)); - default_camera->setAim(QVector3D()); - camera_ = default_camera; -// qDebug() << camera_->aim(); - default_camera->setName("Camera"); - emit cameraPosChanged(default_camera->pos()); - //camera().aim_ = camera().pos_; - ktm_.restart(); - - //Mesh * m = Primitive::torus(100, 40, 1., 0.4, 360); - Mesh * m = Primitive::cube(10, 10, 10); - m->flipNormals(); - //QMatrix4x4 mat; - //mat.rotate(90, 0,1,0); - //mat.translate(0, 0, 2); - //mat.rotate(180, 1,0,0); - //m->transformPoints(mat); - ObjectBase * o = new ObjectBase(m); - o->setColor(Qt::cyan); - scene()->addObject(o); - delete m; - -} - - -QGLView::~QGLView() { - deleting_ = true; - stop(); - scene_->clear(); - delete scene_; - delete default_camera; -} - - -void QGLView::stop() { - if (timer) killTimer(timer); -} - - -void QGLView::start(float freq) { - timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq)); -} - - -QList QGLView::selectedLights() const { - QList ret; - ObjectBaseList sol = scene_->selectedObjects(); - foreach (ObjectBase * o, sol) - if (o->type() == ObjectBase::glLight) - ret << (Light*)o; - return ret; -} - - -QList QGLView::selectedCameras() const { - QList ret; - ObjectBaseList sol = scene_->selectedObjects(); - foreach (ObjectBase * o, sol) - if (o->type() == ObjectBase::glCamera) - ret << (Camera*)o; - return ret; -} - - - -void QGLView::resizeEvent(QResizeEvent * e) { - renderLater(); - mouse.resize(); -} - - -void QGLView::timerEvent(QTimerEvent *) { - renderNow(); - //if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return; - Qt::KeyboardModifiers km = QApplication::keyboardModifiers(); - foreach (int i, keys_) - emit keyEvent((Qt::Key)i, km); -} - - -void QGLView::render() { - resizeGL(width(), height()); - emit glBeginPaint(); - renderer_.mouse_pos = mapFromGlobal(QCursor::pos()); - renderer_.renderScene(); - emit glEndPaint(); - fps_tm += time.elapsed(); - time.restart(); - fps_cnt++; - if (fps_tm < 1000.) return; - fps_ = fps_cnt / fps_tm * 1000.; - fps_tm = 0.; - fps_cnt = 0; -} - - -void QGLView::initialize() { - checkCaps(); - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glDisable(GL_MULTISAMPLE); - glDisable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glEnable(GL_TEXTURE_CUBE_MAP); - glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT); - glEnable(GL_CULL_FACE); - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - glCullFace(GL_BACK); - renderer_.reloadShaders(); - renderer_.init(width(), height()); - is_init = true; - need_init_ = false; - emit glInitializeDone(); -} - - -void QGLView::checkCaps() { - glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic); - shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms(); -} - - -void QGLView::__destroyed() { - renderer_.rend_mat.mat_thumbnails.clear(); - mouse.hov_objects.clear(); -} - - -void QGLView::__objectDeleted(ObjectBase * o) { - if (o == camera_) - setDefaultCamera(); -} - - -void QGLView::resizeGL(int width, int height) { - if (!is_init) return; - if (width <= 0 || height <= 0) return; - if (prev_size == QSize(width, height)) return; - prev_size = QSize(width, height); - aspect = float(width) / float(height); - renderer_.resize(width, height); - //qDebug() << "resize" << width << height; - iaspect = (aspect == 0.f) ? 0. : 1 / aspect; - glViewport(0, 0, width, height); - emit glResize(width, height); -} - - -void QGLView::keyPressEvent(QKeyEvent * e) { - emit glKeyPressEvent(e); - if (e->key() > 0) keys_.insert(e->key()); - if (e->key() == Qt::Key_F11) { - emit doubleClick(); - } -} - - -void QGLView::keyReleaseEvent(QKeyEvent * e) { - emit glKeyReleaseEvent(e); - keys_.remove(e->key()); -} - - -void QGLView::focusOutEvent(QFocusEvent *) { - keys_.clear(); -} - - -void QGLView::focusOn(const Box3D & bb) { - if (bb.isEmpty() || !camera()) return; - double size = qMax(qMax(bb.width, bb.length), bb.height); - camera()->setAim(bb.center()); - camera()->flyToDistance(size * 1.25); -} - - -QByteArray QGLView::saveCamera() { - ChunkStream cs; - const Camera * c = camera(); - cs.add(1, c->pos()).add(2, c->aim()).add(3, c->rotation()).add(4, c->FOV()); - return cs.data(); -} - - -void QGLView::restoreCamera(const QByteArray & ba) { - if (ba.isEmpty()) return; - Camera * c = camera(); - QVector3D pos(c->pos()), aim(c->aim()), ang(c->rotation()); - float fov(c->FOV()); - ChunkStream cs(ba); - cs.readAll(); - cs.get(1, pos).get(2, aim).get(3, ang).get(4, fov); - camera()->setPos(pos); - camera()->setAim(aim); - camera()->setAngles(ang); - camera()->setFOV(fov); -} - - -QByteArray QGLView::saveFeatures() { - QByteArray ba; - QDataStream ds(&ba, QIODevice::WriteOnly); - ds << features_; - return ba; -} - - -void QGLView::restoreFeatures(const QByteArray & ba) { - QHash f; - QDataStream ds(ba); - ds >> f; - features_ = f; -} diff --git a/qglengine/qglview.h b/qglengine/qglview.h deleted file mode 100644 index 8f4d40e..0000000 --- a/qglengine/qglview.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - QGLView - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef QGLVIEW_H -#define QGLVIEW_H - -#include "openglwindow.h" -#include "glframebuffer.h" -#include "glprimitives.h" -#include "glcamera.h" -#include "glrendererbase.h" -#include "glscene.h" -#include "renderer.h" -#include "mouse_controller.h" -#include -#include - - -class QGLView: public OpenGLWindow -{ - friend class MouseController; - friend class GLRendererBase; - friend class TextureManager; - friend class ObjectBase; - friend class Scene; - friend class RendererBase; - friend class Renderer; - friend class RendererMaterial; - friend class RendererService; - friend class RendererSelection; - friend class TonemappingProc; - Q_OBJECT - Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor) - Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth) - Q_PROPERTY (float FOV READ FOV WRITE setFOV) - Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart) - Q_PROPERTY (float gamma READ gamma WRITE setGamma) - Q_PROPERTY (bool autoExposure READ autoExposure WRITE setAutoExposure) - Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor) - Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor) - Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled) - Q_PROPERTY (float fogDensity READ fogDensity WRITE setFogDensity) - Q_PROPERTY (float fogDecay READ fogDecay WRITE setFogDecay) - Q_PROPERTY (int renderMode READ renderMode WRITE setRenderMode) - Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled) - Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled) - Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled) - Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit) - Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled) - Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor) - Q_PROPERTY (float hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha) - Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled) - Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor) - Q_PROPERTY (float selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha) - Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton) - Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier) - Q_PROPERTY (Scene::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - -public: - QGLView(); - virtual ~QGLView(); - - enum CameraLightMode { - clmOff, - clmAuto, - clmOn, - }; - - enum Feature { - qglFXAA, - qglAnisotropicLevel, - qglEyeAccomodationEnabled, - qglEyeAccomodationTime, - qglEyeAccomodationMaxSpeed, - qglBloomEnabled, - qglBloomThreshold, - qglBloomFactor, - qglBloomRadius, - qglMotionBlurEnabled, - qglMotionBlurFactor, - qglMotionBlurSteps, - qglShadowsEnabled, - qglShadowsMapSize, - qglShadowsSoftEnabled, - qglReflectionsEnabled, - qglReflectionsBlur, - qglSSAOEnabled, - qglSSAORadius, - qglDepthOfFieldEnabled, - qglDepthOfFieldAutoFocusEnabled, - qglDepthOfFieldAutoFocusSpeed, - qglDepthOfFieldFocus, - qglDepthOfFieldDiaphragm - }; - - Q_ENUM(CameraLightMode) - - void stop(); - void start(float freq = 60.); - - QColor backColor() const {return backColor_;} - float lineWidth() const {return lineWidth_;} - float FOV() const {return camera()->fov_;} - float depthStart() const {return camera()->depth_start;} - float currentFPS() const {return fps_;} - float gamma() const {return renderer_.gamma_;} - bool autoExposure() const {return renderer_.tone_proc.enabled;} - int maxAnisotropicLevel() const {return max_anisotropic;} - QString environmentMapFile() const {return renderer_.tex_env.fileHDR();} - - QColor ambientColor() const {return ambientColor_;} - QColor fogColor() const {return fogColor_;} - float fogDensity() const {return fogDensity_;} - float fogDecay() const {return fogDecay_;} - bool isFogEnabled() const {return fogEnabled_;} - bool isLightEnabled() const {return lightEnabled_;} - bool isGrabMouseEnabled() const {return mouse.isGrabMouseEnabled();} - bool isMouseRotateEnabled() const {return mouse.isMouseRotateEnabled();} - bool isMouseSelectionEnabled() const {return mouse.isMouseSelectionEnabled();} - bool isCameraOrbit() const {return mouse.isCameraOrbit();} - bool isHoverHaloEnabled() const {return hoverHalo_;} - QColor hoverHaloColor() const {return hoverHaloColor_;} - float hoverHaloFillAlpha() const {return hoverHaloFill_;} - bool isSelectionHaloEnabled() const {return selectionHalo_;} - QColor selectionHaloColor() const {return selectionHaloColor_;} - float selectionHaloFillAlpha() const {return selectionHaloFill_;} - - QVariant feature(Feature f) const {return features_.value(int(f));} - QVariant setFeature(Feature f, const QVariant & value) {QVariant ret = features_.value(int(f)); features_[int(f)] = value; return ret;} - bool isFeatureEnabled(Feature f) const {return features_[int(f)].toBool();} - - int renderMode() const {return (int)rmode;} - void setRenderMode(int mode) {rmode = (ObjectBase::RenderMode)mode;} - - bool isServiceMode() const {return renderer_.edit_mode;} - void setServiceMode(bool yes) {renderer_.edit_mode = yes;} - - - Scene::SelectionMode selectionMode() const {return scene_->selectionMode();} - Qt::MouseButton selectionButton() const {return mouse.selectionButton();} - Qt::KeyboardModifier selectionModifier() const {return mouse.selectionModifier();} - - void setSelectionMode(Scene::SelectionMode m) {scene_->setSelectionMode(m);} - void setSelectionButton(Qt::MouseButton v) {mouse.setSelectionButton(v);} - void setSelectionModifier(Qt::KeyboardModifier v) {mouse.setSelectionModifier(v);} - - void selectObject(ObjectBase * o, bool add_to_selection = false) {scene_->selectObject(o, add_to_selection);} - void clearSelection() {scene_->clearSelection();} - ObjectBaseList selectedObjects(bool top_only = false) const {return scene_->selectedObjects(top_only);} - QList selectedLights() const; - QList selectedCameras() const; - ObjectBase * selectedObject() const {return scene_->selectedObject();} - - TextureManager * textureManager() {return renderer_.textures_manager;} - void reloadTextures() {renderer_.markReloadTextures();} - - Scene * scene() {return scene_;} - void focusOn(const Box3D & bb); - void setCameraLightMode(CameraLightMode m) {renderer_.setCameraLightMode(m);} - CameraLightMode cameraLightMode() const {return (CameraLightMode)renderer_.cameraLightMode();} - - Camera * camera() {return camera_;} - const Camera * camera() const {return camera_;} - void setCamera(Camera * camera) {camera_ = camera;} - void setDefaultCamera() {camera_ = default_camera;} - QByteArray saveCamera(); - void restoreCamera(const QByteArray & ba); - QByteArray saveFeatures(); - void restoreFeatures(const QByteArray & ba); - - QImage materialThumbnail(Material * m) {return renderer_.materialThumbnail(m);} - void setCurrentAction(RendererService::HandleAction ha) {renderer_.rend_service.setCurrentAction(ha);} - void setContextActions(QList al) {context_menu.clear(); context_menu.addActions(al);} - - GLfloat aspect, iaspect; - Renderer renderer_; - -protected: - void render(); - void resizeEvent(QResizeEvent * e); - - void timerEvent(QTimerEvent * ); - void initialize(); - void resizeGL(int width, int height); - void mousePressEvent(QMouseEvent * e) {mouse.mousePressEvent(e);} - void mouseMoveEvent(QMouseEvent * e) {mouse.mouseMoveEvent(e);} - void mouseReleaseEvent(QMouseEvent * e) {mouse.mouseReleaseEvent(e);} - void wheelEvent(QWheelEvent * e) {mouse.wheelEvent(e);} - void mouseDoubleClickEvent(QMouseEvent * e) {mouse.mouseDoubleClickEvent(e);} - void leaveEvent(QEvent * ); - - void keyPressEvent(QKeyEvent * e); - void keyReleaseEvent(QKeyEvent * e); - void focusOutEvent(QFocusEvent *); - - void checkCaps(); - -private: - void processKeys(); - bool setupViewport(); - - Scene * scene_; - Camera * camera_, * default_camera; - MouseController mouse; - QMenu context_menu; - QSet keys_; - QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_; - QTime time, ktm_; - GLint max_anisotropic, max_texture_chanels; - ObjectBase::RenderMode rmode; - GLRendererBase::RenderingParameters start_rp; - QHash features_; - QSize prev_size; - float lineWidth_; - float fps_, fps_tm, fogDensity_, fogDecay_; - float hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor; - int timer, fps_cnt, sh_id_loc, deleting_; - bool is_first_draw, is_init, fogEnabled_, lightEnabled_; - bool shaders_supported, changed_, need_init_; - bool hoverHalo_, selectionHalo_, shaders_bind; - -private slots: - void __destroyed(); - void __objectDeleted(ObjectBase * o); - -public slots: - void setBackColor(const QColor & arg) {backColor_ = arg;} - void setLineWidth(const float & arg) {lineWidth_ = arg;} - void setFOV(const float & arg) {camera()->fov_ = arg;} - void setDepthStart(const float & arg) {camera()->depth_start = arg;} - void setGamma(const float & arg) {renderer_.gamma_ = arg;} - void setAutoExposure(bool arg) {renderer_.tone_proc.enabled = arg;} - void setAmbientColor(const QColor & arg) {ambientColor_ = arg;} - void setEnvironmentMapFile(QString file) {renderer_.tex_env.setFileHDR(file); renderer_.recreateMaterialThumbnails(true);} - void setFogColor(const QColor & arg) {fogColor_ = arg;} - void setFogDensity(const float & arg) {fogDensity_ = arg;} - void setFogDecay(const float & arg) {fogDecay_ = arg;} - void setFogEnabled(const bool & arg) {fogEnabled_ = arg;} - void setLightEnabled(const bool & arg) {lightEnabled_ = arg;} - void setGrabMouseEnabled(const bool & arg) {mouse.setGrabMouseEnabled(arg);} - void setMouseRotateEnabled(const bool & arg) {mouse.setMouseRotateEnabled(arg);} - void setMouseSelectionEnabled(const bool & arg) {mouse.setMouseSelectionEnabled(arg);} - void setCustomMouseMove(const bool & arg) {mouse.setCustomMouseMove(arg);} - void setCameraOrbit(const bool & arg) {mouse.setCameraOrbit(arg);} - void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;} - void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;} - void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;} - void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;} - void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;} - void setSelectionHaloFillAlpha(const float & arg) {selectionHaloFill_ = arg;} - - void reloadShaders() {renderer_.reloadShaders();} - -signals: - void glBeginPaint(); - void glEndPaint(); - void glKeyPressEvent(QKeyEvent * e); - void glKeyReleaseEvent(QKeyEvent * e); - void glMousePressEvent(QMouseEvent * e); - void glMouseMoveEvent(QMouseEvent * e); - void glMouseReleaseEvent(QMouseEvent * e); - void glWheelEvent(QWheelEvent * e); - void glResize(int, int); - void glInitializeDone(); - void cameraPosChanged(QVector3D pos); - void keyEvent(Qt::Key key, Qt::KeyboardModifiers mod); - void customMouseMoveEvent(QPoint curpos, QPoint lastpos, Qt::MouseButtons buttons); - - void hoverChanged(ObjectBase * cur, ObjectBase * prev); - void selectionChanged(); - void objectsPositionChanged(); - void materialsChanged(); - void materialThumbnailCreated(Material*); - void doubleClick(); - -}; - -#endif // QGLVIEW_H diff --git a/qglengine/qglview.qrc b/qglengine/qglview.qrc deleted file mode 100644 index e67f617..0000000 --- a/qglengine/qglview.qrc +++ /dev/null @@ -1,46 +0,0 @@ - - - coeffs_brdf.png - icons/add-type-camera.png - icons/add-type-geo.png - icons/add-type-light.png - icons/add-type-empty.png - icons/collapse.png - icons/expand.png - icons/edit-rename.png - icons/alpha.png - icons/application-exit.png - icons/configure.png - icons/dialog-close.png - icons/document-edit.png - icons/document-import.png - icons/document-new.png - icons/document-open.png - icons/document-save.png - icons/document-save-all.png - icons/edit-clear.png - icons/edit-clear-locationbar-rtl.png - icons/edit-copy.png - icons/edit-delete.png - icons/edit-find.png - icons/edit-paste.png - icons/go-jump.png - icons/go-top.png - icons/layer-visible-on.png - icons/layer-visible-off.png - icons/light-+.png - icons/list-add.png - icons/object-flip-horizontal.png - icons/object-flip-vertical.png - icons/picker.png - icons/qglview.png - icons/transform-move.png - icons/transform-rotate.png - icons/transform-scale.png - icons/type-camera.png - icons/type-geo.png - icons/type-light.png - icons/type-empty.png - icons/view-refresh.png - - diff --git a/qglengine/qglview_test/main.cpp b/qglengine/qglview_test/main.cpp deleted file mode 100644 index eb43d61..0000000 --- a/qglengine/qglview_test/main.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - QGLViewWindow - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include "qglview_window.h" - -int main(int argc, char ** argv) { - QApplication a(argc, argv); - a.setAttribute(Qt::AA_UseHighDpiPixmaps, true); - QGLViewWindow w; - w.show(); - QStringList al(a.arguments()); - al.pop_front(); - foreach (QString s, al) - w.loadFile(s); - return a.exec(); -} diff --git a/qglengine/qglview_test/qglview_window.cpp b/qglengine/qglview_test/qglview_window.cpp deleted file mode 100644 index a6ac505..0000000 --- a/qglengine/qglview_test/qglview_window.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* - QGLViewWindow - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "qglview_window.h" -#include "renderer.h" -#include "glwidget.h" -#include "gltexture_manager.h" -#include -#include -#include -#include "qad_types.h" - - -QGLViewWindow::QGLViewWindow(QWidget * parent): QMainWindow(parent), Ui::QGLViewWindow() { - setupUi(this); - session.setFile("session_qglview_test.conf"); - session.addEntry(this); - - extensions = "All(" + supportedFormats().join(" ") + " *.qgl)"; - extensions += ";;QGLEngine(*.qgl)"; - - //view->view()->camera()->setPos(QVector3D(2, 2, 2)); - //view->view()->camera()->setAim(QVector3D()); - //view->view()->camera()->flyToDistance(2.); -// view->setFrameShape(QFrame::NoFrame); - view->view()->setMouseRotateEnabled(true); - view->view()->setMouseSelectionEnabled(true); - view->view()->setSelectionHaloEnabled(true); - view->view()->setHoverHaloEnabled(true); - view->view()->setBackColor(Qt::lightGray); - view->view()->setDepthStart(0.1); - view->view()->setSelectionMode(Scene::smMultiSelection); - - - groupShadows->setChecked(view->view()->isFeatureEnabled(QGLView::qglShadowsEnabled)); - groupEyeAccomodation->setChecked(view->view()->isFeatureEnabled(QGLView::qglEyeAccomodationEnabled)); - groupBloom->setChecked(view->view()->isFeatureEnabled(QGLView::qglBloomEnabled)); - groupMotionBlur->setChecked(view->view()->isFeatureEnabled(QGLView::qglMotionBlurEnabled)); - groupReflections->setChecked(view->view()->isFeatureEnabled(QGLView::qglReflectionsEnabled)); - checkSoftShadows->setChecked(view->view()->isFeatureEnabled(QGLView::qglShadowsSoftEnabled)); - groupSSAO->setChecked(view->view()->isFeatureEnabled(QGLView::qglSSAOEnabled)); - spinAccom->setValue(view->view()->feature(QGLView::qglEyeAccomodationTime).toDouble()); - spinAccomMS->setValue(view->view()->feature(QGLView::qglEyeAccomodationMaxSpeed).toDouble()); - checkReflectionsBlur->setChecked(view->view()->isFeatureEnabled(QGLView::qglReflectionsBlur)); - spinShadowmapSize->setValue(view->view()->feature(QGLView::qglShadowsMapSize).toInt()); - spinMotionBlurFactor->setValue(view->view()->feature(QGLView::qglMotionBlurFactor).toDouble()); - spinMotionBlurSteps->setValue(view->view()->feature(QGLView::qglMotionBlurSteps).toInt()); - spinBloomFactor->setValue(view->view()->feature(QGLView::qglBloomFactor).toDouble()); - spinBloomRadius->setValue(view->view()->feature(QGLView::qglBloomRadius).toInt()); - spinBloomThreshold->setValue(view->view()->feature(QGLView::qglBloomThreshold).toDouble()); - spinSSAORadius->setValue(view->view()->feature(QGLView::qglSSAORadius).toInt()); - groupDOF->setChecked(view->view()->isFeatureEnabled(QGLView::qglDepthOfFieldEnabled)); - checkDOFAutoFocus->setChecked(view->view()->isFeatureEnabled(QGLView::qglDepthOfFieldAutoFocusEnabled)); - spinDOFFocus->setValue(view->view()->feature(QGLView::qglDepthOfFieldFocus).toDouble()); - spinDOFDiaphragm->setValue(view->view()->feature(QGLView::qglDepthOfFieldDiaphragm).toDouble()); - spinDOFSpeed->setValue(view->view()->feature(QGLView::qglDepthOfFieldAutoFocusSpeed).toDouble()); - - view->view()->start(-1); - startTimer(1000/60); - - connect(view->view(), SIGNAL(keyEvent(Qt::Key, Qt::KeyboardModifiers)), this, SLOT(view_keyEvent(Qt::Key, Qt::KeyboardModifiers))); - //connect(matEditor, SIGNAL(changed()), this, SLOT(materialChanged())); - sceneTree->assignQGLView(view->view()); - matEditor->assignQGLView(view->view()); - objectEditor->assignQGLView(view->view()); - primitiveEditor->assignQGLView(view->view()); - viewEditor->assignQGLView(view->view()); - - session.load(); - - //loadFile("axis.DAE.qgl"); - //matEditor->setMaterial(const_cast(view->view()->scene()->rootObject()->child(0))->material()); - /*Scene * sc = loadScene("truck.obj"); - //view->view()->scene()->addScene(sc); - sc->rootObject()->moveY(-8); - for (int i = 0; i < 7; ++i) { - sc->rootObject()->moveY(2); - view->view()->scene()->addScene(sc); - } - //view->view()->scene()->dump(); - delete sc;*/ -} - - -QGLViewWindow::~QGLViewWindow() { - session.save(); - //delete ps; -} - - -void QGLViewWindow::changeEvent(QEvent * e) { - QMainWindow::changeEvent(e); - if (e->type() == QEvent::LanguageChange) { - retranslateUi(this); - return; - } -} - - -void QGLViewWindow::timerEvent(QTimerEvent * ) { - //static double t = 0.; - //((RendererSimple*)(view->view()->renderer()))->mpos = view->view()->mapFromGlobal(QCursor::pos()); - statusBar()->showMessage(QString("FPS: %1").arg(QString::number(view->view()->currentFPS(), 'f', 2))); -} - - -void QGLViewWindow::loadFile(const QString & path, bool import) { - prev_path = path; - QApplication::setOverrideCursor(Qt::WaitCursor); - QFileInfo fi(path); - Scene * s = nullptr; - if (fi.suffix().toLower() == "qgl") s = loadFromQGLFile(path); - else s = loadScene(path); - QApplication::restoreOverrideCursor(); - if (!s) { - QMessageBox::critical(this, "Import", "Can`t load " + path + "!"); - return; - } - s->setName(fi.baseName()); - if (import) view->scene()->addScene(s); - else { - TextureManager::clearSearchPathes(); - view->scene()->assignFrom(s); - view->view()->focusOn(view->scene()->boundingBox()); - } - TextureManager::addSearchPath(fi.absoluteDir().path()); - delete s; -} - - -void QGLViewWindow::on_actionReset_triggered() { - ///view->view()->removeObject(axis, false); - view->view()->scene()->clear(); - ///view->view()->addObject(axis); -} - - -void QGLViewWindow::on_actionImport_triggered() { - QStringList fl = QFileDialog::getOpenFileNames(this, "Select files", prev_path, extensions); - if (fl.isEmpty()) return; - prev_path = fl.back(); - foreach (QString f, fl) - loadFile(f, true); -} - - -void QGLViewWindow::on_actionSave_triggered() { - QString f = QFileDialog::getSaveFileName(this, "Select file", prev_path, "QGLView(*.qgl)"); - if (f.isEmpty()) return; - if (f.right(4).toLower() != ".qgl") - f += ".qgl"; - prev_path = f; - QApplication::setOverrideCursor(Qt::WaitCursor); - saveToQGLFile(f, view->scene()); - QApplication::restoreOverrideCursor(); -} - - -void QGLViewWindow::on_actionSaveSelected_triggered() { - ObjectBase * sel_obj = view->view()->selectedObject(); - if (!sel_obj) return; - QString f = QFileDialog::getSaveFileName(this, "Select file", prev_path, "QGLView(*.qgl)"); - if (f.isEmpty()) return; - if (f.right(4).toLower() != ".qgl") - f += ".qgl"; - prev_path = f; - QApplication::setOverrideCursor(Qt::WaitCursor); - ///saveToQGLFile(f, sel_obj); - QApplication::restoreOverrideCursor(); -} - - -void QGLViewWindow::on_actionOpen_triggered() { - QString f = QFileDialog::getOpenFileName(this, "Select file", prev_path, extensions); - if (f.isEmpty()) return; - prev_path = f; - loadFile(f); -} - - -void QGLViewWindow::view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m) { - //qDebug() << k; - double spd = 0.2; - if (m.testFlag(Qt::ShiftModifier)) - spd = 0.5; - switch (k) { - case Qt::Key_W: view->view()->camera()->moveForward(spd); break; - case Qt::Key_S: view->view()->camera()->moveBackward(spd); break; - case Qt::Key_A: view->view()->camera()->moveLeft(spd); break; - case Qt::Key_D: view->view()->camera()->moveRight(spd); break; - default: break; - } -} - - -void QGLViewWindow::on_actionArrow_triggered(bool on) { - actionArrow ->setChecked(true); - actionMove ->setChecked(false); - actionRotate->setChecked(false); - actionScale ->setChecked(false); - view->view()->setCurrentAction(RendererService::haNoAction); -} - - -void QGLViewWindow::on_actionMove_triggered(bool on) { - actionArrow ->setChecked(false); - actionMove ->setChecked(true); - actionRotate->setChecked(false); - actionScale ->setChecked(false); - view->view()->setCurrentAction(RendererService::haMove); -} - - -void QGLViewWindow::on_actionRotate_triggered(bool on) { - actionArrow ->setChecked(false); - actionMove ->setChecked(false); - actionRotate->setChecked(true); - actionScale ->setChecked(false); - view->view()->setCurrentAction(RendererService::haRotate); -} - - -void QGLViewWindow::on_actionScale_triggered(bool on) { - actionArrow ->setChecked(false); - actionMove ->setChecked(false); - actionRotate->setChecked(false); - actionScale ->setChecked(true); - view->view()->setCurrentAction(RendererService::haScale); -} - - -#include "glcubemap.h" -void QGLViewWindow::on_pushButton_3_clicked() { - QString f = QFileDialog::getOpenFileName(this, "Select file", "", "*"); - if (f.isEmpty()) return; -} diff --git a/qglengine/qglview_test/qglview_window.h b/qglengine/qglview_test/qglview_window.h deleted file mode 100644 index 304353f..0000000 --- a/qglengine/qglview_test/qglview_window.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - QGLViewWindow - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef QGLVIEWWINDOW_H -#define QGLVIEWWINDOW_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ui_qglview_window.h" -#include "formats/loader_qgl.h" -#include "formats/loader_assimp.h" -#include "session_manager.h" -//#include "renderer_rt.h" -#include "qglview.h" -#include "ui_qglview_window.h" - - -class QGLViewWindow: public QMainWindow, public Ui::QGLViewWindow -{ - Q_OBJECT -public: - QGLViewWindow(QWidget * parent = 0); - ~QGLViewWindow(); - - void loadFile(const QString & path, bool import = false); - -private: - // Qt`s overloaded - void changeEvent(QEvent * e); - void timerEvent(QTimerEvent * ); - - QString extensions; - QTranslator translator; - QString prev_path; - //GLPrimitiveCube * box; - Material m; - SessionManager session; - bool isChanged; - -private slots: - void on_groupShadows_clicked(bool val) {view->view()->setFeature(QGLView::qglShadowsEnabled, val);} - void on_groupEyeAccomodation_clicked(bool val) {view->view()->setFeature(QGLView::qglEyeAccomodationEnabled, val);} - void on_groupBloom_clicked(bool val) {view->view()->setFeature(QGLView::qglBloomEnabled, val);} - void on_groupMotionBlur_clicked(bool val) {view->view()->setFeature(QGLView::qglMotionBlurEnabled, val);} - void on_groupReflections_clicked(bool val) {view->view()->setFeature(QGLView::qglReflectionsEnabled, val);} - void on_checkSoftShadows_clicked(bool val) {view->view()->setFeature(QGLView::qglShadowsSoftEnabled, val);} - void on_groupSSAO_clicked(bool val) {view->view()->setFeature(QGLView::qglSSAOEnabled, val);} - void on_groupDOF_clicked(bool val) {view->view()->setFeature(QGLView::qglDepthOfFieldEnabled, val);} - void on_checkDOFAutoFocus_clicked(bool val) {view->view()->setFeature(QGLView::qglDepthOfFieldAutoFocusEnabled, val);} - void on_spinDOFFocus_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldFocus, val);} - void on_spinDOFDiaphragm_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldDiaphragm, val);} - void on_spinDOFSpeed_valueChanged(double val) {view->view()->setFeature(QGLView::qglDepthOfFieldAutoFocusSpeed, val);} - void on_spinAccom_valueChanged(double val) {view->view()->setFeature(QGLView::qglEyeAccomodationTime, val);} - void on_spinAccomMS_valueChanged(double val) {view->view()->setFeature(QGLView::qglEyeAccomodationMaxSpeed, val);} - void on_checkReflectionsBlur_clicked(bool val) {view->view()->setFeature(QGLView::qglReflectionsBlur, val);} - void on_spinShadowmapSize_valueChanged(double val) {view->view()->setFeature(QGLView::qglShadowsMapSize, val);} - void on_spinMotionBlurFactor_valueChanged(double val) {view->view()->setFeature(QGLView::qglMotionBlurFactor, val);} - void on_spinMotionBlurSteps_valueChanged(int val) {view->view()->setFeature(QGLView::qglMotionBlurSteps, val);} - void on_spinBloomFactor_valueChanged(double val) {view->view()->setFeature(QGLView::qglBloomFactor, val);} - void on_spinBloomRadius_valueChanged(int val) {view->view()->setFeature(QGLView::qglBloomRadius, val);} - void on_spinBloomThreshold_valueChanged(double val) {view->view()->setFeature(QGLView::qglBloomThreshold, val);} - void on_spinSSAORadius_valueChanged(int val) {view->view()->setFeature(QGLView::qglSSAORadius, val);} - - void on_actionExit_triggered() {close();} - void on_actionReset_triggered(); - void on_actionImport_triggered(); - void on_actionSave_triggered(); - void on_actionSaveSelected_triggered(); - void on_actionOpen_triggered(); - - void view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m); - - void on_pushButton_2_clicked() {view->view()->reloadShaders();} - - void on_actionArrow_triggered(bool on); - void on_actionMove_triggered(bool on); - void on_actionRotate_triggered(bool on); - void on_actionScale_triggered(bool on); - - void on_colorFogBack_colorChanged(const QColor & v) {view->view()->setFogColor(v);} - void on_spinFogDensity_valueChanged(double v) {view->view()->setFogDensity(v);} - void on_spinFogDecay_valueChanged(double v) {view->view()->setFogDecay(v);} - - void on_pushButton_3_clicked(); - -public slots: - -signals: - -private: - QMatrix4x4 cam_mat; - -}; - -#endif // QGLVIEWWINDOW_H diff --git a/qglengine/qglview_test/qglview_window.ui b/qglengine/qglview_test/qglview_window.ui deleted file mode 100644 index a9bde08..0000000 --- a/qglengine/qglview_test/qglview_window.ui +++ /dev/null @@ -1,978 +0,0 @@ - - - QGLViewWindow - - - - 0 - 0 - 1107 - 878 - - - - QGLView converter - - - - - - - Qt::Horizontal - - - - - 2 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - View - - - - - - 0 - - - - Common - - - - - - - - - - Features - - - - - - QFrame::NoFrame - - - true - - - - - 0 - 0 - 934 - 737 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Shadows - - - true - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Shadowmap size - - - - - - - 16.000000000000000 - - - 2048.000000000000000 - - - 512.000000000000000 - - - 0 - - - 16.000000000000000 - - - 512.000000000000000 - - - true - - - - - - - Soft - - - true - - - - - - - - - - Bloom - - - true - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Factror - - - - - - - 0.000000000000000 - - - 100.000000000000000 - - - 1.000000000000000 - - - 1 - - - 0.100000000000000 - - - 1.000000000000000 - - - false - - - - - - - 1.000000000000000 - - - 128.000000000000000 - - - 8.000000000000000 - - - 0 - - - 1.000000000000000 - - - 4.000000000000000 - - - false - - - - - - - Radius - - - - - - - Threshold - - - - - - - 0.000000000000000 - - - 1.000000000000000 - - - 0.900000000000000 - - - 2 - - - 0.050000000000000 - - - 0.100000000000000 - - - false - - - - - - - - - - Motion blur - - - true - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Factror - - - - - - - Steps - - - - - - - 0.000000000000000 - - - 10000.000000000000000 - - - 1.000000000000000 - - - 1 - - - 0.100000000000000 - - - 1.000000000000000 - - - false - - - - - - - 1.000000000000000 - - - 128.000000000000000 - - - 8.000000000000000 - - - 0 - - - 1.000000000000000 - - - 4.000000000000000 - - - false - - - - - - - - - - Eye accomodation - - - true - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Time - - - - - - - Max speed - - - - - - - 0.000000000000000 - - - 256.000000000000000 - - - 32.000000000000000 - - - true - - - - - - - 0.010000000000000 - - - 1.000000000000000 - - - 0.100000000000000 - - - 3 - - - 0.100000000000000 - - - 1.000000000000000 - - - true - - - - - - - - - - Depth of field - - - true - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Diaphragm - - - - - - - Max speed - - - - - - - 0.100000000000000 - - - 1024.000000000000000 - - - 8.000000000000000 - - - true - - - - - - - 0.010000000000000 - - - 10.000000000000000 - - - 0.100000000000000 - - - 2 - - - 0.100000000000000 - - - 1.000000000000000 - - - true - - - - - - - Focus - - - - - - - 0.100000000000000 - - - 1000.000000000000000 - - - 1.000000000000000 - - - true - - - 999999.000000000000000 - - - - - - - Auto focus - - - - - - - - - - Reflections - - - true - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Blur - - - - - - - - - - SSAO - - - true - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Time - - - - - - - 0.000000000000000 - - - 16.000000000000000 - - - 5.000000000000000 - - - 0 - - - 1.000000000000000 - - - 4.000000000000000 - - - false - - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - - - - - - - - reload shaders - - - - - - - load HDR - - - - - - - Qt::Vertical - - - - 20 - 107 - - - - - - - - - Object - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - Material - - - - - - - - - - Primitives - - - - - - - - - - - - - - - 0 - 0 - - - - - - Scene - - - - - - - - - - - - - - toolBar - - - TopToolBarArea - - - false - - - - - - - - - - - 0 - 0 - 1107 - 24 - - - - - File - - - - - - - - - - - - - Scene - - - - - Mode - - - - - - - - - - - - - - toolBar_2 - - - TopToolBarArea - - - false - - - - - - :/icons/application-exit.png:/icons/application-exit.png - - - Exit - - - - - - :/icons/document-import.png:/icons/document-import.png - - - Import ... - - - Ctrl+I - - - - - - :/icons/document-open.png:/icons/document-open.png - - - Open ... - - - Ctrl+O - - - - - - :/icons/document-save-all.png:/icons/document-save-all.png - - - Save ... - - - Ctrl+S - - - - - - :/icons/document-new.png:/icons/document-new.png - - - Reset - - - Ctrl+N - - - - - - :/icons/document-save.png:/icons/document-save.png - - - Save selected ... - - - Save selected - - - Ctrl+Shift+S - - - - - true - - - true - - - Arrow - - - Ctrl+1 - - - - - true - - - - :/icons/transform-move.png:/icons/transform-move.png - - - Move - - - Ctrl+2 - - - - - true - - - - :/icons/transform-rotate.png:/icons/transform-rotate.png - - - Rotate - - - Ctrl+3 - - - - - true - - - - :/icons/transform-scale.png:/icons/transform-scale.png - - - Scale - - - Ctrl+4 - - - - - - SpinSlider - QWidget -
    spinslider.h
    -
    - - GLWidget - QWidget -
    glwidget.h
    - 1 -
    - - ObjectEditor - QWidget -
    widgets/object_editor.h
    - 1 -
    - - SceneTree - QWidget -
    scene_tree.h
    - 1 -
    - - MaterialsEditor - QWidget -
    widgets/materials_editor.h
    - 1 -
    - - PrimitiveEditor - QWidget -
    primitiveeditor.h
    - 1 -
    - - ViewEditor - QWidget -
    view_editor.h
    - 1 -
    -
    - - - - - - -
    diff --git a/qglengine/renderer.cpp b/qglengine/renderer.cpp deleted file mode 100644 index 7aaec3c..0000000 --- a/qglengine/renderer.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/* - QGL Renderer - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "renderer.h" -#include "qglview.h" -#include "glmesh.h" -#include "gltexture_manager.h" -#include - -using namespace QGLEngineShaders; - - -Renderer::Renderer(QGLView * view_): RendererBase(view_), - fbo_ds (view_, QVector() << GL_RGBA16F << GL_RGBA32F << GL_RGBA16F << GL_RGBA16F << GL_RGBA16F), - fbo_out (view_, obrBuffersCount, false, GL_RGBA16F), - rend_mat(this), rend_service(this), rend_selection(this), tone_proc(this), tex_env(view_, 512) { - quad = Primitive::plane(2., 2.); - cam_light = new Light(); - cam_light->intensity = 0.75; - cam_light->setName("Camera_Light"); - - shader_files[srSelectionFill ] = "selection.glsl"; - shader_files[srSelectionHalo ] = "selection_halo.glsl"; - shader_files[srSelectionApply] = "selection_apply.glsl"; - shader_files[srSelectionFrame] = "selection_frame.glsl"; - - shader_files[srServiceFill ] = "service_fill.glsl"; - shader_files[srServiceFrame] = "service_frame.glsl"; - shader_files[srServiceLine ] = "service_line.glsl"; - - shader_files[srGeometryPass ] = "ds_geom.glsl"; - shader_files[srLightOmniPass] = "ds_light.glsl"; - shader_files[srLightSpotPass] = "ds_light.glsl"; shader_defines[srLightSpotPass] << "SPOT"; - shader_files[srFinalPass ] = "ds_final.glsl"; - shader_files[srTonemapPass ] = "ds_tonemap.glsl"; - - /*shaders << ShaderPair("FXAA", &shader_fxaa) - << ShaderPair("dsl_pass_0", &shader_ds_0) - << ShaderPair("dsl_pass_1", &shader_ds_1) - << ShaderPair("hdr", &shader_hdr) - << ShaderPair("downscale", &shader_small) - << ShaderPair("bloom_pass_0", &shader_bloom_0) - << ShaderPair("bloom_pass_1", &shader_bloom_1) - << ShaderPair("fbo_add", &shader_fbo_add) - << ShaderPair("motion_blur", &shader_motion_blur) - << ShaderPair("shadow", &shader_shadow) - << ShaderPair("ssr", &shader_ssr) - << ShaderPair("ssr_blur", &shader_ssr_blur) - << ShaderPair("ssr_merge", &shader_ssr_merge) - << ShaderPair("ssao_blur", &shader_ssao_blur) - << ShaderPair("ssao_merge", &shader_ssao_merge) - << ShaderPair("dof", &shader_dof);*/ - shader_fxaa = 0; - gamma_ = 1.; - edit_mode = need_init_shaders = true; - camera_light_mode = QGLView::clmAuto; -} - - -Renderer::~Renderer() { - delete quad; - delete cam_light; - qDeleteAll(shaders.values()); - if (shader_fxaa) delete shader_fxaa; -} - - -void Renderer::init(int width, int height) { - resize(width, height); - rend_mat.init(width, height); - rend_service.init(width, height); - rend_selection.init(width, height); - tone_proc.init(); - initQuad(quad); - initTextureArrays(); - initCoeffTextures(); - tex_env.init(); - need_init_shaders = true; -} - - -void Renderer::resize(int width, int height) { - rend_mat.resize(width, height); - rend_service.resize(width, height); - rend_selection.resize(width, height); - fbo_ds .resize(width, height); - fbo_out .resize(width, height); - tone_proc.resize(); -} - - -void Renderer::reloadShaders() { - QMapIterator it(shader_files); - QString dir = ":shaders/"; - while (it.hasNext()) { - it.next(); - loadShadersMulti(shaders[it.key()], dir + it.value(), true, shader_defines.value(it.key())); - } - loadShadersMulti(tone_proc.shader_sum, dir + "sum.glsl", false); - QStringList fxaa_defs; - fxaa_defs << "FXAA_PC 1" << "FXAA_GLSL_130 1" << "FXAA_QUALITY__PRESET 15"; - loadShaders(shader_fxaa, QStringList() << (dir + "fxaa.vert") << (dir + "fxaa.frag"), true, fxaa_defs); - need_init_shaders = true; - view->scene()->setLightsChanged(); - view->scene()->setTreeStructChanged(); - view->scene()->setMaterialsChanged(); -} - - -bool Renderer::bindShader(Renderer::ShaderRole role, QOpenGLShaderProgram ** ret) { - QOpenGLShaderProgram * prog = shaders.value(role); - if (ret) *ret = prog; - if (!prog) return false; - if (!prog->isLinked()) return false; - prog->bind(); - return true; -} - - -bool Renderer::bindShader(QOpenGLShaderProgram * sp) { - if (!sp) return true; - if (!sp->isLinked()) return true; - if (!sp->bind()) return false; - return true; -} - - -void Renderer::initShaders() { - if (!need_init_shaders) return; - need_init_shaders = false; - initUniformBuffer(shaders.value(srGeometryPass ), &buffer_materials , bpMaterials , "QGLMaterialData" ); - initUniformBuffer(shaders.value(srLightOmniPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); - initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights , bpLightParameters, "QGLLightParameterData"); - initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" ); - initUniformBuffer(shaders.value(srLightSpotPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); - initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights , bpLightParameters, "QGLLightParameterData"); - initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" ); - ShaderRole roles[] = {srLightOmniPass, srLightSpotPass}; - QOpenGLShaderProgram * prog = 0; - for (int p = 0; p < 2; ++p) { - if (!bindShader(roles[p], &prog)) continue; - for (int i = 0; i < 5; ++i) - prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); - prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount); - //prog->setUniformValue("tex_coeffs[1]", (int)Renderer::dbrBuffersCount+1); - prog->setUniformValue("tex_env", (int)Renderer::dbrBuffersCount+1); - } - if (bindShader(srFinalPass, &prog)) { - prog->setUniformValue("tex_g1" , 0); - prog->setUniformValue("tex_s_0", 1); - prog->setUniformValue("tex_s_1", 2); - prog->setUniformValue("tex_t_0", 3); - prog->setUniformValue("tex_t_1", 4); - } - if (bindShader(srGeometryPass, &prog)) { - setUniformMaps(prog); - } - if (bindShader(srTonemapPass, &prog)) { - prog->setUniformValue("tex_0", 0); - prog->setUniformValue("tex_sum", 1); - } -} - - -void Renderer::releaseShader() { - view->glUseProgram(0); -} - - -void Renderer::fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass) { - cur_objects_.resize(ol.size()); - for (int i = 0; i < ol.size(); ++i) { - Object & so(cur_objects_[i]); - ObjectBase * o = ol[i]; - if (o->material()) { - so.material = o->material()->_index; - so.color = QVector4D(1,1,1,1); - } else { - so.material = 0; - so.color = QColor2QVector(o->color_); - } - so.object_id = o->id_; - o->worldTransform().transposed().copyDataTo(so.modelmatrix); - //qDebug() << "load obj" << o->name() << o->worldTransform(); - } - //qDebug() << "fillObjectsBuffer" << ol.size(); - -} - - -void Renderer::renderObjects(Scene & scene, RenderPass pass) { - QOpenGLExtraFunctions * f = view; - QMapIterator it(scene.geometries_used[pass]); - bool emit_pos_change = false; - while (it.hasNext()) { - it.next(); - Mesh * mesh = it.key(); - if (mesh->isObjectsChanged(pass)) { - mesh->setObjectsChanged(pass, false); - emit_pos_change = true; - fillObjectsBuffer(it.value(), pass); - //qDebug() << "loadObjects" << pass << cur_objects_.size(); - mesh->loadObjects(f, cur_objects_, pass); - } - if (mesh->isSelectionChanged(pass) && edit_mode) { - mesh->setSelectionChanged(pass, false); - fillSelectionsBuffer(rend_selection.cur_selections_, it.value()); - //qDebug() << "fillSelectionsBuffer" << pass << rend_selection.cur_selections_.size(); - mesh->loadSelections(f, rend_selection.cur_selections_, pass); - } - //qDebug() << "draw" << pass << it.value().size(); - mesh->draw(f, it.value().size(), pass); - } - if (emit_pos_change) emit view->objectsPositionChanged(); -} - - -void Renderer::renderLight(int first_wr_buff, bool clear_only) { - QOpenGLShaderProgram * prog = 0; - Camera * cam = view->camera(); - for (int i = 0; i < 2; ++i) { - view->glActiveTexture(GL_TEXTURE0 + Renderer::dbrBuffersCount + i); - view->glBindTexture(GL_TEXTURE_2D, tex_coeff[i]); - } - fbo_ds.bindColorTextures(); - fbo_out.bind(); - tex_env.bind((int)Renderer::dbrBuffersCount+1); - //int ri = 1, wi = 0; - typedef QPair PassPair; - QVector passes; - passes << PassPair(srLightOmniPass, Light::Omni) << PassPair(srLightSpotPass, Light::Cone); - QColor back = view->fogColor_; - back.setAlpha(0); - foreach (PassPair pass, passes) { - if (bindShader(pass.first, &prog)) { - fbo_out.setWriteBuffer(first_wr_buff + pass.second); - glClearFramebuffer(back, false); - if (clear_only) continue; - setUniformCamera(prog, cam); - setUniformViewCorners(prog, cam); - prog->setUniformValue("lights_start", lights_start[pass.second]); - prog->setUniformValue("lights_count", cur_lights[pass.second].size()); - prog->setUniformValue("fog_color", view->fogColor_); - prog->setUniformValue("fog_decay", qMax(view->fogDecay_, 0.001f)); - prog->setUniformValue("fog_density", view->fogDensity_); - prog->setUniformValue("view_mat", cam->viewMatrix().inverted().toGenericMatrix<3,3>()); - renderQuad(prog, quad, cam); - } - } -} - - -void Renderer::renderScene() { - initShaders(); - tex_env.load(); - QOpenGLExtraFunctions * f = view; - Scene & scene(*(view->scene_)); - Camera * cam = view->camera(); - QOpenGLShaderProgram * prog = 0; - bool scene_changed = scene.prepare(); - scene.destroyUnused(f); - - /// reload materials on change - if (scene_changed || scene.need_reload_materials) { - //if (scene.need_reload_materials) - // maps_hash = 0; - rend_selection.generateObjectsID(scene); - reloadMaterials(scene); - if (edit_mode) - recreateMaterialThumbnails(); - emit view->materialsChanged(); - } - - /// material thumbnails - if (edit_mode && !scene_changed) { - rend_mat.procQueue(); - } - - /// lights - cur_lights = scene.lights_used; - bool use_camlight = (camera_light_mode == QGLView::clmOn); - if ((camera_light_mode == QGLView::clmAuto) && cur_lights.isEmpty()) - use_camlight = true; - if (use_camlight) { - cur_lights[Light::Omni] << cam_light; - cam_light->setPos(cam->pos()); - } - if (scene.lights_changed) { - scene.lights_changed = false; - reloadLightsParameters(cur_lights); - } - reloadLightsPositions(cam); - - /// selection - if (edit_mode) { - rend_selection.renderSelection(scene); - } - - /// solid geometry pass - fbo_ds.bind(); - glEnableDepth(); - glClearFramebuffer(); - if (bindShader(srGeometryPass, &prog)) { - setUniformCamera(prog, cam); - textures_empty.bind(f, tarEmpty); - textures_maps .bind(f, tarMaps ); - renderObjects(scene, rpSolid); - } - fbo_ds.release(); - - /// lighting passes - renderLight(obrSolidOmni, scene.geometries_used[rpSolid].isEmpty()); - - /// transparent geometry pass - fbo_ds.bind(); - glEnableDepth(); - glClearFramebuffer(Qt::black, false); - if (bindShader(srGeometryPass, &prog)) { - renderObjects(scene, rpTransparent); - } - fbo_ds.release(); - - /// lighting passes - renderLight(obrTransparentOmni, scene.geometries_used[rpTransparent].isEmpty()); - - /// blending layers - if (bindShader(srFinalPass, &prog)) { - //fbo_ds .bindColorTexture(dbrNormalZ , 0); - fbo_out.bindColorTexture(obrSolidOmni , 1); - fbo_out.bindColorTexture(obrSolidSpot , 2); - fbo_out.bindColorTexture(obrTransparentOmni, 3); - fbo_out.bindColorTexture(obrTransparentSpot, 4); - fbo_out.setWriteBuffer(obrSum); - renderQuad(prog, quad); - } - - /// tonemapping - if (tone_proc.process()) - fbo_out.bind(); - if (bindShader(srTonemapPass, &prog)) { - prog->setUniformValue("gamma", gamma_); - prog->setUniformValue("frame_max", tone_proc.frameMax()); - fbo_out.bindColorTexture(obrSum, 0); - fbo_out.setWriteBuffer(obrTonemap); - renderQuad(prog, quad); - } else - fbo_out.blit(obrSum, fbo_out.id(), obrTonemap, fbo_out.rect(), fbo_out.rect()); - fbo_out.release(); - - /// apply hovers and selection frame - if (edit_mode) { - rend_selection.drawSelection(fbo_out, obrTonemap); - rend_service.renderService(); - } else { - fbo_out.blit(obrTonemap, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size())); - } - //fbo_small_16.blit(0, 0, 0, fbo_small_16.rect(), fbo_small_16.rect(), GL_COLOR_BUFFER_BIT, GL_LINEAR); - -} - - -void Renderer::setCameraLightMode(int m) { - camera_light_mode = m; - view->scene()->setLightsChanged(); -} diff --git a/qglengine/renderer.h b/qglengine/renderer.h deleted file mode 100644 index d865bbb..0000000 --- a/qglengine/renderer.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - QGL Renderer - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef RENDERER_H -#define RENDERER_H - -#include "renderer_base.h" -#include "renderer_material.h" -#include "renderer_service.h" -#include "renderer_selection.h" -#include "tonemapping_proc.h" -#include "glcubemap.h" -#include - - -class Renderer: public RendererBase { - friend class QGLView; - friend class MouseController; - friend class RendererBase; - friend class RendererMaterial; - friend class RendererService; - friend class RendererSelection; - friend class TonemappingProc; - enum ShaderRole { - // Selection - srSelectionFill, - srSelectionHalo, - srSelectionApply, - srSelectionFrame, - - // Service - srServiceFill, - srServiceFrame, - srServiceLine, - - // Deferred shading - srGeometryPass, - srLightOmniPass, - srLightSpotPass, - srFinalPass, - srTonemapPass, - }; - enum DeferredBufferRole { - dbrDiffuse, - dbrNormalZ, - dbrSpecularReflect, - dbrEmissionRough, - dbrSpeedBitangXY, - - dbrBuffersCount, - }; - enum OutBufferRole { - obrTonemap, - obrSum, - obrSolidOmni, - obrSolidSpot, - obrTransparentOmni, - obrTransparentSpot, - - obrBuffersCount, - }; - -public: - Renderer(QGLView * view_); - virtual ~Renderer(); - - void init(int width, int height); - void resize(int width, int height); - void reloadShaders(); - void renderScene(); - void setCameraLightMode(int m); - int cameraLightMode() const {return camera_light_mode;} - - QImage materialThumbnail(Material * m) {return rend_mat.materialThumbnail(m);} - void recreateMaterialThumbnails(bool force_all = false) {rend_mat.recreateMaterialThumbnails(force_all);} - -protected: - void fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass); - void reloadObjects(); - void renderObjects(Scene & scene, RenderPass pass); - void renderLight(int first_wr_buff, bool clear_only); - - bool bindShader(ShaderRole role, QOpenGLShaderProgram ** ret = 0); - bool bindShader(QOpenGLShaderProgram * sp); - void initShaders(); - void releaseShader(); - -private: - float gamma_; - int camera_light_mode; - bool edit_mode, need_init_shaders, need_render_sum; - Framebuffer fbo_ds, fbo_out; - /*QOpenGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1, * shader_hdr, * shader_small; - QOpenGLShaderProgram * shader_bloom_0, * shader_bloom_1, * shader_motion_blur, * shader_fbo_add; - QOpenGLShaderProgram * shader_shadow, * shader_ssr, * shader_ssr_blur, * shader_ssr_merge; - QOpenGLShaderProgram * shader_ssao_blur, * shader_ssao_merge, * shader_dof;*/ - QMap shader_files; - QMap shader_defines; - QMap shaders; - QOpenGLShaderProgram * shader_fxaa; - - RendererMaterial rend_mat; - RendererService rend_service; - RendererSelection rend_selection; - TonemappingProc tone_proc; - - Mesh * quad; - Light * cam_light; - CubeTexture tex_env; - - QPoint mouse_pos; - QRect mouse_rect; - QMatrix4x4 prev_view, prev_proj; - QMatrix3x3 nm; - QVector4D corner_dirs[4]; - QVector hcontent; - QMap> cur_lights; - -}; - -#endif // RENDERER_H diff --git a/qglengine/renderer_base.cpp b/qglengine/renderer_base.cpp deleted file mode 100644 index f22c287..0000000 --- a/qglengine/renderer_base.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* - QGL RendererBase - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "renderer_base.h" -#include "renderer.h" -#include "qglview.h" -#include "glmesh.h" -#include "gltexture_manager.h" -#include "glshaders_headers.h" - -using namespace QGLEngineShaders; - - -RendererBase::RendererBase(QGLView * view_): - view(view_), - buffer_materials (GL_UNIFORM_BUFFER, GL_STREAM_DRAW), - buffer_lights (GL_UNIFORM_BUFFER, GL_STREAM_DRAW), - buffer_lights_pos(GL_UNIFORM_BUFFER, GL_STREAM_DRAW), - textures_empty(false), - textures_maps(true) -{ - textures_manager = new TextureManager(view); - maps_size = QSize(512, 512); - maps_hash = 0; - tex_coeff[0] = tex_coeff[1] = 0; - -} - - -RendererBase::~RendererBase() { - delete textures_manager; -} - - -void RendererBase::initTextureArrays() { - QOpenGLExtraFunctions * f = view; - textures_maps.init(f); - textures_empty.init(f); - textures_empty.resize(f, QSize(1, 1), 2); - textures_empty.bind(f); - QImage im(1, 1, QImage::Format_RGBA8888); - im.fill(0xFFFFFFFF); - textures_empty.load(f, im, emrWhite); - im.fill(0xFF8080); - textures_empty.load(f, im, emrBlue); -} - - -void RendererBase::initUniformBuffer(QOpenGLShaderProgram * prog, Buffer * buffer, int bind_point, const char * blockName) { - if (!prog || !buffer) return; - if (!prog->isLinked()) return; - QOpenGLExtraFunctions * f = view; - buffer->init(f); - //glClearError(); - GLint ubo_ind = f->glGetUniformBlockIndex(prog->programId(), blockName); - f->glUniformBlockBinding(prog->programId(), ubo_ind, bind_point); - f->glBindBufferBase(GL_UNIFORM_BUFFER, bind_point, buffer->ID()); - //qDebug() << "initUBO" << QString::number(f->glGetError(), 16); -} - - -void RendererBase::setUniformHalo(QOpenGLShaderProgram * prog, const char * type, QColor color, float fill) { - prog->setUniformValue((QString(type) + "_color").toLatin1().constData(), color); - prog->setUniformValue((QString(type) + "_fill" ).toLatin1().constData(), fill); -} - - -void RendererBase::setUniformMaps(QOpenGLShaderProgram * prog) { - prog->setUniformValue("qgl_texture_array[0]", (int)tarEmpty); - prog->setUniformValue("qgl_texture_array[1]", (int)tarMaps ); -} - - -void RendererBase::setUniformCamera(QOpenGLShaderProgram * prog, Camera * cam, bool matrices, QSize viewport) { - double w = view->width(), h = view->height(); - if (viewport.isValid()) { - w = viewport.width(); - h = viewport.height(); - } - QMatrix4x4 mat_view, mat_proj; - if (cam) { - if (matrices) { - mat_view = cam->fullViewMatrix(); - mat_proj = cam->projectionMatrix(w / h); - } - prog->setUniformValue("z_near", cam->depthStart()); - } - prog->setUniformValue("dt", QVector2D(1. / w, 1. / h)); - prog->setUniformValue("qgl_ViewMatrix" , mat_view); - prog->setUniformValue("qgl_ViewProjMatrix", mat_proj * mat_view); -} - - -void RendererBase::setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * cam, QSize viewport) { - double w = view->width(), h = view->height(); - if (viewport.isValid()) { - w = viewport.width(); - h = viewport.height(); - } - QMatrix4x4 mproji = cam->projectionMatrix(w / h).inverted(); - QMatrix4x4 mviewi = cam->viewMatrix().inverted(); - QVector4D corner_dirs[4], world_dirs[4]; - corner_dirs[0] = (mproji * QVector4D(-1, -1, 0, 1)); - corner_dirs[1] = (mproji * QVector4D(-1, 1, 0, 1)); - corner_dirs[2] = (mproji * QVector4D( 1, 1, 0, 1)); - corner_dirs[3] = (mproji * QVector4D( 1, -1, 0, 1)); - for (int i = 0; i < 4; ++i) { - world_dirs[i] = mviewi.mapVector(corner_dirs[i].toVector3D()); - prog->setUniformValue(QString("view_corners[%1]").arg(i).toLatin1().constData(), corner_dirs[i]); - prog->setUniformValue(QString("world_corners[%1]").arg(i).toLatin1().constData(), world_dirs[i]); - } -} - - -void RendererBase::fillSelectionsBuffer(QVector & buffer, const ObjectBaseList & ol) { - buffer.resize(ol.size()); - for (int i = 0; i < ol.size(); ++i) { - buffer[i] = (ol[i]->isSelected(true) ? 1 : 0); - } -} - - -void RendererBase::fillSelectionsBuffer(QVector & buffer, bool yes, int size) { - buffer.resize(size); - for (int i = 0; i < size; ++i) - buffer[i] = (yes ? 1 : 0); -} - - -void RendererBase::reloadMaterials(Scene & scene) { - //qDebug() << "reloadMaterias"; - QList maps[2]; - QMap tex_layers[2]; - foreach (Material * m, scene.materials) { - if (m->map_diffuse .hasBitmap()) maps[0] << &(m->map_diffuse ); - if (m->map_normal .hasBitmap()) maps[1] << &(m->map_normal ); - if (m->map_metalness.hasBitmap()) maps[0] << &(m->map_metalness); - if (m->map_roughness.hasBitmap()) maps[0] << &(m->map_roughness); - if (m->map_emission .hasBitmap()) maps[0] << &(m->map_emission ); - if (m->map_relief .hasBitmap()) maps[0] << &(m->map_relief ); - } - for (int i = 0; i < 2; ++i) { - foreach (Map * m, maps[i]) - tex_layers[i][m->bitmap_path] = 0; - } - int layers_count = tex_layers[0].size() + tex_layers[1].size(), cl = -1; - uint cur_maps_hash = qHash(tex_layers[0].keys()) ^ (qHash(tex_layers[1].keys()) + 0xF00FF00F); - if (maps_hash != cur_maps_hash) { - maps_hash = cur_maps_hash; - textures_maps.resize(view, maps_size, layers_count); - textures_maps.bind(view); - for (int i = 0; i < 2; ++i) { - QMutableMapIterator it(tex_layers[i]); - while (it.hasNext()) { - it.next(); - QImage im = textures_manager->loadTextureImage(it.key(), i == 1); - textures_maps.load(view, im, ++cl); - it.value() = cl; - } - foreach (Map * m, maps[i]) { - m->_layer = tex_layers[i].value(m->bitmap_path); - //qDebug() << "assign" << m->bitmap_path << "layer" << m->_layer; - } - } - textures_maps.mipmaps(view); -// qDebug() << "load" << (cl+1) << "bitmaps"; - } - - QGLMaterial glm; - cur_materials_.clear(); - cur_materials_ << glm; - foreach (Material * m, scene.materials) { - if (cur_materials_.size() >= max_materials) { - qDebug() << "[QGLEngine] Warning: Too many materials! Maximum" << max_materials; - break; - } - //m->load(textures_manager); - m->_index = cur_materials_.size(); - m->_changed = false; - glm.color_diffuse = QColor2QVector(m->color_diffuse ); - glm.color_emission = QColor2QVector(m->color_emission); - glm.transparency = m->transparency; - glm.reflectivity = m->reflectivity; - glm.iof = m->iof ; - glm.dispersion = m->dispersion ; - m->map_diffuse .copyToQGLMap(glm.map[mtDiffuse ]); - m->map_normal .copyToQGLMap(glm.map[mtNormal ]); - m->map_metalness.copyToQGLMap(glm.map[mtMetalness ]); - m->map_roughness.copyToQGLMap(glm.map[mtRoughness]); - m->map_emission .copyToQGLMap(glm.map[mtEmission ]); - m->map_relief .copyToQGLMap(glm.map[mtRelief ]); - cur_materials_ << glm; - } - //qDebug() << "load" << cur_materials_.size() << "materials"; - //textures_maps.resize(maps_size, ); - //cur_materials_[0].color_diffuse = QColor2QVector(Qt::red); - buffer_materials.bind(view); - buffer_materials.resize(view, cur_materials_.size() * sizeof(QGLMaterial)); - buffer_materials.load(view, cur_materials_.constData(), cur_materials_.size() * sizeof(QGLMaterial)); - scene.need_reload_materials = false; - -} - - -void RendererBase::reloadLightsParameters(const QMap> & lights) { - lights_start.clear(); - lights_start[Light::Omni] = 0; - QMapIterator> it(lights); - current_lights.clear(); - while (it.hasNext()) { - it.next(); - lights_start[it.key()] = current_lights.size(); - current_lights.append(it.value()); - } - cur_lights_params_.resize(qMin(current_lights.size(), max_lights)); - //qDebug() << "reloadLightsParameters" << cur_lights_params_.size(); - for (int i = 0; i < cur_lights_params_.size(); ++i) { - QGLLightParameter & so(cur_lights_params_[i]); - Light * l = current_lights[i]; - double ang_start = l->angle_start / 2.f, ang_end = l->angle_end / 2.f; - if (l->light_type == Light::Omni) - ang_start = ang_end = 180.; - //qDebug() << "light" << light->name() << ulightn << pos; - so.color = QColor2QVector(l->color_); - so.angles[0] = ang_start; - so.angles[1] = cos(ang_start * deg2rad); - so.angles[2] = ang_end; - so.angles[3] = cos(ang_end * deg2rad); - so.decay_intensity[0] = l->decay_const; - so.decay_intensity[1] = l->decay_linear; - so.decay_intensity[2] = l->decay_quadratic; - so.decay_intensity[3] = l->intensity; - //so.shadow = shadow; - //so.shadowColor = shadow; - } - buffer_lights.bind(view); - buffer_lights.resize(view, cur_lights_params_.size() * sizeof(QGLLightParameter)); - buffer_lights.load(view, cur_lights_params_.constData(), cur_lights_params_.size() * sizeof(QGLLightParameter)); -} - - -void RendererBase::reloadLightsPositions(Camera * cam) { - cur_lights_pos_.resize(qMin(current_lights.size(), max_lights)); - QMatrix4x4 mat = cam->viewMatrix() * cam->offsetMatrix(); - for (int i = 0; i < cur_lights_pos_.size(); ++i) { - QGLLightPosition & so(cur_lights_pos_[i]); - Light * l = current_lights[i]; - QMatrix4x4 m = mat * l->worldTransform(); - QVector4D pos(0, 0, 0, 1.), dir(QVector3D(0,0,-1), 1);//, dir0(light->dir0), dir1(light->dir1); - pos = m * pos; - dir = (m * QVector4D(QVector3D(0,0,-1),0)).normalized();//((m * dir) - pos).normalized(); - so.position = pos; - so.direction = dir; - //so.shadowMatrix = l->shadow_matrix; - } - buffer_lights_pos.bind(view); - buffer_lights_pos.resize(view, cur_lights_pos_.size() * sizeof(QGLLightPosition)); - buffer_lights_pos.load(view, cur_lights_pos_.constData(), cur_lights_pos_.size() * sizeof(QGLLightPosition)); -} - - -void RendererBase::markReloadTextures() { - maps_hash = 0; - textures_manager->clearImageCache(); - view->scene_->need_reload_materials = true; -} - - -void RendererBase::setMapsSize(QSize sz) { - maps_size = sz; - markReloadTextures(); -} - - -void RendererBase::initQuad(Mesh * mesh, QMatrix4x4 mat) { - QGLEngineShaders::Object quab_object; - mat.transposed().copyDataTo(quab_object.modelmatrix); - mesh->init(view); - mesh->loadObject(view, quab_object); -} - - -void RendererBase::renderQuad(QOpenGLShaderProgram * prog, Mesh * mesh, Camera * cam, bool uniforms) { - glDisableDepth(); - if (uniforms) - setUniformCamera(prog, cam, false); - mesh->draw(view, 1); -} - - - - -float RadicalInverse_VdC(uint bits) { - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // / 0x100000000 -} -// ---------------------------------------------------------------------------- -QVector2D Hammersley(uint i, uint N) { - return QVector2D(float(i)/float(N), RadicalInverse_VdC(i)); -} -QVector3D ImportanceSampleGGX(QVector2D Xi, QVector3D N, float roughness) { - float a = roughness*roughness; - float phi = 2.0 * M_PI * Xi[0]; - float cosTheta = sqrt((1.0 - Xi[1]) / (1.0 + (a*a - 1.0) * Xi[1])); - float sinTheta = sqrt(1.0 - cosTheta*cosTheta); - // преобразование из сферических в декартовы координаты - QVector3D H; - H[0] = cos(phi) * sinTheta; - H[1] = sin(phi) * sinTheta; - H[2] = cosTheta; - // преобразование из касательного пространства в мировые координаты - QVector3D up = qAbs(N[2]) < 0.999 ? QVector3D(0.0, 0.0, 1.0) : QVector3D(1.0, 0.0, 0.0); - QVector3D tangent = QVector3D::crossProduct(up, N).normalized(); - QVector3D bitangent = QVector3D::crossProduct(N, tangent); - QVector3D sampleVec = tangent * H[0] + bitangent * H[1] + N * H[2]; - return sampleVec.normalized(); -} -float GeometrySchlickGGX(float NdotV, float roughness) { - float k = (roughness * roughness) / 2.0; - float nom = NdotV; - float denom = NdotV * (1.0 - k) + k; - return nom / denom; -} -float GeometrySmith(QVector3D N, QVector3D V, QVector3D L, float roughness) { - float NdotV = piMax(QVector3D::dotProduct(N, V), 0.f); - float NdotL = piMax(QVector3D::dotProduct(N, L), 0.f); - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); - return ggx1 * ggx2; -} -QVector2D IntegrateBRDF(float NdotV, float roughness) { - QVector3D V; - V[0] = sqrt(1.f - NdotV*NdotV); - V[1] = 0.f; - V[2] = NdotV; - float A = 0.f; - float B = 0.f; - QVector3D N = QVector3D(0.f, 0.f, 1.f); - const uint SAMPLE_COUNT = 256u; - for(uint i = 0u; i < SAMPLE_COUNT; ++i) { - QVector2D Xi = Hammersley(i, SAMPLE_COUNT); - QVector3D H = ImportanceSampleGGX(Xi, N, roughness); - QVector3D L = (2.f * QVector3D::dotProduct(V, H) * H - V).normalized(); - float NdotL = piMax(L[2], 0.f); - float NdotH = piMax(H[2], 0.f); - float VdotH = piMax(QVector3D::dotProduct(V, H), 0.f); - if(NdotL > 0.f) { - float G = GeometrySmith(N, V, L, roughness); - float G_Vis = (G * VdotH) / (NdotH * NdotV); - float Fc = pow(1.f - VdotH, 5.f); - A += (1.f - Fc) * G_Vis; - B += Fc * G_Vis; - } - } - A /= float(SAMPLE_COUNT); - B /= float(SAMPLE_COUNT); - return QVector2D(A, B); -} - -void RendererBase::initCoeffTextures() { - QImage im = QImage(":/coeffs_brdf.png").mirrored(); - int size = im.width(); - QVector data(size*size); - int ind = -1; - for (int x = 0; x < size; ++x) { - //float c = x / double(size - 1) + 1.E-3; - for (int y = 0; y < size; ++y) { - //float r = y / double(size - 1); - QColor p = im.pixelColor(x, y); - data[++ind] = QVector2D(p.redF(), p.greenF());//IntegrateBRDF(c, 1.f - r + 1.E-3); - } - } - createCoeffTexture(tex_coeff[0], data.constData(), size, 2); - /*const int size = 512; - QVector data_diff(size*size), data_spec(size*size); - double r, c, c2; - int ind = -1; - for (int x = 0; x < size; ++x) { - c = x / double(size - 1); - c = sqrt(c); - c = piMax(1.E-16, c); - c2 = c*c; - for (int y = 0; y < size; ++y) { - r = y / double(size - 1); - double r_d = r; - double r_s = r*r*r; - r_d = piMax(1.E-16, r_d); - r_s = piMax(1.E-16, r_s); - - double ndlc = (1. - c2) / c2; - double diff = 2. / (1. + sqrt(1. + (1. - r_d) * ndlc)); - - double spec = c2 * (r_s + ndlc); - spec = r_s / (spec * spec) / M_PI; - - ++ind; - data_diff[ind] = piClamp(diff, 1.E-12, 1.E+36); - data_spec[ind] = piClamp(spec, 1.E-12, 1.E+36); - } - } - createCoeffTexture(tex_coeff[0], data_diff, size); - createCoeffTexture(tex_coeff[1], data_spec, size);*/ -} - - -void RendererBase::createCoeffTexture(GLuint & id, const void * data, int size, int channels) { - QOpenGLExtraFunctions * f = view; - deleteGLTexture(f, id); - f->glGenTextures(1, &id); - f->glBindTexture(GL_TEXTURE_2D, id); - f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - GLenum iformat = GL_R16F, format = GL_RED; - if (channels == 2) {iformat = GL_RG16F; format = GL_RG;} - if (channels == 3) {iformat = GL_RGB16F; format = GL_RGB;} - if (channels == 4) {iformat = GL_RGBA16F; format = GL_RGBA;} - f->glTexImage2D(GL_TEXTURE_2D, 0, iformat, size, size, 0, format, GL_FLOAT, data); -} diff --git a/qglengine/renderer_base.h b/qglengine/renderer_base.h deleted file mode 100644 index e0f5574..0000000 --- a/qglengine/renderer_base.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - QGL RendererBase - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef RENDERER_BASE_H -#define RENDERER_BASE_H - -#include "glshaders_types.h" -#include "gltexturearray.h" -#include "glbuffer.h" - - -class RendererBase { -public: - RendererBase(QGLView * view_); - ~RendererBase(); - -protected: - void initTextureArrays(); - void initUniformBuffer (QOpenGLShaderProgram * prog, Buffer * buffer, int bind_point, const char * blockName); - void setUniformHalo (QOpenGLShaderProgram * prog, const char * type, QColor color, float fill); - void setUniformMaps (QOpenGLShaderProgram * prog); - void setUniformCamera (QOpenGLShaderProgram * prog, Camera * cam, bool matrices = true, QSize viewport = QSize()); - void setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * cam, QSize viewport = QSize()); - void fillSelectionsBuffer(QVector & buffer, const ObjectBaseList & ol); - void fillSelectionsBuffer(QVector & buffer, bool yes, int size); - void reloadMaterials(Scene & scene); - void reloadLightsParameters(const QMap> & lights); - void reloadLightsPositions (Camera * cam); - void markReloadTextures(); - void setMapsSize(QSize sz); - void initQuad(Mesh * mesh, QMatrix4x4 mat = QMatrix4x4()); - void renderQuad(QOpenGLShaderProgram * prog, Mesh * mesh, Camera * cam = 0, bool uniforms = true); - void initCoeffTextures(); - void createCoeffTexture(GLuint & id, const void * data, int size, int channels = 1); - - QGLView * view; - TextureManager * textures_manager; - QVector cur_objects_; - QVector cur_materials_; - QVector cur_lights_params_; - QVector cur_lights_pos_; - Buffer buffer_materials; - Buffer buffer_lights, buffer_lights_pos; - Texture2DArray textures_empty, textures_maps; - QSize maps_size; - uint maps_hash; - GLuint tex_coeff[2]; - QMap lights_start; - QList current_lights; - -}; - -#endif // RENDERER_BASE_H diff --git a/qglengine/renderer_material.cpp b/qglengine/renderer_material.cpp deleted file mode 100644 index 0e6c594..0000000 --- a/qglengine/renderer_material.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - QGL RendererMaterial - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "renderer_material.h" -#include "renderer.h" -#include "qglview.h" -#include "glmesh.h" -#include "gltexture_manager.h" -#include - -using namespace QGLEngineShaders; - - -RendererMaterial::RendererMaterial(Renderer * r_): r(r_), - fbo_mat_thumb(r->view, 6, true , GL_RGBA16F) { - mat_sphere = Primitive::ellipsoid(16, 16); - mat_camera = new Camera(); - mat_camera->setPos(QVector3D(2, 2, 2)); - mat_camera->setAim(QVector3D()); - mat_camera->setFOV(45.); - mat_light = new Light(); - mat_light->setPos(QVector3D(50, 100, 25)); - last_thumb_material = 0; -} - - -RendererMaterial::~RendererMaterial() { - delete mat_sphere; - delete mat_camera; - delete mat_light; -} - - -void RendererMaterial::init(int width, int height) { - resize(width, height); -} - - -void RendererMaterial::resize(int width, int height) { - fbo_mat_thumb.enablePixelBuffer(); - fbo_mat_thumb.resize(256, 256); -} - - -void RendererMaterial::renderMaterial(Material * m) { - //qDebug() << "renderMaterial" << m; - last_thumb_material = m; - QOpenGLShaderProgram * prog = 0; - QOpenGLExtraFunctions * f = r->view; - fbo_mat_thumb.bind(); - glEnableDepth(); - glClearFramebuffer(QColor(0,0,0,0)); - if (r->bindShader(Renderer::srGeometryPass, &prog)) { - r->setUniformMaps(prog); - r->setUniformCamera(prog, mat_camera, true, fbo_mat_thumb.size()); - //qDebug() << mat_camera->viewMatrix(); - r->textures_empty.bind(f, tarEmpty); - r->textures_maps .bind(f, tarMaps ); - Object o; - o.material = m->_index; - mat_sphere->loadObject(f, o); - mat_sphere->draw(f, 1); - } - fbo_mat_thumb.bindColorTextures(); - fbo_mat_thumb.bindDepthTexture(5); - fbo_mat_thumb.setWriteBuffer(5); - if (r->bindShader(Renderer::srLightOmniPass, &prog)) { - r->setUniformCamera(prog, mat_camera, true, fbo_mat_thumb.size()); - r->setUniformViewCorners(prog, mat_camera, fbo_mat_thumb.size()); - for (int i = 0; i < 5; ++i) - prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); - prog->setUniformValue("tex_d", 5); - prog->setUniformValue("lights_start", 0); - prog->setUniformValue("lights_count", 1); - QMap> mat_l; - mat_l[Light::Omni] << mat_light; - r->reloadLightsParameters(mat_l); - r->reloadLightsPositions(mat_camera); - glClearFramebuffer(r->view->backColor(), false); - r->renderQuad(prog, r->quad, mat_camera); - r->view->scene()->setLightsChanged(); - } - fbo_mat_thumb.queryImage(5); - fbo_mat_thumb.release(); -} - - -void RendererMaterial::procQueue() { - if (last_thumb_material) { - mat_thumbnails[last_thumb_material] = fbo_mat_thumb.getImage(); - emit r->view->materialThumbnailCreated(last_thumb_material); - last_thumb_material = 0; - } - if (!mat_thumb_queue.isEmpty()) - renderMaterial(mat_thumb_queue.dequeue()); -} - - -QImage RendererMaterial::materialThumbnail(Material * m) { - return mat_thumbnails.value(m); -} - - -void RendererMaterial::recreateMaterialThumbnails(bool force_all) { - if (force_all) { - mat_thumb_queue.clear(); - //qDebug() << "recreateMaterialThumbnails" << view->scene_->materials; - foreach (Material * m, r->view->scene_->materials) - mat_thumb_queue.enqueue(m); - } else { - foreach (Material * m, r->view->scene_->changed_materials) - if (!mat_thumb_queue.contains(m)) - mat_thumb_queue.enqueue(m); - } -} diff --git a/qglengine/renderer_material.h b/qglengine/renderer_material.h deleted file mode 100644 index 3c08a7b..0000000 --- a/qglengine/renderer_material.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - QGL RendererMaterial - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef RENDERER_MATERIAL_H -#define RENDERER_MATERIAL_H - -#include "glframebuffer.h" -#include - - -class RendererMaterial { - friend class QGLView; - -public: - RendererMaterial(Renderer * r_); - virtual ~RendererMaterial(); - - void init(int width, int height); - void resize(int width, int height); - - QImage materialThumbnail(Material * m); - void recreateMaterialThumbnails(bool force_all = false); - void renderMaterial(Material * m); - void procQueue(); - -private: - Renderer * r; - - Framebuffer fbo_mat_thumb; - Mesh * mat_sphere; - Camera * mat_camera; - Light * mat_light; - QMap mat_thumbnails; - Material * last_thumb_material; - QQueue mat_thumb_queue; - -}; - -#endif // RENDERER_MATERIAL_H diff --git a/qglengine/renderer_selection.cpp b/qglengine/renderer_selection.cpp deleted file mode 100644 index 00897a7..0000000 --- a/qglengine/renderer_selection.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - QGL RendererSelection - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "renderer_selection.h" -#include "qglview.h" -#include "glmesh.h" -#include - -using namespace QGLEngineShaders; - - -RendererSelection::RendererSelection(Renderer * r_): r(r_), - fbo_selection(r->view, 6) { - sel_frame = Primitive::plane(2., 2.); - id_hover = 0; - line_thick_ = 2.; - scale_ = 0.5; -} - - -RendererSelection::~RendererSelection() { - delete sel_frame; -} - - -void RendererSelection::init(int width, int height) { - resize(width, height); -} - - -void RendererSelection::resize(int width, int height) { - line_thick_ = lineThickness() + 1.; - scale_ = 0.5 / appScale(); - fbo_selection.enablePixelBuffer(); - fbo_selection.resize(width * scale_, height * scale_); - //fbo_selection.setColorTextureFiltering(sbrSrcHover , GL_LINEAR); - //fbo_selection.setColorTextureFiltering(sbrSrcSelect, GL_LINEAR); -} - - -void RendererSelection::generateObjectsID(Scene & scene) { - ids.clear(); - aim_ids.clear(); - QList passes = scene.geometries_used.keys(); - foreach (int p, passes) { - QMapIterator it(scene.geometries_used[p]); - while (it.hasNext()) { - it.next(); - foreach (ObjectBase * o, it.value()) { - uint id = qHash(o); - ids[id] = o; - o->id_ = id; - } - } - QMapIterator> lit(scene.lights_used); - while (lit.hasNext()) { - lit.next(); - foreach (ObjectBase * o, lit.value()) { - uint id = qHash(o); - ids[id] = o; - aim_ids[id + 1] = o; - o->id_ = id; - } - } - foreach (Camera * o, scene.cameras_used) { - uint id = qHash(o); - ids[id] = o; - aim_ids[id + 1] = o; - o->id_ = id; - } - } -} - - -void RendererSelection::renderSelection(Scene & scene) { - QOpenGLShaderProgram * prog = 0; - QGLView * view = r->view; - MouseController & mc(view->mouse); - if (r->bindShader(Renderer::srSelectionFill, &prog)) { - mc.hov_objects.clear(); - mc.hov_aims.clear(); - id_hover = 0; - if (fbo_selection.queriedPoints() > 0) { - if (fbo_selection.queriedPoints() == 1) { - id_hover = fbo_selection.getPoint(); - ObjectBase * o = ids.value(id_hover); - if (o) - mc.hov_objects << o; - else { - o = aim_ids.value(id_hover); - if (o) - mc.hov_aims << o; - } - //qDebug() << id_hover; - } else { - QVector points = fbo_selection.getPointsByte(); - QSet ids_hover; - foreach (uint i, points) - ids_hover << i; - foreach (uint i, ids_hover) { - ObjectBase * o = ids.value(i); - if (o) mc.hov_objects << o; - o = aim_ids.value(i); - if (o) mc.hov_aims << o; - } - //qDebug() << ids_hover; - } - } - - fbo_selection.bind(); - - fbo_selection.setWriteBuffers(); - glEnableDepth(); - glClearFramebuffer(QColor(0,0,0,0)); - r->setUniformCamera(prog, view->camera()); - r->renderObjects(scene, rpSolid); - r->renderObjects(scene, rpTransparent); - view->glClear(GL_DEPTH_BUFFER_BIT); - - RendererService & rs(r->rend_service); - rs.drawLights(); - rs.drawCameras(); - rs.drawCurrentHandleObjects(); - - //mouse_rect = fbo_selection.rect(); - if (r->mouse_rect.isNull()) - fbo_selection.queryPoint(0, r->mouse_pos * scale_); - else - fbo_selection.queryPoints(0, QRect(r->mouse_rect.topLeft() * scale_, - r->mouse_rect.size() * scale_)); - - //qDebug() << id_hover; - fbo_selection.bindColorTexture(sbrSrcHover , sbrSrcHover ); - fbo_selection.bindColorTexture(sbrSrcSelect, sbrSrcSelect); - fbo_selection.setWriteBuffers(QVector() << sbrHovered << sbrSelected); - if (!view->hoverHalo_ && !view->selectionHalo_) - glClearFramebuffer(QColor(0,0,0,0), false); - else { - r->bindShader(Renderer::srSelectionHalo, &prog); - r->setUniformHalo(prog, "hover" , view->hoverHaloColor() , view->hoverHaloFillAlpha()); - r->setUniformHalo(prog, "selection", view->selectionHaloColor(), view->selectionHaloFillAlpha()); - prog->setUniformValue("has_hover" , view->hoverHalo_ && (id_hover > 0) ? 1.f : 0.f); - prog->setUniformValue("has_selection", view->selectionHalo_ ? 1.f : 0.f); - prog->setUniformValue("fb_hover" , (int)sbrSrcHover); - prog->setUniformValue("fb_selection", (int)sbrSrcSelect); - prog->setUniformValue("hover_id", QVector4D(float( id_hover & 0xFF) / 255.f, - float((id_hover >> 8 ) & 0xFF) / 255.f, - float((id_hover >> 16) & 0xFF) / 255.f, - float((id_hover >> 24) & 0xFF) / 255.f)); - r->renderQuad(prog, r->quad, view->camera()); - } - - prog = r->shader_fxaa; - if (r->bindShader(prog)) { - r->setUniformCamera(prog, 0, true, fbo_selection.size()); - fbo_selection.bindColorTexture(sbrHovered); - fbo_selection.setWriteBuffer(sbrHoveredFXAA); - r->renderQuad(prog, r->quad, 0, false); - fbo_selection.bindColorTexture(sbrSelected); - fbo_selection.setWriteBuffer(sbrSelectedFXAA); - r->renderQuad(prog, r->quad, 0, false); - } - - fbo_selection.release(); - } -} - - -void RendererSelection::renderSelectionFrame() { - QOpenGLShaderProgram * prog = 0; - if (r->bindShader(Renderer::srSelectionFrame, &prog)) { - QMatrix4x4 mat; - double mrx = r->mouse_rect.x(), mrw = r->mouse_rect.width() , vw = r->view->width(); - double mry = r->mouse_rect.y(), mrh = r->mouse_rect.height(), vh = r->view->height(); - mat.translate(-1. + (mrw + mrx*2) / vw, 1. - (mrh + mry*2) / vh, 0.); - mat.scale(mrw / vw, mrh / vh, 0.); - r->initQuad(sel_frame, mat); - prog->setUniformValue("size", QVector2D(mrw / vw, mrh / vh)); - prog->setUniformValue("thickness", line_thick_); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - r->renderQuad(prog, sel_frame); - glDisable(GL_BLEND); - } -} - - -void RendererSelection::drawSelection(Framebuffer & fbo_out, int index_out) { - QOpenGLShaderProgram * prog = 0; - if (r->bindShader(Renderer::srSelectionApply, &prog)) { - fbo_selection.bindColorTextures(); - fbo_out.bindColorTexture(index_out); - prog->setUniformValue("fb_out" , 0); - prog->setUniformValue("fb_hover" , (int)sbrHoveredFXAA ); - prog->setUniformValue("fb_select", (int)sbrSelectedFXAA); - r->renderQuad(prog, r->quad, r->view->camera()); - if (!r->mouse_rect.isNull()) { - renderSelectionFrame(); - } - } -} diff --git a/qglengine/renderer_selection.h b/qglengine/renderer_selection.h deleted file mode 100644 index 9062a18..0000000 --- a/qglengine/renderer_selection.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - QGL RendererSelection - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef RENDERER_SELECTION_H -#define RENDERER_SELECTION_H - -#include "renderer_service.h" -#include - - -class RendererSelection { - friend class QGLView; - friend class MouseController; - friend class Renderer; - friend class RendererService; - -public: - RendererSelection(Renderer * r_); - virtual ~RendererSelection(); - - void init(int width, int height); - void resize(int width, int height); - -protected: - enum SelectionBufferRole { - sbrSrcHover, - sbrSrcSelect, - sbrHovered, - sbrSelected, - sbrHoveredFXAA, - sbrSelectedFXAA, - }; - - void generateObjectsID(Scene & scene); - void renderSelection(Scene & scene); - void renderSelectionFrame(); - void drawSelection(Framebuffer & fbo_out, int index_out = 0); - -private: - Renderer * r; - - Framebuffer fbo_selection; - Mesh * sel_frame; - float line_thick_, scale_; - - QVector cur_selections_; - QHash ids; - QHash aim_ids; - uint id_hover; - -}; - -#endif // RENDERER_selection_H diff --git a/qglengine/renderer_service.cpp b/qglengine/renderer_service.cpp deleted file mode 100644 index e71a183..0000000 --- a/qglengine/renderer_service.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/* - QGL RendererService - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "renderer_service.h" -#include "renderer.h" -#include "qglview.h" -#include "glmesh.h" -#include - -using namespace QGLEngineShaders; - - -RendererService::RendererService(Renderer * r_): r(r_) { - line_width = 1; - current_action = haNoAction; - current_handle = 0; - mat_xyz.resize(3); mat_ms2.resize(3); - color_xyz.resize(3); color_ms2.resize(3); - const QVector3D _rot [3] = {QVector3D(0,1,0), QVector3D(-1,0,0), QVector3D(0, 0,1)}; - const QVector3D _rot2[3] = {QVector3D(0,0,0), QVector3D( 1,0,0), QVector3D(0,-1,0)}; - for (int i = 0; i < 3; ++i) { - QMatrix4x4 m; - m.rotate(90., _rot[i]); - mat_xyz[i] = m; - m.setToIdentity(); - if (!_rot2[i].isNull()) - m.rotate(90., _rot2[i]); - mat_ms2[i] = m; - color_xyz[i] = color_ms2[i] = QVector4D(0,0,0,0.8); - color_xyz[i][i] = 1.; - } - color_ms2[0] = (color_xyz[0] + color_xyz[1]) / 2.; - color_ms2[1] = (color_xyz[0] + color_xyz[2]) / 2.; - color_ms2[2] = (color_xyz[1] + color_xyz[2]) / 2.; - axis_camera = new Camera(); - axis_camera->setAim(QVector3D()); - axis_camera->setFOV(45.); - axis_mesh = Primitive::arrow(12); - size_vp_scale = size_full_scale = 1.; - - box_mesh = Primitive::cube(0.8, 0.8, 0.8); - box_mesh_f = Primitive::cubeFrame(0.8, 0.8, 0.8); - omni_mesh = Primitive::ellipsoid(2, 1, 0.5); - omni_mesh_f = Primitive::ellipsoidFrame(2, 1, 0.5); - omni_mesh ->scalePoints(1.5); - omni_mesh_f ->scalePoints(1.5); - cone_mesh = Primitive::cone(8, 0.5, 1.); - cone_mesh_f = Primitive::coneFrame(8, 0.5, 1.); - QMatrix4x4 mat; - mat.translate(0,0,-1); - cone_mesh ->transformPoints(mat); - cone_mesh_f->transformPoints(mat); - cone_mesh_f->scalePoints(1.5); - - box_mesh ->scalePoints(1.3); - omni_mesh ->scalePoints(1.3); - cone_mesh ->translatePoints(0,0,0.5); - cone_mesh ->scalePoints(1.4); - cone_mesh ->translatePoints(0,0,-0.5); - cone_mesh ->scalePoints(1.5); - - camera_mesh = Primitive::cube(1.2, 1.2, 1.2); - mat.translate(0,0,-0.5); - Mesh * m = Primitive::cone(6, 0.6, 1.); - m->scalePoints(1.4); - m->transformPoints(mat); - camera_mesh->append(m); - camera_mesh_f = Primitive::cubeFrame(1., 1., 1.); - camera_mesh_f->append(Primitive::cubeFrame(0.5, 0.5, 0.5)); - m = Primitive::coneFrame(6, 0.6, 1.); - m->transformPoints(mat); - camera_mesh_f->append(m); - - line_spot_f = Primitive::lineFrame(QVector3D(), QVector3D(0, 0, -1)); - line_camera_f = Primitive::lineFrame(QVector3D(), QVector3D(0, 0, -1)); - - handle_move_mesh = Primitive::arrow(12, 0.06); - handle_ms_2_mesh = Primitive::torus(8, 12, 0.5, 0.02, 90); - m = Primitive::disc(8, 0.5, 90); - handle_ms_2_mesh->append(m); - m->flipNormals(); - handle_ms_2_mesh->append(m); - delete m; - - handle_rotate_mesh = Primitive::arrow(12, 0.03); - m = Primitive::torus(30, 12, 0.5, 0.06); - m->translatePoints(QVector3D(0., 0., 0.75)); - handle_rotate_mesh->append(m); - delete m; - - handle_scale_mesh = Primitive::cylinder(12, 0.03, 0.85); - m = Primitive::ellipsoid(12, 12, 0.15); - m->translatePoints(QVector3D(0., 0., 0.85)); - handle_scale_mesh->append(m); - delete m; - handle_scale_3_mesh = Primitive::ellipsoid(12, 12, 0.2); - - handle_move_mesh ->scalePoints(7.5); - handle_ms_2_mesh ->scalePoints(7.5); - handle_rotate_mesh ->scalePoints(7.5); - handle_scale_mesh ->scalePoints(7.5); - handle_scale_3_mesh->scalePoints(7.5); -} - - -RendererService::~RendererService() { - delete box_mesh; - delete box_mesh_f; - delete omni_mesh; - delete omni_mesh_f; - delete cone_mesh; - delete cone_mesh_f; - delete camera_mesh; - delete camera_mesh_f; - delete line_spot_f; - delete line_camera_f; - delete axis_camera; - delete axis_mesh; - delete handle_move_mesh; - delete handle_ms_2_mesh; - delete handle_rotate_mesh; - delete handle_scale_mesh; - delete handle_scale_3_mesh; -} - - -void RendererService::init(int width, int height) { - fillXYZObjects(); - axis_mesh->loadObjects(r->view, cur_objects); - resize(width, height); -} - - -void RendererService::resize(int width, int height) { - axis_viewport = preferredIconSize(10.); - line_width = lineThickness(); - size_vp_scale = 25. * appScale() / qMax(qMin(width, height), 1); - //qDebug() << axis_viewport; -} - - -QMatrix4x4 RendererService::invariantSizeMatrix(QVector3D p, double * ret_scale) { - QVector4D pos = QVector4D(p, 1.); - double dist = -(v_mat * pos).z(); - QMatrix4x4 m; - m.translate(pos.toVector3D()); - m.scale(dist * size_full_scale); - if (ret_scale) *ret_scale = dist * size_full_scale; - return m; -} - - -QMatrix4x4 RendererService::parentRotationMatrix(ObjectBase * o, bool self_rotation) { - QMatrix4x4 ret; - if (!o) return ret; - QMatrix4x4 pmat; - if (o->parent()) { - pmat = o->parent()->transform().matrixRotate(); - } - if (self_rotation) { - ret *= o->transform().matrixRotate(); - } - ret = pmat * ret; - return ret; -} - - -void RendererService::fillXYZObjects() { - cur_objects.resize(3); - for (int i = 0; i < 3; ++i) { - cur_objects[i].color = color_xyz[i]; - mat_xyz[i].transposed().copyDataTo(cur_objects[i].modelmatrix); - } -} - - -void RendererService::fillOmniObjects() { - QList ll = r->view->scene()->lights_used.value(Light::Omni); - Object o; - cur_objects.clear(); - foreach (Light * l, ll) { - QMatrix4x4 m = invariantSizeMatrix(l->worldPos()); - m.transposed().copyDataTo(o.modelmatrix); - o.object_id = l->id_; - cur_objects << o; - } -} - - -void RendererService::fillAimedObjects(const ObjectBaseList & objects, Mesh * line_mesh) { - Object o; - cur_objects.clear(); - cur_aims.clear(); - QVector & lv (line_mesh->vertices ()); - QVector & ln (line_mesh->normals ()); - QVector & lt (line_mesh->texcoords ()); - QVector< Vector2i> & lind(line_mesh->indicesLines()); - lv.clear(); - foreach (ObjectBase * go, objects) { - AimedObject * ao = (AimedObject *)go; - QMatrix4x4 m; - m = invariantSizeMatrix(ao->worldPos()) * parentRotationMatrix(ao); - m.transposed().copyDataTo(o.modelmatrix); - o.object_id = ao->id_; - cur_objects << o; - - lv << ao->worldPos() << ao->worldAim(); - - m = invariantSizeMatrix(ao->worldAim()); - m.transposed().copyDataTo(o.modelmatrix); - o.object_id = ao->id_ + 1; - cur_aims << o; - } - ln.resize(lv.size()); - lt.resize(lv.size()); - lind.resize(lv.size() / 2); - for (int i = 0; i < lind.size(); ++i) { - lind[i] = Vector2i(i*2, i*2 + 1); - } -} - - -void RendererService::fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count) { - QMatrix4x4 m = invariantSizeMatrix(center) * add_mat; - cur_objects.resize(count); - for (int i = 0; i < count; ++i) { - cur_objects[i].color = colors[i]; - QMatrix4x4 omat = m * mats[i]; - cur_objects[i].object_id = ids[i]; - if (current_handle.testFlag(ids[i])) { - cur_objects[i].color = QVector4D(0,1,1,1); - } - omat.transposed().copyDataTo(cur_objects[i].modelmatrix); - } -} - - -bool RendererService::calculateCenter() { - ObjectBaseList sol = r->view->scene()->selectedObjects(true); - if (sol.isEmpty()) return false; - selection_center = sol[0]->worldPos(); - if (sol.size() > 1) { - Box3D bb; - foreach (ObjectBase * o, sol) { - o->calculateBoundingBox(); - bb |= o->boundingBox(); - } - if (!bb.isEmpty()) { - selection_center = bb.center(); - } - } - axis_mat = QMatrix4x4(); - if ((sol.size() == 1)) { - if (current_action == haMove) { - if (sol[0]->selected_aim) - selection_center = ((AimedObject*)sol[0])->worldAim(); - } else { - axis_mat = parentRotationMatrix(sol[0]); - } - } - return true; -} - - -void RendererService::drawCurrentHandleObjects() { - if (current_action == haNoAction) return; - if (calculateCenter()) { - HandleMesh ids[3]; - switch (current_action) { - case haMove : ids[0] = hmMoveX ; ids[1] = hmMoveY ; ids[2] = hmMoveZ ; break; - case haRotate: ids[0] = hmRotateX; ids[1] = hmRotateY; ids[2] = hmRotateZ; break; - case haScale : ids[0] = hmScaleX ; ids[1] = hmScaleY ; ids[2] = hmScaleZ ; break; - default: break; - } - fillHandleObjects(selection_center, ids, mat_xyz, color_xyz, axis_mat); - Mesh * hm = currentHandleMesh(); - QVector sel; - sel.fill(0, 3); - if (hm) { - hm->loadObjects(r->view, cur_objects); - hm->loadSelections(r->view, sel); - hm->draw(r->view, 3); - } - if (current_action == haMove || current_action == haScale) { - switch (current_action) { - case haMove : ids[0] = hmMoveXY ; ids[1] = hmMoveXZ ; ids[2] = hmMoveYZ ; break; - case haScale : ids[0] = hmScaleXY ; ids[1] = hmScaleXZ ; ids[2] = hmScaleYZ ; break; - default: break; - } - hm = handle_ms_2_mesh; - fillHandleObjects(selection_center, ids, mat_ms2, color_ms2, axis_mat); - hm->loadObjects(r->view, cur_objects); - hm->loadSelections(r->view, sel); - hm->draw(r->view, 3); - if (current_action == haScale) { - hm = handle_scale_3_mesh; - QVector mv; mv.resize(1); - QVector cv; cv.fill(QVector4D(1, 1, 0.5, 1), 1); - ids[0] = hmMaxScale; - fillHandleObjects(selection_center, ids, mv, cv, axis_mat, 1); - hm->loadObjects(r->view, cur_objects); - hm->loadSelections(r->view, sel); - hm->draw(r->view, 1); - } - } - } -} - - -void RendererService::drawLights() { - QGLView * v = r->view; - RendererSelection & rs(r->rend_selection); - - fillOmniObjects(); - omni_mesh->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, lights2objectList(v->scene_->lights_used.value(Light::Omni))); - omni_mesh->loadSelections(v, rs.cur_selections_); - omni_mesh->draw(v, cur_objects.size()); - - ObjectBaseList ll = lights2objectList(r->view->scene()->lights_used.value(Light::Cone)); - fillAimedObjects(ll, line_spot_f); - cone_mesh->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, ll); - cone_mesh->loadSelections(v, rs.cur_selections_); - cone_mesh->draw(v, cur_objects.size()); - box_mesh->loadObjects(v, cur_aims); - box_mesh->loadSelections(v, rs.cur_selections_); - box_mesh->draw(v, cur_aims.size()); - -} - - -void RendererService::drawLightsFrame(QColor color) { - QGLView * v = r->view; - RendererSelection & rs(r->rend_selection); - - fillOmniObjects(); - setObjectsColor(cur_objects, color); - omni_mesh_f->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, lights2objectList(v->scene_->lights_used.value(Light::Omni))); - omni_mesh_f->loadSelections(v, rs.cur_selections_); - omni_mesh_f->draw(v, cur_objects.size()); - - ObjectBaseList ll = lights2objectList(r->view->scene()->lights_used.value(Light::Cone)); - fillAimedObjects(ll, line_spot_f); - setObjectsColor(cur_objects, color); - cone_mesh_f->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, ll); - cone_mesh_f->loadSelections(v, rs.cur_selections_); - cone_mesh_f->draw(v, cur_objects.size()); - - setObjectsColor(cur_aims, color); - box_mesh_f->loadObjects(v, cur_aims); - box_mesh_f->loadSelections(v, rs.cur_selections_); - box_mesh_f->draw(v, cur_aims.size()); - -} - - -void RendererService::drawCameras() { - QGLView * v = r->view; - RendererSelection & rs(r->rend_selection); - - ObjectBaseList cl = cameras2objectList(r->view->scene()->cameras_used); - cl.removeOne(r->view->camera()); - fillAimedObjects(cl, line_camera_f); - camera_mesh->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, cl); - camera_mesh->loadSelections(v, rs.cur_selections_); - camera_mesh->draw(v, cur_objects.size()); - box_mesh->loadObjects(v, cur_aims); - box_mesh->loadSelections(v, rs.cur_selections_); - box_mesh->draw(v, cur_aims.size()); - -} - - -void RendererService::drawCamerasFrame(QColor color) { - QGLView * v = r->view; - RendererSelection & rs(r->rend_selection); - - ObjectBaseList cl = cameras2objectList(r->view->scene()->cameras_used); - cl.removeOne(r->view->camera()); - fillAimedObjects(cl, line_camera_f); - setObjectsColor(cur_objects, color); - camera_mesh_f->loadObjects(v, cur_objects); - r->fillSelectionsBuffer(rs.cur_selections_, cl); - camera_mesh_f->loadSelections(v, rs.cur_selections_); - camera_mesh_f->draw(v, cur_objects.size()); - - setObjectsColor(cur_aims, color); - box_mesh_f->loadObjects(v, cur_aims); - box_mesh_f->loadSelections(v, rs.cur_selections_); - box_mesh_f->draw(v, cur_aims.size()); - -} - - -void RendererService::setObjectsColor(QVector & ol, QColor col) { - QVector4D cv = QColor2QVector(col); - for (int i = 0; i < ol.size(); ++i) - ol[i].color = cv; -} - - -void RendererService::renderService() { - QOpenGLShaderProgram * prog = 0; - QOpenGLExtraFunctions * f = r->view; - size_full_scale = tan(r->view->camera()->FOV() / 2. * deg2rad) * size_vp_scale; - v_mat = r->view->camera()->fullViewMatrix(); - f->glEnable(GL_MULTISAMPLE); - glEnableDepth(); - f->glClear(GL_DEPTH_BUFFER_BIT); - glDisable(GL_CULL_FACE); - if (r->bindShader(Renderer::srServiceFrame, &prog)) { - prog->setUniformValue("qgl_ProjMatrix", r->view->camera()->projectionMatrix(r->view->aspect)); - - /// lights - r->setUniformCamera(prog, r->view->camera()); - - prog->setUniformValue("line_width", 2.f); - prog->setUniformValue("z_offset", 0.f); - drawLightsFrame(Qt::white); - drawCamerasFrame(Qt::white); - prog->setUniformValue("line_width", 1.f); - prog->setUniformValue("z_offset", -1.E-2f); - drawLightsFrame(Qt::black); - drawCamerasFrame(Qt::black); - - } - if (r->bindShader(Renderer::srServiceLine, &prog)) { - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - r->setUniformCamera(prog, r->view->camera()); - line_object.color = QColor2QVector(Qt::white); - line_spot_f ->loadObject(f, line_object); - line_camera_f->loadObject(f, line_object); - line_spot_f ->draw(f, 1); - line_camera_f->draw(f, 1); - //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - glEnable(GL_CULL_FACE); - if (r->bindShader(Renderer::srServiceFill, &prog)) { - r->setUniformCamera(prog, r->view->camera()); - - /// handles - f->glEnable(GL_BLEND); - f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - drawCurrentHandleObjects(); - f->glDisable(GL_BLEND); - - /// axis - f->glViewport(0, 0, axis_viewport.width(), axis_viewport.height()); - axis_camera->setPos(-r->view->camera()->direction() * 3.); - axis_camera->setAim(QVector3D()); - axis_camera->setRotation(r->view->camera()->rotation()); - r->setUniformCamera(prog, axis_camera, true, axis_viewport); - axis_mesh->draw(f, 3); - f->glViewport(0, 0, r->view->width(), r->view->height()); - - } - f->glDisable(GL_MULTISAMPLE); -} - - -Mesh * RendererService::currentHandleMesh() { - switch (current_action) { - case haMove : return handle_move_mesh; - case haRotate: return handle_rotate_mesh; - case haScale : return handle_scale_mesh; - default: break; - } - return 0; -} diff --git a/qglengine/renderer_service.h b/qglengine/renderer_service.h deleted file mode 100644 index c0de71f..0000000 --- a/qglengine/renderer_service.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - QGL RendererService - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef RENDERER_SERVICE_H -#define RENDERER_SERVICE_H - -#include "glframebuffer.h" -#include "glshaders_types.h" -#include - - -class RendererService { - friend class QGLView; - friend class MouseController; - friend class Renderer; - friend class RendererSelection; - -public: - RendererService(Renderer * r_); - virtual ~RendererService(); - - enum HandleAction { - haNoAction, - haMove, - haRotate, - haScale, - }; - - enum HandleMesh { - hmMoveX = 0x01, - hmMoveY = 0x02, - hmMoveZ = 0x04, - hmMoveXY = hmMoveX | hmMoveY, - hmMoveXZ = hmMoveX | hmMoveZ, - hmMoveYZ = hmMoveY | hmMoveZ, - hmMaxMove = hmMoveX | hmMoveY | hmMoveZ, - hmRotateX = 0x08, - hmRotateY = 0x10, - hmRotateZ = 0x20, - hmMaxRotate = hmRotateX | hmRotateY | hmRotateZ, - hmScaleX = 0x40, - hmScaleY = 0x80, - hmScaleZ = 0x100, - hmScaleXY = hmScaleX | hmScaleY, - hmScaleXZ = hmScaleX | hmScaleZ, - hmScaleYZ = hmScaleY | hmScaleZ, - hmMaxScale = hmScaleX | hmScaleY | hmScaleZ, - }; - - void init(int width, int height); - void resize(int width, int height); - - QMatrix4x4 invariantSizeMatrix(QVector3D p, double * ret_scale = 0); - QMatrix4x4 parentRotationMatrix(ObjectBase * o, bool self_rotation = true); - void fillXYZObjects(); - void fillOmniObjects(); - void fillAimedObjects(const ObjectBaseList & objects, Mesh * line_mesh); - void fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count = 3); - bool calculateCenter(); - void drawCurrentHandleObjects(); - void drawLights(); - void drawLightsFrame(QColor color); - void drawCameras(); - void drawCamerasFrame(QColor color); - void setObjectsColor(QVector & ol, QColor col); - void renderService(); - void setCurrentAction(HandleAction ha) {current_action = ha;} - Mesh * currentHandleMesh(); - -private: - Renderer * r; - - Mesh * axis_mesh, * handle_move_mesh, * handle_rotate_mesh, * handle_scale_mesh; - Mesh * handle_ms_2_mesh, * handle_scale_3_mesh; - Mesh * box_mesh_f, * omni_mesh_f, * cone_mesh_f, * camera_mesh_f; - Mesh * box_mesh, * omni_mesh, * cone_mesh, * camera_mesh; - Mesh * line_spot_f, * line_camera_f; - QMatrix4x4 v_mat, axis_mat; - QVector3D selection_center; - QVector mat_xyz, mat_ms2; - QVector color_xyz, color_ms2; - QVector cur_objects, cur_aims; - QGLEngineShaders::Object line_object; - Camera * axis_camera; - QSize axis_viewport; - HandleAction current_action; - QFlags current_handle; - int line_width; - double size_vp_scale, size_full_scale; - -}; - -#endif // RENDERER_SERVICE_H diff --git a/qglengine/shaders.qrc b/qglengine/shaders.qrc deleted file mode 100644 index ad92bf9..0000000 --- a/qglengine/shaders.qrc +++ /dev/null @@ -1,19 +0,0 @@ - - - shaders/ds_final.glsl - shaders/ds_geom.glsl - shaders/ds_light.glsl - shaders/ds_tonemap.glsl - shaders/fxaa.frag - shaders/fxaa.vert - shaders/fxaa_v3.h - shaders/selection.glsl - shaders/selection_apply.glsl - shaders/selection_frame.glsl - shaders/selection_halo.glsl - shaders/service_fill.glsl - shaders/service_frame.glsl - shaders/service_line.glsl - shaders/sum.glsl - - diff --git a/qglengine/shaders/ds_final.glsl b/qglengine/shaders/ds_final.glsl deleted file mode 100644 index 73aecb6..0000000 --- a/qglengine/shaders/ds_final.glsl +++ /dev/null @@ -1,22 +0,0 @@ -// vert // - -void main(void) { - gl_Position = qgl_ftransform(); -} - - -// frag // - -uniform sampler2D tex_g1, tex_s_0, tex_s_1, tex_t_0, tex_t_1; - -void main(void) { - ivec2 tc = ivec2(gl_FragCoord.xy); - vec4 vs0 = texelFetch(tex_s_0, tc, 0); - vec4 vs1 = texelFetch(tex_s_1, tc, 0); - vec3 sr = vs0.rgb + vs1.rgb; - vec4 vt0 = texelFetch(tex_t_0, tc, 0); - vec4 vt1 = texelFetch(tex_t_1, tc, 0); - vec3 tr = vt0.rgb + vt1.rgb; - float alpha = (vt0.a + vt1.a) / 2; - qgl_FragColor.rgb = mix(sr, tr, alpha); -} diff --git a/qglengine/shaders/ds_geom.glsl b/qglengine/shaders/ds_geom.glsl deleted file mode 100644 index 617a6ee..0000000 --- a/qglengine/shaders/ds_geom.glsl +++ /dev/null @@ -1,71 +0,0 @@ -// vert // - -out vec3 geom_normal; -out mat3 TBN; -out vec4 object_color; - -void main(void) { - qgl_MaterialIndex = qgl_Material; - qgl_FragTexture = qgl_Texture; - gl_Position = qgl_ftransform(); - - geom_normal = normalize(qgl_Normal * qgl_getNormalMatrix()); - TBN = qgl_getTangentMatrix() * mat3(qgl_Tangent, qgl_Bitangent, qgl_Normal); - object_color = qgl_ObjectColor; -} - - -// frag // - -in vec3 geom_normal; -in mat3 TBN; -in vec4 object_color; - -uniform vec2 dt; -uniform float z_near; - -const vec3 luma = vec3(0.299, 0.587, 0.114); -const float _pe = 2.4e-7; - -void main(void) { - vec2 tc = qgl_FragTexture.xy; - - vec4 diffuse = qgl_materialTexture(QGL_MAP_DIFFUSE, tc, vec4(0)) * object_color; - diffuse.rgb *= qgl_material[qgl_MaterialIndex].color_diffuse.rgb; - diffuse.a *= (1.f - qgl_material[qgl_MaterialIndex].transparency); - - vec3 normal, dn; - dn = qgl_materialTexture(QGL_MAP_NORMAL, tc, -vec4(0.5, 0.5, 1., 0.)).xyz; - //dn.y = -dn.y; - float dn_sl = length(dn); - dn = TBN * dn; - dn *= dn_sl / (length(dn) + 1E-6); - normal = normalize(geom_normal + dn); - - float metalness = dot(qgl_materialTexture(QGL_MAP_METALNESS, tc, vec4(0)).rgb, luma); - metalness = clamp(metalness, 0, 1); - - float roughness = dot(qgl_materialTexture(QGL_MAP_ROUGHNESS, tc, vec4(0)).rgb, luma); - roughness = clamp(roughness, 0.0001, 0.9999); - - float reflectivity = clamp(qgl_material[qgl_MaterialIndex].reflectivity, 0., 1.); - - vec4 emission = qgl_materialTexture(QGL_MAP_EMISSION, tc, vec4(0)); - emission *= qgl_material[qgl_MaterialIndex].color_emission; - - float height = dot(qgl_materialTexture(QGL_MAP_RELIEF, tc, vec4(0)).rgb, luma); - - float z = gl_FragCoord.z; - z = z + z - 1; - z = ((_pe - 2.) * z_near) / (z + _pe - 1.); // infinite depth - - qgl_FragData[0] = vec4(diffuse .rgba); - qgl_FragData[1] = vec4(normal .xyz, z); - qgl_FragData[2] = vec4(metalness, roughness, reflectivity, 0); - qgl_FragData[3] = vec4(emission.rgb, 0/*bn.x*/); - //qgl_FragData[4] = vec4(speed.xy, bn.yz); - - //ivec2 itc = ivec2(gl_FragCoord.xy); - //qgl_FragData[0].rgb = vec3(dot(n,vec3(0,0,1))); - //qgl_FragData[0].rgb = diffuse.rgb * dot(n,vec3(0,0,1)); -} diff --git a/qglengine/shaders/ds_light.glsl b/qglengine/shaders/ds_light.glsl deleted file mode 100644 index 7f8c132..0000000 --- a/qglengine/shaders/ds_light.glsl +++ /dev/null @@ -1,181 +0,0 @@ -// vert // - -out vec3 view_dir, world_dir; - -uniform vec4 view_corners[4], world_corners[4]; - -void main(void) { - qgl_FragTexture = qgl_Texture; - gl_Position = qgl_ftransform(); - view_dir = view_corners [gl_VertexID].xyz; - world_dir = world_corners[gl_VertexID].xyz; -} - - -// frag // - -in vec3 view_dir, world_dir; - -uniform vec2 dt; -uniform float z_near; -uniform sampler2D tex_coeffs[2]; -uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4; -uniform samplerCube tex_env; -uniform int lights_start, lights_count; - -uniform vec4 fog_color = vec4(0.5, 0.5, 0.5, 1); -uniform float fog_decay = 10, fog_density = 0; -uniform mat3 view_mat; - -const vec3 luma = vec3(0.299, 0.587, 0.114); -const float _min_rough = 1.e-8, max_lod = 8; - -vec4 pos, lpos, shp; -vec3 li, si, ldir, halfV, bn, bn2, lwdir; -//vec3 vds, vds2; -float rough_diff, rough_spec, dist, NdotL, NdotH, spot, ldist, diff, spec, sdist, shadow; - -void calcLight(in int index, in vec3 n, in vec3 v) { - lpos = qgl_light_position[index].position; - ldir = lpos.xyz - (pos.xyz * lpos.w); - ldist = length(ldir); - ldir = normalize(ldir); - //ldir = vec3(0,0,1); - halfV = normalize(ldir + v); - NdotL = max(dot(n, ldir), 1E-8); - NdotH = max(dot(n, halfV), 1E-8); - spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w; -#ifdef SPOT - float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.); - spot *= scos * step(qgl_light_parameter[index].angles.w, scos); - spot *= smoothstep(qgl_light_parameter[index].angles.w, qgl_light_parameter[index].angles.y, scos); - /*//lwdir = mat3(mat_viewi) * qgl_Light[index].direction.xyz; - //bn = normalize(cross(lwdir, vec3(1, 0, 0))); - //bn2 = normalize(cross(lwdir, bn)); - float ds = ldist/200.;//max(abs(sdist) / 5000, 0.02); - //spot *= clamp(1. - sdist, 0, 1); - vds = ds * bn.xyz; - vds2 = ds * bn2.xyz; - float shadow = getShadow(index, pos.xyz, vec3(0)) * 3.; - shadow += getShadow(index, pos.xyz, vds ) * 2.; - shadow += getShadow(index, pos.xyz, - vds ) * 2.; - shadow += getShadow(index, pos.xyz, - vds2 ) * 2.; - shadow += getShadow(index, pos.xyz, + vds2 ) * 2.; - //shadow += getShadow(index, pos.xyz, vds - vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, vds + vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, - vds - vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, - vds + vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, vds + vds ); - //shadow += getShadow(index, pos.xyz, - vds - vds ); - //shadow += getShadow(index, pos.xyz, - vds2 - vds2); - //shadow += getShadow(index, pos.xyz, + vds2 + vds2); - //shadow += getShadow(index, pos.xyz, vds + vds - vds2 ); - //shadow += getShadow(index, pos.xyz, - vds - vds - vds2 ); - //shadow += getShadow(index, pos.xyz, vds + vds + vds2 ); - //shadow += getShadow(index, pos.xyz, - vds - vds + vds2 ); - //shadow += getShadow(index, pos.xyz, vds - vds2 - vds2); - //shadow += getShadow(index, pos.xyz, vds + vds2 + vds2); - //shadow += getShadow(index, pos.xyz, - vds - vds2 - vds2); - //shadow += getShadow(index, pos.xyz, - vds + vds2 + vds2); - //shadow += shadow += getShadow(index, pos.xyz, vds+vds2)*10; - spot *= mix(1., shadow / 11., shadow_on);*/ -#endif - vec3 dist_decay = vec3(1, ldist, ldist*ldist); - spot /= dot(qgl_light_parameter[index].decay_intensity.xyz, dist_decay); - - float NdotLs = NdotL*NdotL; - float NdotHs = NdotH*NdotH; - - float ndlc = (1. - NdotLs) / NdotLs; - diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc)); - //diff = texture(tex_coeffs[0], vec2(roughness, (NdotLs))).r; - li += spot * diff * qgl_light_parameter[index].color.rgb; - - ndlc = (1. - NdotHs) / NdotHs; - float der = NdotHs * (rough_spec + ndlc); - spec = rough_spec / (der*der) / 3.1416; - //spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r; - si += spot * spec * qgl_light_parameter[index].color.rgb; -} - - - -float GeometrySchlickGGX(float NdotV, float roughness) { - float a = roughness; - float k = (a * a) / 2.0; - float nom = NdotV; - float denom = NdotV * (1.0 - k) + k; - return nom / denom; -} -// ---------------------------------------------------------------------------- -float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { - float NdotV = max(dot(N, V), 0.0); - float NdotL = max(dot(N, L), 0.0); - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); - return ggx1 * ggx2; -} - - - -void main(void) { - ivec2 tc = ivec2(gl_FragCoord.xy); - vec4 v1 = texelFetch(tex_1, tc, 0); - float z = v1.w; - if (z == 1.) { - discard; - } - pos.w = 1; - pos.xyz = view_dir * z; - vec3 v = normalize(-pos.xyz); - - vec4 v0 = texelFetch(tex_0, tc, 0), - v2 = texelFetch(tex_2, tc, 0), - v3 = texelFetch(tex_3, tc, 0), - v4 = texelFetch(tex_4, tc, 0); - - vec3 diffuse = v0.rgb; - vec3 normal = v1.xyz; - vec3 emission = v3.rgb; - float alpha = v0.a; - float metalness = v2.r; - float roughness = v2.g; - float reflectivity = v2.b; - float NdotV = dot(normal, v); - float roughness3 = roughness*roughness*roughness; - //bn = normalize(vec3(v3.w, v4.zw)); - //bn2 = normalize(cross(n, bn)); - rough_diff = max(roughness, _min_rough); - rough_spec = max(roughness3, _min_rough); - float shlick = clamp(metalness + (1 - metalness) * pow(1 - NdotV, 5), 0, 1); - - li = vec3(0.);//qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity; - si = vec3(0.); - for (int i = 0; i < lights_count; ++i) - calcLight(lights_start + i, normal, v); - si *= shlick; - li *= (1 - shlick); - alpha = min(1, alpha * (1 + shlick)); - - vec2 brdf = texture(tex_coeffs[0], vec2(NdotV*0.99, roughness*0.995)).rg; - float env_spec = shlick * brdf.x + brdf.y; - vec3 spec_col = mix(vec3(1), diffuse, metalness); - vec3 env_dir = view_mat * reflect(-v, normal); - vec3 env_col = textureLod(tex_env, env_dir, sqrt(roughness) * max_lod).rgb * spec_col; - - vec3 res_col = max(vec3(0), li * diffuse + si * spec_col + emission); - res_col = mix(res_col, env_col, env_spec * reflectivity); - - float plen = length(pos.xyz); - float fog = 1 - exp(-plen / fog_decay); - fog = clamp(fog * fog_color.a * fog_density, 0, 1); - res_col = mix(res_col, fog_color.rgb, fog); - - qgl_FragColor = vec4(res_col, alpha); - - //vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y); - //qgl_FragColor.rgb = vec3(shlick * brdf.x + brdf.y); - //qgl_FragColor.rgb = vec3(alpha); - //qgl_FragColor.rgb = vec3(textureLod(tex_env, world_dir, 0).rgb); - //qgl_FragColor.a = 1.; -} diff --git a/qglengine/shaders/ds_tonemap.glsl b/qglengine/shaders/ds_tonemap.glsl deleted file mode 100644 index b9b1f8a..0000000 --- a/qglengine/shaders/ds_tonemap.glsl +++ /dev/null @@ -1,25 +0,0 @@ -// vert // - -void main(void) { - gl_Position = qgl_ftransform(); -} - - -// frag // - -uniform sampler2D tex_0; -uniform float gamma, frame_max; - -const vec3 luma = vec3(0.299, 0.587, 0.114); - -void main(void) { - ivec2 tc = ivec2(gl_FragCoord.xy); - vec4 src = texelFetch(tex_0, tc, 0); - vec3 res = src.rgb; - float l = dot(res, luma) * 0.75; - float g = gamma / frame_max; - res /= l; - l = 1 - exp(-l*g); - res *= l; - qgl_FragColor = vec4(res, dot(res, luma)); -} diff --git a/qglengine/shaders/fxaa.frag b/qglengine/shaders/fxaa.frag deleted file mode 100644 index 5e93037..0000000 --- a/qglengine/shaders/fxaa.frag +++ /dev/null @@ -1,2223 +0,0 @@ -/*============================================================================ - - - NVIDIA FXAA 3.11 by TIMOTHY LOTTES - - ------------------------------------------------------------------------------- -COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. ------------------------------------------------------------------------------- -TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED -*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA -OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR -LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, -OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE -THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - ------------------------------------------------------------------------------- - INTEGRATION CHECKLIST ------------------------------------------------------------------------------- -(1.) -In the shader source, setup defines for the desired configuration. -When providing multiple shaders (for different presets), -simply setup the defines differently in multiple files. -Example, - - #define FXAA_PC 1 - #define FXAA_HLSL_5 1 - #define FXAA_QUALITY__PRESET 12 - -Or, - - #define FXAA_360 1 - -Or, - - #define FXAA_PS3 1 - -Etc. - -(2.) -Then include this file, - - #include "Fxaa3_11.h" - -(3.) -Then call the FXAA pixel shader from within your desired shader. -Look at the FXAA Quality FxaaPixelShader() for docs on inputs. -As for FXAA 3.11 all inputs for all shaders are the same -to enable easy porting between platforms. - - return FxaaPixelShader(...); - -(4.) -Insure pass prior to FXAA outputs RGBL (see next section). -Or use, - - #define FXAA_GREEN_AS_LUMA 1 - -(5.) -Setup engine to provide the following constants -which are used in the FxaaPixelShader() inputs, - - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir - -Look at the FXAA Quality FxaaPixelShader() for docs on inputs. - -(6.) -Have FXAA vertex shader run as a full screen triangle, -and output "pos" and "fxaaConsolePosPos" -such that inputs in the pixel shader provide, - - // {xy} = center of pixel - FxaaFloat2 pos, - - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - FxaaFloat4 fxaaConsolePosPos, - -(7.) -Insure the texture sampler(s) used by FXAA are set to bilinear filtering. - - ------------------------------------------------------------------------------- - INTEGRATION - RGBL AND COLORSPACE ------------------------------------------------------------------------------- -FXAA3 requires RGBL as input unless the following is set, - - #define FXAA_GREEN_AS_LUMA 1 - -In which case the engine uses green in place of luma, -and requires RGB input is in a non-linear colorspace. - -RGB should be LDR (low dynamic range). -Specifically do FXAA after tonemapping. - -RGB data as returned by a texture fetch can be non-linear, -or linear when FXAA_GREEN_AS_LUMA is not set. -Note an "sRGB format" texture counts as linear, -because the result of a texture fetch is linear data. -Regular "RGBA8" textures in the sRGB colorspace are non-linear. - -If FXAA_GREEN_AS_LUMA is not set, -luma must be stored in the alpha channel prior to running FXAA. -This luma should be in a perceptual space (could be gamma 2.0). -Example pass before FXAA where output is gamma 2.0 encoded, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma - return color; - -Another example where output is linear encoded, -say for instance writing to an sRGB formated render target, -where the render target does the conversion back to sRGB after blending, - - color.rgb = ToneMap(color.rgb); // linear color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma - return color; - -Getting luma correct is required for the algorithm to work correctly. - - ------------------------------------------------------------------------------- - BEING LINEARLY CORRECT? ------------------------------------------------------------------------------- -Applying FXAA to a framebuffer with linear RGB color will look worse. -This is very counter intuitive, but happends to be true in this case. -The reason is because dithering artifacts will be more visiable -in a linear colorspace. - - ------------------------------------------------------------------------------- - COMPLEX INTEGRATION ------------------------------------------------------------------------------- -Q. What if the engine is blending into RGB before wanting to run FXAA? - -A. In the last opaque pass prior to FXAA, - have the pass write out luma into alpha. - Then blend into RGB only. - FXAA should be able to run ok - assuming the blending pass did not any add aliasing. - This should be the common case for particles and common blending passes. - -A. Or use FXAA_GREEN_AS_LUMA. - -============================================================================*/ - -/*============================================================================ - - INTEGRATION KNOBS - -============================================================================*/ -// -// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). -// FXAA_360_OPT is a prototype for the new optimized 360 version. -// -// 1 = Use API. -// 0 = Don't use API. -// -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PS3 - #define FXAA_PS3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360 - #define FXAA_360 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360_OPT - #define FXAA_360_OPT 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_PC - // - // FXAA Quality - // The high quality PC algorithm. - // - #define FXAA_PC 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PC_CONSOLE - // - // The console algorithm for PC is included - // for developers targeting really low spec machines. - // Likely better to just run FXAA_PC, and use a really low preset. - // - #define FXAA_PC_CONSOLE 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_120 - #define FXAA_GLSL_120 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_130 - #define FXAA_GLSL_130 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_3 - #define FXAA_HLSL_3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_4 - #define FXAA_HLSL_4 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_5 - #define FXAA_HLSL_5 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_GREEN_AS_LUMA - // - // For those using non-linear color, - // and either not able to get luma in alpha, or not wanting to, - // this enables FXAA to run using green as a proxy for luma. - // So with this enabled, no need to pack luma in alpha. - // - // This will turn off AA on anything which lacks some amount of green. - // Pure red and blue or combination of only R and B, will get no AA. - // - // Might want to lower the settings for both, - // fxaaConsoleEdgeThresholdMin - // fxaaQualityEdgeThresholdMin - // In order to insure AA does not get turned off on colors - // which contain a minor amount of green. - // - // 1 = On. - // 0 = Off. - // - #define FXAA_GREEN_AS_LUMA 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_EARLY_EXIT - // - // Controls algorithm's early exit path. - // On PS3 turning this ON adds 2 cycles to the shader. - // On 360 turning this OFF adds 10ths of a millisecond to the shader. - // Turning this off on console will result in a more blurry image. - // So this defaults to on. - // - // 1 = On. - // 0 = Off. - // - #define FXAA_EARLY_EXIT 1 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_DISCARD - // - // Only valid for PC OpenGL currently. - // Probably will not work when FXAA_GREEN_AS_LUMA = 1. - // - // 1 = Use discard on pixels which don't need AA. - // For APIs which enable concurrent TEX+ROP from same surface. - // 0 = Return unchanged color on pixels which don't need AA. - // - #define FXAA_DISCARD 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_FAST_PIXEL_OFFSET - // - // Used for GLSL 120 only. - // - // 1 = GL API supports fast pixel offsets - // 0 = do not use fast pixel offsets - // - #ifdef GL_EXT_gpu_shader4 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifndef FXAA_FAST_PIXEL_OFFSET - #define FXAA_FAST_PIXEL_OFFSET 0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GATHER4_ALPHA - // - // 1 = API supports gather4 on alpha channel. - // 0 = API does not support gather4 on alpha channel. - // - #if (FXAA_HLSL_5 == 1) - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifndef FXAA_GATHER4_ALPHA - #define FXAA_GATHER4_ALPHA 0 - #endif -#endif - -/*============================================================================ - FXAA CONSOLE PS3 - TUNING KNOBS -============================================================================*/ -#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS - // - // Consoles the sharpness of edges on PS3 only. - // Non-PS3 tuning is done with shader input. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 4 and 8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // - // 8.0 is sharper - // 4.0 is softer - // 2.0 is really soft (good for vector graphics inputs) - // - #if 1 - #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 - #endif - #if 0 - #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 - #endif - #if 0 - #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD - // - // Only effects PS3. - // Non-PS3 tuning is done with shader input. - // - // The minimum amount of local contrast required to apply algorithm. - // The console setting has a different mapping than the quality setting. - // - // This only applies when FXAA_EARLY_EXIT is 1. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 0.25 and 0.125. - // These options use the shaders ability to a free *|/ by 2|4|8. - // - // 0.125 leaves less aliasing, but is softer - // 0.25 leaves more aliasing, and is sharper - // - #if 1 - #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 - #else - #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 - #endif -#endif - -/*============================================================================ - FXAA QUALITY - TUNING KNOBS ------------------------------------------------------------------------------- -NOTE the other tuning knobs are now in the shader function inputs! -============================================================================*/ -#ifndef FXAA_QUALITY__PRESET - // - // Choose the quality preset. - // This needs to be compiled into the shader as it effects code. - // Best option to include multiple presets is to - // in each shader define the preset, then include this file. - // - // OPTIONS - // ----------------------------------------------------------------------- - // 10 to 15 - default medium dither (10=fastest, 15=highest quality) - // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) - // 39 - no dither, very expensive - // - // NOTES - // ----------------------------------------------------------------------- - // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) - // 13 = about same speed as FXAA 3.9 and better than 12 - // 23 = closest to FXAA 3.9 visually and performance wise - // _ = the lowest digit is directly related to performance - // _ = the highest digit is directly related to style - // - #define FXAA_QUALITY__PRESET 12 -#endif - - -/*============================================================================ - - FXAA QUALITY - PRESETS - -============================================================================*/ - -/*============================================================================ - FXAA QUALITY - MEDIUM DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 10) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 3.0 - #define FXAA_QUALITY__P2 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 11) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 3.0 - #define FXAA_QUALITY__P3 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 12) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 4.0 - #define FXAA_QUALITY__P4 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 13) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 4.0 - #define FXAA_QUALITY__P5 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 14) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 4.0 - #define FXAA_QUALITY__P6 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 15) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 12.0 -#endif - -/*============================================================================ - FXAA QUALITY - LOW DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 20) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 2.0 - #define FXAA_QUALITY__P2 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 21) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 22) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 23) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 24) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 3.0 - #define FXAA_QUALITY__P6 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 25) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 26) - #define FXAA_QUALITY__PS 9 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 4.0 - #define FXAA_QUALITY__P8 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 27) - #define FXAA_QUALITY__PS 10 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 4.0 - #define FXAA_QUALITY__P9 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 28) - #define FXAA_QUALITY__PS 11 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 4.0 - #define FXAA_QUALITY__P10 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 29) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 -#endif - -/*============================================================================ - FXAA QUALITY - EXTREME QUALITY -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 39) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.0 - #define FXAA_QUALITY__P2 1.0 - #define FXAA_QUALITY__P3 1.0 - #define FXAA_QUALITY__P4 1.0 - #define FXAA_QUALITY__P5 1.5 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 -#endif - - - -/*============================================================================ - - API PORTING - -============================================================================*/ -#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) - #define FxaaBool bool - #define FxaaDiscard discard - #define FxaaFloat float - #define FxaaFloat2 vec2 - #define FxaaFloat3 vec3 - #define FxaaFloat4 vec4 - #define FxaaHalf float - #define FxaaHalf2 vec2 - #define FxaaHalf3 vec3 - #define FxaaHalf4 vec4 - #define FxaaInt2 ivec2 - #define FxaaSat(x) clamp(x, 0.0, 1.0) - #define FxaaTex sampler2D -#else - #define FxaaBool bool - #define FxaaDiscard clip(-1) - #define FxaaFloat float - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaHalf half - #define FxaaHalf2 half2 - #define FxaaHalf3 half3 - #define FxaaHalf4 half4 - #define FxaaSat(x) saturate(x) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_GLSL_120 == 1) - // Requires, - // #version 120 - // And at least, - // #extension GL_EXT_gpu_shader4 : enable - // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) - #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) - #if (FXAA_FAST_PIXEL_OFFSET == 1) - #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) - #else - #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) - #endif - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) - #define FxaaTexGreen4(t, p) textureGather(t, p, 1) - #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_GLSL_130 == 1) - // Requires "#version 130" or better - #define FxaaTexTop(t, p) textureLod(t, p, 0.0) - #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) - #define FxaaTexGreen4(t, p) textureGather(t, p, 1) - #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) - #define FxaaInt2 float2 - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) - #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_4 == 1) - #define FxaaInt2 int2 - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_5 == 1) - #define FxaaInt2 int2 - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) - #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) - #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) - #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) - #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) -#endif - - -/*============================================================================ - GREEN AS LUMA OPTION SUPPORT FUNCTION -============================================================================*/ -#if (FXAA_GREEN_AS_LUMA == 0) - //FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } - FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return dot(rgba.rgb, FxaaFloat3(0.299, 0.587, 0.114)); } -#else - FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } -#endif - - - - -/*============================================================================ - - FXAA3 QUALITY - PC - -============================================================================*/ -#if (FXAA_PC == 1) -/*--------------------------------------------------------------------------*/ -FxaaFloat4 FxaaPixelShader( - // - // Use noperspective interpolation here (turn off perspective interpolation). - // {xy} = center of pixel - FxaaFloat2 pos, - // - // Used only for FXAA Console, and not used on the 360 version. - // Use noperspective interpolation here (turn off perspective interpolation). - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - FxaaFloat4 fxaaConsolePosPos, - // - // Input color texture. - // {rgb_} = color in linear or perceptual color space - // if (FXAA_GREEN_AS_LUMA == 0) - // {___a} = luma in perceptual color space (not linear) - FxaaTex tex, - // - // Only used on the optimized 360 version of FXAA Console. - // For everything but 360, just use the same input here as for "tex". - // For 360, same texture, just alias with a 2nd sampler. - // This sampler needs to have an exponent bias of -1. - FxaaTex fxaaConsole360TexExpBiasNegOne, - // - // Only used on the optimized 360 version of FXAA Console. - // For everything but 360, just use the same input here as for "tex". - // For 360, same texture, just alias with a 3nd sampler. - // This sampler needs to have an exponent bias of -2. - FxaaTex fxaaConsole360TexExpBiasNegTwo, - // - // Only used on FXAA Quality. - // This must be from a constant/uniform. - // {x_} = 1.0/screenWidthInPixels - // {_y} = 1.0/screenHeightInPixels - FxaaFloat2 fxaaQualityRcpFrame, - // - // Only used on FXAA Console. - // This must be from a constant/uniform. - // This effects sub-pixel AA quality and inversely sharpness. - // Where N ranges between, - // N = 0.50 (default) - // N = 0.33 (sharper) - // {x___} = -N/screenWidthInPixels - // {_y__} = -N/screenHeightInPixels - // {__z_} = N/screenWidthInPixels - // {___w} = N/screenHeightInPixels - FxaaFloat4 fxaaConsoleRcpFrameOpt, - // - // Only used on FXAA Console. - // Not used on 360, but used on PS3 and PC. - // This must be from a constant/uniform. - // {x___} = -2.0/screenWidthInPixels - // {_y__} = -2.0/screenHeightInPixels - // {__z_} = 2.0/screenWidthInPixels - // {___w} = 2.0/screenHeightInPixels - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - // - // Only used on FXAA Console. - // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. - // This must be from a constant/uniform. - // {x___} = 8.0/screenWidthInPixels - // {_y__} = 8.0/screenHeightInPixels - // {__z_} = -4.0/screenWidthInPixels - // {___w} = -4.0/screenHeightInPixels - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__SUBPIX define. - // It is here now to allow easier tuning. - // Choose the amount of sub-pixel aliasing removal. - // This can effect sharpness. - // 1.00 - upper limit (softer) - // 0.75 - default amount of filtering - // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) - // 0.25 - almost off - // 0.00 - completely off - FxaaFloat fxaaQualitySubpix, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. - // It is here now to allow easier tuning. - // The minimum amount of local contrast required to apply algorithm. - // 0.333 - too little (faster) - // 0.250 - low quality - // 0.166 - default - // 0.125 - high quality - // 0.063 - overkill (slower) - FxaaFloat fxaaQualityEdgeThreshold, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. - // It is here now to allow easier tuning. - // Trims the algorithm from processing darks. - // 0.0833 - upper limit (default, the start of visible unfiltered edges) - // 0.0625 - high quality (faster) - // 0.0312 - visible limit (slower) - // Special notes when using FXAA_GREEN_AS_LUMA, - // Likely want to set this to zero. - // As colors that are mostly not-green - // will appear very dark in the green channel! - // Tune by looking at mostly non-green content, - // then start at zero and increase until aliasing is a problem. - FxaaFloat fxaaQualityEdgeThresholdMin, - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. - // It is here now to allow easier tuning. - // This does not effect PS3, as this needs to be compiled in. - // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. - // Due to the PS3 being ALU bound, - // there are only three safe values here: 2 and 4 and 8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // For all other platforms can be a non-power of two. - // 8.0 is sharper (default!!!) - // 4.0 is softer - // 2.0 is really soft (good only for vector graphics inputs) - FxaaFloat fxaaConsoleEdgeSharpness, - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. - // It is here now to allow easier tuning. - // This does not effect PS3, as this needs to be compiled in. - // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. - // Due to the PS3 being ALU bound, - // there are only two safe values here: 1/4 and 1/8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // The console setting has a different mapping than the quality setting. - // Other platforms can use other values. - // 0.125 leaves less aliasing, but is softer (default!!!) - // 0.25 leaves more aliasing, and is sharper - FxaaFloat fxaaConsoleEdgeThreshold, - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. - // It is here now to allow easier tuning. - // Trims the algorithm from processing darks. - // The console setting has a different mapping than the quality setting. - // This only applies when FXAA_EARLY_EXIT is 1. - // This does not apply to PS3, - // PS3 was simplified to avoid more shader instructions. - // 0.06 - faster but more aliasing in darks - // 0.05 - default - // 0.04 - slower and less aliasing in darks - // Special notes when using FXAA_GREEN_AS_LUMA, - // Likely want to set this to zero. - // As colors that are mostly not-green - // will appear very dark in the green channel! - // Tune by looking at mostly non-green content, - // then start at zero and increase until aliasing is a problem. - FxaaFloat fxaaConsoleEdgeThresholdMin, - // - // Extra constants for 360 FXAA Console only. - // Use zeros or anything else for other platforms. - // These must be in physical constant registers and NOT immedates. - // Immedates will result in compiler un-optimizing. - // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ - FxaaFloat2 posM; - posM.x = pos.x; - posM.y = pos.y; - #if (FXAA_GATHER4_ALPHA == 1) - #if (FXAA_DISCARD == 0) - FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); - #if (FXAA_GREEN_AS_LUMA == 0) - #define lumaM dot(rgbyM.rgb, FxaaFloat3(0.299, 0.587, 0.114)) - #else - #define lumaM rgbyM.y - #endif - #endif - #if (FXAA_GREEN_AS_LUMA == 0) - FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); - FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); - #else - FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); - FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); - #endif - #if (FXAA_DISCARD == 1) - #define lumaM luma4A.w - #endif - #define lumaE luma4A.z - #define lumaS luma4A.x - #define lumaSE luma4A.y - #define lumaNW luma4B.w - #define lumaN luma4B.z - #define lumaW luma4B.x - #else - FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); - #if (FXAA_GREEN_AS_LUMA == 0) - #define lumaM dot(rgbyM.rgb, FxaaFloat3(0.299, 0.587, 0.114)) - #else - #define lumaM rgbyM.y - #endif - FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); - #endif -/*--------------------------------------------------------------------------*/ - FxaaFloat maxSM = max(lumaS, lumaM); - FxaaFloat minSM = min(lumaS, lumaM); - FxaaFloat maxESM = max(lumaE, maxSM); - FxaaFloat minESM = min(lumaE, minSM); - FxaaFloat maxWN = max(lumaN, lumaW); - FxaaFloat minWN = min(lumaN, lumaW); - FxaaFloat rangeMax = max(maxWN, maxESM); - FxaaFloat rangeMin = min(minWN, minESM); - FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; - FxaaFloat range = rangeMax - rangeMin; - FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); - FxaaBool earlyExit = range < rangeMaxClamped; -/*--------------------------------------------------------------------------*/ - if(earlyExit) - #if (FXAA_DISCARD == 1) - FxaaDiscard; - #else - return rgbyM; - #endif -/*--------------------------------------------------------------------------*/ - #if (FXAA_GATHER4_ALPHA == 0) - FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); - #else - FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); - #endif -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNS = lumaN + lumaS; - FxaaFloat lumaWE = lumaW + lumaE; - FxaaFloat subpixRcpRange = 1.0/range; - FxaaFloat subpixNSWE = lumaNS + lumaWE; - FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; - FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNESE = lumaNE + lumaSE; - FxaaFloat lumaNWNE = lumaNW + lumaNE; - FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; - FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNWSW = lumaNW + lumaSW; - FxaaFloat lumaSWSE = lumaSW + lumaSE; - FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); - FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); - FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; - FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; - FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; - FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; -/*--------------------------------------------------------------------------*/ - FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; - FxaaFloat lengthSign = fxaaQualityRcpFrame.x; - FxaaBool horzSpan = edgeHorz >= edgeVert; - FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; -/*--------------------------------------------------------------------------*/ - if(!horzSpan) lumaN = lumaW; - if(!horzSpan) lumaS = lumaE; - if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; - FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; -/*--------------------------------------------------------------------------*/ - FxaaFloat gradientN = lumaN - lumaM; - FxaaFloat gradientS = lumaS - lumaM; - FxaaFloat lumaNN = lumaN + lumaM; - FxaaFloat lumaSS = lumaS + lumaM; - FxaaBool pairN = abs(gradientN) >= abs(gradientS); - FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); - if(pairN) lengthSign = -lengthSign; - FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); -/*--------------------------------------------------------------------------*/ - FxaaFloat2 posB; - posB.x = posM.x; - posB.y = posM.y; - FxaaFloat2 offNP; - offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; - offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; - if(!horzSpan) posB.x += lengthSign * 0.5; - if( horzSpan) posB.y += lengthSign * 0.5; -/*--------------------------------------------------------------------------*/ - FxaaFloat2 posN; - posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; - posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; - FxaaFloat2 posP; - posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; - posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; - FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; - FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); - FxaaFloat subpixE = subpixC * subpixC; - FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); -/*--------------------------------------------------------------------------*/ - if(!pairN) lumaNN = lumaSS; - FxaaFloat gradientScaled = gradient * 1.0/4.0; - FxaaFloat lumaMM = lumaM - lumaNN * 0.5; - FxaaFloat subpixF = subpixD * subpixE; - FxaaBool lumaMLTZero = lumaMM < 0.0; -/*--------------------------------------------------------------------------*/ - lumaEndN -= lumaNN * 0.5; - lumaEndP -= lumaNN * 0.5; - FxaaBool doneN = abs(lumaEndN) >= gradientScaled; - FxaaBool doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; - FxaaBool doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; -/*--------------------------------------------------------------------------*/ - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 3) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 4) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 5) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 6) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 7) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 8) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 9) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 10) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 11) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 12) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } -/*--------------------------------------------------------------------------*/ - FxaaFloat dstN = posM.x - posN.x; - FxaaFloat dstP = posP.x - posM.x; - if(!horzSpan) dstN = posM.y - posN.y; - if(!horzSpan) dstP = posP.y - posM.y; -/*--------------------------------------------------------------------------*/ - FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; - FxaaFloat spanLength = (dstP + dstN); - FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; - FxaaFloat spanLengthRcp = 1.0/spanLength; -/*--------------------------------------------------------------------------*/ - FxaaBool directionN = dstN < dstP; - FxaaFloat dst = min(dstN, dstP); - FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; - FxaaFloat subpixG = subpixF * subpixF; - FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; - FxaaFloat subpixH = subpixG * fxaaQualitySubpix; -/*--------------------------------------------------------------------------*/ - FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; - FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); - if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; - if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; - #if (FXAA_DISCARD == 1) - return FxaaTexTop(tex, posM); - #else - //return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); - return FxaaFloat4(FxaaTexTop(tex, posM)); - #endif -} -/*==========================================================================*/ -#endif - - - - -/*============================================================================ - - FXAA3 CONSOLE - PC VERSION - ------------------------------------------------------------------------------- -Instead of using this on PC, I'd suggest just using FXAA Quality with - #define FXAA_QUALITY__PRESET 10 -Or - #define FXAA_QUALITY__PRESET 20 -Either are higher qualilty and almost as fast as this on modern PC GPUs. -============================================================================*/ -#if (FXAA_PC_CONSOLE == 1) -/*--------------------------------------------------------------------------*/ -FxaaFloat4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); - FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); - FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); - FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); -/*--------------------------------------------------------------------------*/ - FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); - #if (FXAA_GREEN_AS_LUMA == 0) - FxaaFloat lumaM = rgbyM.w; - #else - FxaaFloat lumaM = rgbyM.y; - #endif -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); - lumaNe += 1.0/384.0; - FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); - FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); - FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMinM = min(lumaMin, lumaM); - FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); - FxaaFloat lumaMaxM = max(lumaMax, lumaM); - FxaaFloat dirSwMinusNe = lumaSw - lumaNe; - FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; - FxaaFloat dirSeMinusNw = lumaSe - lumaNw; - if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; -/*--------------------------------------------------------------------------*/ - FxaaFloat2 dir; - dir.x = dirSwMinusNe + dirSeMinusNw; - dir.y = dirSwMinusNe - dirSeMinusNw; -/*--------------------------------------------------------------------------*/ - FxaaFloat2 dir1 = normalize(dir.xy); - FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); - FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); -/*--------------------------------------------------------------------------*/ - FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; - FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); -/*--------------------------------------------------------------------------*/ - FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); - FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); -/*--------------------------------------------------------------------------*/ - FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; - FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); -/*--------------------------------------------------------------------------*/ - #if (FXAA_GREEN_AS_LUMA == 0) - FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); - #else - FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); - #endif - if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; - return rgbyB; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - 360 PIXEL SHADER - ------------------------------------------------------------------------------- -This optimized version thanks to suggestions from Andy Luedke. -Should be fully tex bound in all cases. -As of the FXAA 3.11 release, I have still not tested this code, -however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. -And note this is replacing the old unoptimized version. -If it does not work, please let me know so I can fix it. -============================================================================*/ -#if (FXAA_360 == 1) -/*--------------------------------------------------------------------------*/ -[reduceTempRegUsage(4)] -float4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ - float4 lumaNwNeSwSe; - #if (FXAA_GREEN_AS_LUMA == 0) - asm { - tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false - }; - #else - asm { - tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false - }; - #endif -/*--------------------------------------------------------------------------*/ - lumaNwNeSwSe.y += 1.0/384.0; - float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); - float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); - float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); - float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); -/*--------------------------------------------------------------------------*/ - float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); - #if (FXAA_GREEN_AS_LUMA == 0) - float lumaMinM = min(lumaMin, rgbyM.w); - float lumaMaxM = max(lumaMax, rgbyM.w); - #else - float lumaMinM = min(lumaMin, rgbyM.y); - float lumaMaxM = max(lumaMax, rgbyM.y); - #endif - if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; -/*--------------------------------------------------------------------------*/ - float2 dir; - dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); - dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); - dir = normalize(dir); -/*--------------------------------------------------------------------------*/ - float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; -/*--------------------------------------------------------------------------*/ - float4 dir2; - float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; - dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); - dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; -/*--------------------------------------------------------------------------*/ - float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); - float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); - float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); - float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); -/*--------------------------------------------------------------------------*/ - float4 rgbyA = rgbyN1 + rgbyP1; - float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; -/*--------------------------------------------------------------------------*/ - float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; - rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; - return rgbyR; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) - -============================================================================== -The code below does not exactly match the assembly. -I have a feeling that 12 cycles is possible, but was not able to get there. -Might have to increase register count to get full performance. -Note this shader does not use perspective interpolation. - -Use the following cgc options, - - --fenable-bx2 --fastmath --fastprecision --nofloatbindings - ------------------------------------------------------------------------------- - NVSHADERPERF OUTPUT ------------------------------------------------------------------------------- -For reference and to aid in debug, output of NVShaderPerf should match this, - -Shader to schedule: - 0: texpkb h0.w(TRUE), v5.zyxx, #0 - 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x - 4: texpkb h0.w(TRUE), v5.xwxx, #0 - 6: addh h0.z(TRUE), -h2, h0.w - 7: texpkb h1.w(TRUE), v5, #0 - 9: addh h0.x(TRUE), h0.z, -h1.w - 10: addh h3.w(TRUE), h0.z, h1 - 11: texpkb h2.w(TRUE), v5.zwzz, #0 - 13: addh h0.z(TRUE), h3.w, -h2.w - 14: addh h0.x(TRUE), h2.w, h0 - 15: nrmh h1.xz(TRUE), h0_n - 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| - 17: maxh h4.w(TRUE), h0, h1 - 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n - 19: movr r1.zw(TRUE), v4.xxxy - 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww - 22: minh h5.w(TRUE), h0, h1 - 23: texpkb h0(TRUE), r2.xzxx, #0 - 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 - 27: maxh h4.x(TRUE), h2.z, h2.w - 28: texpkb h1(TRUE), r0.zwzz, #0 - 30: addh_d2 h1(TRUE), h0, h1 - 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 33: texpkb h0(TRUE), r0, #0 - 35: minh h4.z(TRUE), h2, h2.w - 36: fenct TRUE - 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 39: texpkb h2(TRUE), r1, #0 - 41: addh_d2 h0(TRUE), h0, h2 - 42: maxh h2.w(TRUE), h4, h4.x - 43: minh h2.x(TRUE), h5.w, h4.z - 44: addh_d2 h0(TRUE), h0, h1 - 45: slth h2.x(TRUE), h0.w, h2 - 46: sgth h2.w(TRUE), h0, h2 - 47: movh h0(TRUE), h0 - 48: addx.c0 rc(TRUE), h2, h2.w - 49: movh h0(c0.NE.x), h1 - -IPU0 ------ Simplified schedule: -------- -Pass | Unit | uOp | PC: Op ------+--------+------+------------------------- - 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; - | | | - 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; - | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; - | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; - | | | - 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; - | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; - | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; - | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; - | | | - 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; - | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; - | | | - 5 | SCT1 | mov | 15: NRMh h1.xz, h0; - | SRB | nrm | 15: NRMh h1.xz, h0; - | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; - | SCB1 | max | 17: MAXh h4.w, h0, h1; - | | | - 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; - | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; - | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; - | SCB1 | min | 22: MINh h5.w, h0, h1; - | | | - 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; - | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; - | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; - | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; - | | | - 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; - | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; - | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; - | | | - 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; - | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; - | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; - | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; - | | | - 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; - | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; - | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; - | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; - | | | - 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; - | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; - | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; - | | | - 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; - | SCT1 | set | 46: SGTh h2.w, h0, h2; - | SCB0/1 | mul | 47: MOVh h0, h0; - | | | - 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; - | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; - -Pass SCT TEX SCB - 1: 0% 100% 25% - 2: 0% 100% 25% - 3: 0% 100% 50% - 4: 0% 100% 50% - 5: 0% 0% 50% - 6: 100% 0% 75% - 7: 0% 100% 75% - 8: 0% 100% 100% - 9: 0% 100% 25% - 10: 0% 100% 100% - 11: 50% 0% 100% - 12: 50% 0% 100% - 13: 25% 0% 100% - -MEAN: 17% 61% 67% - -Pass SCT0 SCT1 TEX SCB0 SCB1 - 1: 0% 0% 100% 0% 100% - 2: 0% 0% 100% 0% 100% - 3: 0% 0% 100% 100% 100% - 4: 0% 0% 100% 100% 100% - 5: 0% 0% 0% 100% 100% - 6: 100% 100% 0% 100% 100% - 7: 0% 0% 100% 100% 100% - 8: 0% 0% 100% 100% 100% - 9: 0% 0% 100% 0% 100% - 10: 0% 0% 100% 100% 100% - 11: 100% 100% 0% 100% 100% - 12: 100% 100% 0% 100% 100% - 13: 100% 0% 0% 100% 100% - -MEAN: 30% 23% 61% 76% 100% -Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 -Results 13 cycles, 3 r regs, 923,076,923 pixels/s -============================================================================*/ -#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) -/*--------------------------------------------------------------------------*/ -#pragma regcount 7 -#pragma disablepc all -#pragma option O3 -#pragma option OutColorPrec=fp16 -#pragma texformat default RGBA8 -/*==========================================================================*/ -half4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ -// (1) - half4 dir; - half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - lumaNe.w += half(1.0/512.0); - dir.x = -lumaNe.w; - dir.z = -lumaNe.w; - #else - lumaNe.y += half(1.0/512.0); - dir.x = -lumaNe.y; - dir.z = -lumaNe.y; - #endif -/*--------------------------------------------------------------------------*/ -// (2) - half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x += lumaSw.w; - dir.z += lumaSw.w; - #else - dir.x += lumaSw.y; - dir.z += lumaSw.y; - #endif -/*--------------------------------------------------------------------------*/ -// (3) - half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x -= lumaNw.w; - dir.z += lumaNw.w; - #else - dir.x -= lumaNw.y; - dir.z += lumaNw.y; - #endif -/*--------------------------------------------------------------------------*/ -// (4) - half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x += lumaSe.w; - dir.z -= lumaSe.w; - #else - dir.x += lumaSe.y; - dir.z -= lumaSe.y; - #endif -/*--------------------------------------------------------------------------*/ -// (5) - half4 dir1_pos; - dir1_pos.xy = normalize(dir.xyz).xz; - half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); -/*--------------------------------------------------------------------------*/ -// (6) - half4 dir2_pos; - dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); - dir1_pos.zw = pos.xy; - dir2_pos.zw = pos.xy; - half4 temp1N; - temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ -// (7) - temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); - half4 rgby1; - rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ -// (8) - rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); - rgby1 = (temp1N + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (9) - half4 temp2N; - temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); -/*--------------------------------------------------------------------------*/ -// (10) - half4 rgby2; - rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); - rgby2 = (temp2N + rgby2) * 0.5; -/*--------------------------------------------------------------------------*/ -// (11) - // compilier moves these scalar ops up to other cycles - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); - half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); - #else - half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); - half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); - #endif - rgby2 = (rgby2 + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (12) - #if (FXAA_GREEN_AS_LUMA == 0) - bool twoTapLt = rgby2.w < lumaMin; - bool twoTapGt = rgby2.w > lumaMax; - #else - bool twoTapLt = rgby2.y < lumaMin; - bool twoTapGt = rgby2.y > lumaMax; - #endif -/*--------------------------------------------------------------------------*/ -// (13) - if(twoTapLt || twoTapGt) rgby2 = rgby1; -/*--------------------------------------------------------------------------*/ - return rgby2; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) - -============================================================================== -The code mostly matches the assembly. -I have a feeling that 14 cycles is possible, but was not able to get there. -Might have to increase register count to get full performance. -Note this shader does not use perspective interpolation. - -Use the following cgc options, - - --fenable-bx2 --fastmath --fastprecision --nofloatbindings - -Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). -Will look at fixing this for FXAA 3.12. ------------------------------------------------------------------------------- - NVSHADERPERF OUTPUT ------------------------------------------------------------------------------- -For reference and to aid in debug, output of NVShaderPerf should match this, - -Shader to schedule: - 0: texpkb h0.w(TRUE), v5.zyxx, #0 - 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x - 4: texpkb h1.w(TRUE), v5.xwxx, #0 - 6: addh h0.x(TRUE), h1.w, -h2.y - 7: texpkb h2.w(TRUE), v5.zwzz, #0 - 9: minh h4.w(TRUE), h2.y, h2 - 10: maxh h5.x(TRUE), h2.y, h2.w - 11: texpkb h0.w(TRUE), v5, #0 - 13: addh h3.w(TRUE), -h0, h0.x - 14: addh h0.x(TRUE), h0.w, h0 - 15: addh h0.z(TRUE), -h2.w, h0.x - 16: addh h0.x(TRUE), h2.w, h3.w - 17: minh h5.y(TRUE), h0.w, h1.w - 18: nrmh h2.xz(TRUE), h0_n - 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| - 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w - 21: movr r1.zw(TRUE), v4.xxxy - 22: maxh h2.w(TRUE), h0, h1 - 23: fenct TRUE - 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz - 26: texpkb h0(TRUE), r0, #0 - 28: maxh h5.x(TRUE), h2.w, h5 - 29: minh h5.w(TRUE), h5.y, h4 - 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz - 32: texpkb h2(TRUE), r1, #0 - 34: addh_d2 h2(TRUE), h0, h2 - 35: texpkb h1(TRUE), v4, #0 - 37: maxh h5.y(TRUE), h5.x, h1.w - 38: minh h4.w(TRUE), h1, h5 - 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 41: texpkb h0(TRUE), r0, #0 - 43: addh_m8 h5.z(TRUE), h5.y, -h4.w - 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 46: texpkb h3(TRUE), r2, #0 - 48: addh_d2 h0(TRUE), h0, h3 - 49: addh_d2 h3(TRUE), h0, h2 - 50: movh h0(TRUE), h3 - 51: slth h3.x(TRUE), h3.w, h5.w - 52: sgth h3.w(TRUE), h3, h5.x - 53: addx.c0 rc(TRUE), h3.x, h3 - 54: slth.c0 rc(TRUE), h5.z, h5 - 55: movh h0(c0.NE.w), h2 - 56: movh h0(c0.NE.x), h1 - -IPU0 ------ Simplified schedule: -------- -Pass | Unit | uOp | PC: Op ------+--------+------+------------------------- - 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; - | | | - 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; - | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; - | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; - | | | - 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; - | SCB1 | min | 9: MINh h4.w, h2.---y, h2; - | | | - 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; - | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; - | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; - | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; - | | | - 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; - | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; - | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; - | | | - 6 | SCT1 | mov | 18: NRMh h2.xz, h0; - | SRB | nrm | 18: NRMh h2.xz, h0; - | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; - | | | - 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; - | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; - | SCB1 | max | 22: MAXh h2.w, h0, h1; - | | | - 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; - | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; - | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; - | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; - | SCB1 | min | 29: MINh h5.w, h5.---y, h4; - | | | - 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; - | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; - | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; - | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; - | | | - 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; - | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; - | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; - | SCB1 | min | 38: MINh h4.w, h1, h5; - | | | - 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; - | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; - | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; - | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; - | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; - | | | - 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; - | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; - | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; - | | | - 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; - | SCB0/1 | mul | 50: MOVh h0, h3; - | | | - 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; - | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; - | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; - | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; - | | | - 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; - | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; - -Pass SCT TEX SCB - 1: 0% 100% 25% - 2: 0% 100% 25% - 3: 0% 100% 50% - 4: 0% 100% 50% - 5: 50% 0% 25% - 6: 0% 0% 25% - 7: 100% 0% 25% - 8: 0% 100% 50% - 9: 0% 100% 100% - 10: 0% 100% 50% - 11: 0% 100% 75% - 12: 0% 100% 100% - 13: 100% 0% 100% - 14: 50% 0% 50% - 15: 100% 0% 100% - -MEAN: 26% 60% 56% - -Pass SCT0 SCT1 TEX SCB0 SCB1 - 1: 0% 0% 100% 100% 0% - 2: 0% 0% 100% 100% 0% - 3: 0% 0% 100% 100% 100% - 4: 0% 0% 100% 100% 100% - 5: 100% 100% 0% 100% 0% - 6: 0% 0% 0% 0% 100% - 7: 100% 100% 0% 0% 100% - 8: 0% 0% 100% 100% 100% - 9: 0% 0% 100% 100% 100% - 10: 0% 0% 100% 100% 100% - 11: 0% 0% 100% 100% 100% - 12: 0% 0% 100% 100% 100% - 13: 100% 100% 0% 100% 100% - 14: 100% 100% 0% 100% 100% - 15: 100% 100% 0% 100% 100% - -MEAN: 33% 33% 60% 86% 80% -Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 -Results 15 cycles, 3 r regs, 800,000,000 pixels/s -============================================================================*/ -#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) -/*--------------------------------------------------------------------------*/ -#pragma regcount 7 -#pragma disablepc all -#pragma option O2 -#pragma option OutColorPrec=fp16 -#pragma texformat default RGBA8 -/*==========================================================================*/ -half4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ -// (1) - half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaNe = rgbyNe.w + half(1.0/512.0); - #else - half lumaNe = rgbyNe.y + half(1.0/512.0); - #endif -/*--------------------------------------------------------------------------*/ -// (2) - half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaSwNegNe = lumaSw.w - lumaNe; - #else - half lumaSwNegNe = lumaSw.y - lumaNe; - #endif -/*--------------------------------------------------------------------------*/ -// (3) - half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); - half lumaMinNwSw = min(lumaNw.w, lumaSw.w); - #else - half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); - half lumaMinNwSw = min(lumaNw.y, lumaSw.y); - #endif -/*--------------------------------------------------------------------------*/ -// (4) - half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half dirZ = lumaNw.w + lumaSwNegNe; - half dirX = -lumaNw.w + lumaSwNegNe; - #else - half dirZ = lumaNw.y + lumaSwNegNe; - half dirX = -lumaNw.y + lumaSwNegNe; - #endif -/*--------------------------------------------------------------------------*/ -// (5) - half3 dir; - dir.y = 0.0; - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x = lumaSe.w + dirX; - dir.z = -lumaSe.w + dirZ; - half lumaMinNeSe = min(lumaNe, lumaSe.w); - #else - dir.x = lumaSe.y + dirX; - dir.z = -lumaSe.y + dirZ; - half lumaMinNeSe = min(lumaNe, lumaSe.y); - #endif -/*--------------------------------------------------------------------------*/ -// (6) - half4 dir1_pos; - dir1_pos.xy = normalize(dir).xz; - half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); -/*--------------------------------------------------------------------------*/ -// (7) - half4 dir2_pos; - dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); - dir1_pos.zw = pos.xy; - dir2_pos.zw = pos.xy; - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMaxNeSe = max(lumaNe, lumaSe.w); - #else - half lumaMaxNeSe = max(lumaNe, lumaSe.y); - #endif -/*--------------------------------------------------------------------------*/ -// (8) - half4 temp1N; - temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; - temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); - half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); - half lumaMin = min(lumaMinNwSw, lumaMinNeSe); -/*--------------------------------------------------------------------------*/ -// (9) - half4 rgby1; - rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; - rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); - rgby1 = (temp1N + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (10) - half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMaxM = max(lumaMax, rgbyM.w); - half lumaMinM = min(lumaMin, rgbyM.w); - #else - half lumaMaxM = max(lumaMax, rgbyM.y); - half lumaMinM = min(lumaMin, rgbyM.y); - #endif -/*--------------------------------------------------------------------------*/ -// (11) - half4 temp2N; - temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); - half4 rgby2; - rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; -/*--------------------------------------------------------------------------*/ -// (12) - rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); - rgby2 = (temp2N + rgby2) * 0.5; -/*--------------------------------------------------------------------------*/ -// (13) - rgby2 = (rgby2 + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (14) - #if (FXAA_GREEN_AS_LUMA == 0) - bool twoTapLt = rgby2.w < lumaMin; - bool twoTapGt = rgby2.w > lumaMax; - #else - bool twoTapLt = rgby2.y < lumaMin; - bool twoTapGt = rgby2.y > lumaMax; - #endif - bool earlyExit = lumaRangeM < lumaMax; - bool twoTap = twoTapLt || twoTapGt; -/*--------------------------------------------------------------------------*/ -// (15) - if(twoTap) rgby2 = rgby1; - if(earlyExit) rgby2 = rgbyM; -/*--------------------------------------------------------------------------*/ - return rgby2; } -/*==========================================================================*/ -#endif - - - - - - - - - - -in vec4 pos; - -uniform sampler2D tex0; -uniform vec2 dt; - -void main() { - qgl_FragColor = FxaaPixelShader( - // - // Use noperspective interpolation here (turn off perspective interpolation). - // {xy} = center of pixel - pos.xy, - // - // Used only for FXAA Console, and not used on the 360 version. - // Use noperspective interpolation here (turn off perspective interpolation). - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - vec4(0), - // - // Input color texture. - // {rgb_} = color in linear or perceptual color space - // if (FXAA_GREEN_AS_LUMA == 0) - // {___a} = luma in perceptual color space (not linear) - tex0, - // - // Only used on the optimized 360 version of FXAA Console. - // For everything but 360, just use the same input here as for "tex". - // For 360, same texture, just alias with a 2nd sampler. - // This sampler needs to have an exponent bias of -1. - tex0, - // - // Only used on the optimized 360 version of FXAA Console. - // For everything but 360, just use the same input here as for "tex". - // For 360, same texture, just alias with a 3nd sampler. - // This sampler needs to have an exponent bias of -2. - tex0, - // - // Only used on FXAA Quality. - // This must be from a constant/uniform. - // {x_} = 1.0/screenWidthInPixels - // {_y} = 1.0/screenHeightInPixels - dt, - // - // Only used on FXAA Console. - // This must be from a constant/uniform. - // This effects sub-pixel AA quality and inversely sharpness. - // Where N ranges between, - // N = 0.50 (default) - // N = 0.33 (sharper) - // {x___} = -N/screenWidthInPixels - // {_y__} = -N/screenHeightInPixels - // {__z_} = N/screenWidthInPixels - // {___w} = N/screenHeightInPixels - vec4(0), - // - // Only used on FXAA Console. - // Not used on 360, but used on PS3 and PC. - // This must be from a constant/uniform. - // {x___} = -2.0/screenWidthInPixels - // {_y__} = -2.0/screenHeightInPixels - // {__z_} = 2.0/screenWidthInPixels - // {___w} = 2.0/screenHeightInPixels - vec4(0), - // - // Only used on FXAA Console. - // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. - // This must be from a constant/uniform. - // {x___} = 8.0/screenWidthInPixels - // {_y__} = 8.0/screenHeightInPixels - // {__z_} = -4.0/screenWidthInPixels - // {___w} = -4.0/screenHeightInPixels - vec4(0), - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__SUBPIX define. - // It is here now to allow easier tuning. - // Choose the amount of sub-pixel aliasing removal. - // This can effect sharpness. - // 1.00 - upper limit (softer) - // 0.75 - default amount of filtering - // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) - // 0.25 - almost off - // 0.00 - completely off - 0.75, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. - // It is here now to allow easier tuning. - // The minimum amount of local contrast required to apply algorithm. - // 0.333 - too little (faster) - // 0.250 - low quality - // 0.166 - default - // 0.125 - high quality - // 0.063 - overkill (slower) - 0.125, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. - // It is here now to allow easier tuning. - // Trims the algorithm from processing darks. - // 0.0833 - upper limit (default, the start of visible unfiltered edges) - // 0.0625 - high quality (faster) - // 0.0312 - visible limit (slower) - // Special notes when using FXAA_GREEN_AS_LUMA, - // Likely want to set this to zero. - // As colors that are mostly not-green - // will appear very dark in the green channel! - // Tune by looking at mostly non-green content, - // then start at zero and increase until aliasing is a problem. - 0.0625, - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. - // It is here now to allow easier tuning. - // This does not effect PS3, as this needs to be compiled in. - // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. - // Due to the PS3 being ALU bound, - // there are only three safe values here: 2 and 4 and 8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // For all other platforms can be a non-power of two. - // 8.0 is sharper (default!!!) - // 4.0 is softer - // 2.0 is really soft (good only for vector graphics inputs) - 0., - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. - // It is here now to allow easier tuning. - // This does not effect PS3, as this needs to be compiled in. - // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. - // Due to the PS3 being ALU bound, - // there are only two safe values here: 1/4 and 1/8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // The console setting has a different mapping than the quality setting. - // Other platforms can use other values. - // 0.125 leaves less aliasing, but is softer (default!!!) - // 0.25 leaves more aliasing, and is sharper - 0., - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. - // It is here now to allow easier tuning. - // Trims the algorithm from processing darks. - // The console setting has a different mapping than the quality setting. - // This only applies when FXAA_EARLY_EXIT is 1. - // This does not apply to PS3, - // PS3 was simplified to avoid more shader instructions. - // 0.06 - faster but more aliasing in darks - // 0.05 - default - // 0.04 - slower and less aliasing in darks - // Special notes when using FXAA_GREEN_AS_LUMA, - // Likely want to set this to zero. - // As colors that are mostly not-green - // will appear very dark in the green channel! - // Tune by looking at mostly non-green content, - // then start at zero and increase until aliasing is a problem. - 0., - // - // Extra constants for 360 FXAA Console only. - // Use zeros or anything else for other platforms. - // These must be in physical constant registers and NOT immedates. - // Immedates will result in compiler un-optimizing. - // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) - vec4(0)); -} diff --git a/qglengine/shaders/fxaa.vert b/qglengine/shaders/fxaa.vert deleted file mode 100644 index 02c3d70..0000000 --- a/qglengine/shaders/fxaa.vert +++ /dev/null @@ -1,11 +0,0 @@ -out vec4 pos; - -const float FXAA_SUBPIX_SHIFT = 1. / 4.; -uniform vec2 dt; - -void main(void) { - qgl_FragTexture = qgl_Texture; - pos.xy = qgl_Texture.xy; - pos.zw = qgl_Texture.xy - (dt * (0.5 + FXAA_SUBPIX_SHIFT)); - gl_Position = qgl_ftransform(); -} diff --git a/qglengine/shaders/selection.glsl b/qglengine/shaders/selection.glsl deleted file mode 100644 index 23909ca..0000000 --- a/qglengine/shaders/selection.glsl +++ /dev/null @@ -1,19 +0,0 @@ -// vert // - -flat out uint id, select; - -void main(void) { - id = qgl_ObjectID; - select = qgl_ObjectSelected; - gl_Position = qgl_ftransform(); -} - - -// frag // - -flat in uint id, select; - -void main(void) { - qgl_FragData[0] = unpackUnorm4x8(id); - qgl_FragData[1] = vec4(select); -} diff --git a/qglengine/shaders/selection_apply.glsl b/qglengine/shaders/selection_apply.glsl deleted file mode 100644 index 5029eba..0000000 --- a/qglengine/shaders/selection_apply.glsl +++ /dev/null @@ -1,25 +0,0 @@ -// vert // - -void main(void) { - qgl_FragTexture = qgl_Texture; - gl_Position = qgl_ftransform(); -} - - -// frag // - -uniform sampler2D fb_out, fb_hover, fb_select; - -void main(void) { - ivec2 tc = ivec2(gl_FragCoord.xy); - vec2 stc = qgl_FragTexture.xy; - vec4 src = texelFetch(fb_out , tc, 0); - vec4 hov = texture(fb_hover , stc); - vec4 sel = texture(fb_select, stc); - src.rgb = clamp(src.rgb, vec3(0), vec3(1)); - src.rgb = mix(src.rgb, sel.rgb, sel.a); - src.rgb = mix(src.rgb, hov.rgb, hov.a * 0.667f); - //src.rgb = src.rgb + (sel.rgb*sel.a); - qgl_FragData[0] = src; - //qgl_FragData[0] = vec4(sel.a); -} diff --git a/qglengine/shaders/selection_frame.glsl b/qglengine/shaders/selection_frame.glsl deleted file mode 100644 index e811faa..0000000 --- a/qglengine/shaders/selection_frame.glsl +++ /dev/null @@ -1,24 +0,0 @@ -// vert // - -void main(void) { - qgl_FragTexture = qgl_Texture; - gl_Position = qgl_ftransform(); -} - - -// frag // - -uniform vec2 dt, size; -uniform float thickness; - -void main(void) { - vec2 frame_size = size / dt; - vec2 pix_pos = qgl_FragTexture * frame_size; - vec2 frame = vec2(1) + step(pix_pos, vec2(thickness)) - step(pix_pos, frame_size - vec2(thickness)); - vec2 line = frame * step(0.5, fract(pix_pos.yx / thickness / 4.)); - float fc = max(frame.x, frame.y); - float fl = max(line.x , line.y ); - fl = mix(1, fl, fc); - qgl_FragColor = vec4(vec3(fl), fc * 0.8 + 0.2); - //qgl_FragColor = vec4(vec3(fl,0),1); -} diff --git a/qglengine/shaders/selection_halo.glsl b/qglengine/shaders/selection_halo.glsl deleted file mode 100644 index f62f74f..0000000 --- a/qglengine/shaders/selection_halo.glsl +++ /dev/null @@ -1,42 +0,0 @@ -// vert // - -void main(void) { - gl_Position = qgl_ftransform(); -} - - -// frag // - -uniform sampler2D fb_hover, fb_selection; -uniform vec4 hover_id, hover_color, selection_color; -uniform float hover_fill, selection_fill, has_hover, has_selection; -ivec2 tc; - -vec4 diffVector(in sampler2D map, in vec4 id) { - vec4 ds0 = abs(texelFetchOffset(map, tc, 0, ivec2(-1, 0)) - id); - vec4 ds1 = abs(texelFetchOffset(map, tc, 0, ivec2( 1, 0)) - id); - vec4 ds2 = abs(texelFetchOffset(map, tc, 0, ivec2(0, -1)) - id); - vec4 ds3 = abs(texelFetchOffset(map, tc, 0, ivec2(0, 1)) - id); - return vec4(dot(ds0, vec4(1)), dot(ds1, vec4(1)), dot(ds2, vec4(1)), dot(ds3, vec4(1))); -} -vec2 diffPair(in vec4 dv) { - const float _c = 64; - return vec2(step(1e-6, dot(dv, vec4(1))), - step(1e-3, (dv.r * _c) * (dv.g * _c) * (dv.b * _c) * (dv.a * _c))); -} -float diffAlpha(in vec2 dp, in float fill) { - return mix(dp.x - dp.y, dp.x - dp.y - dp.y + 1, fill); -} - -void main(void) { - tc = ivec2(gl_FragCoord.xy); - float hh = clamp(dot(hover_id, vec4(1)), 0, 1); - - vec2 dp = diffPair(diffVector(fb_hover, hover_id)); - float v = diffAlpha(dp, hover_fill); - qgl_FragData[0] = has_hover*hh*v*vec4(hover_color.rgb, hover_color.a); - - dp = diffPair(diffVector(fb_selection, vec4(1))); - v = diffAlpha(dp, selection_fill); - qgl_FragData[1] = has_selection*v*vec4(selection_color.rgb, selection_color.a); -} diff --git a/qglengine/shaders/service_fill.glsl b/qglengine/shaders/service_fill.glsl deleted file mode 100644 index bc1cc8f..0000000 --- a/qglengine/shaders/service_fill.glsl +++ /dev/null @@ -1,24 +0,0 @@ -// vert // - -out vec3 geom_normal; -out vec4 object_color; - -void main(void) { - qgl_FragTexture = qgl_Texture; - gl_Position = qgl_ftransform(); - - geom_normal = normalize(qgl_Normal * qgl_getNormalMatrix()); - object_color = qgl_ObjectColor; -} - - -// frag // - -in vec3 geom_normal; -in vec4 object_color; - -void main(void) { - vec3 normal = normalize(geom_normal); - float l = max(0, dot(normal, vec3(0,0,1))); - qgl_FragColor = object_color * (l * 0.6 + 0.4); -} diff --git a/qglengine/shaders/service_frame.glsl b/qglengine/shaders/service_frame.glsl deleted file mode 100644 index 65189c1..0000000 --- a/qglengine/shaders/service_frame.glsl +++ /dev/null @@ -1,51 +0,0 @@ -// vert // - -out vec4 object_color_g; -out float mat_scale; - -void main(void) { - gl_Position = qgl_ftransform(); - object_color_g = qgl_ObjectColor; - //mat_scale = pow(qgl_ModelMatrix[0][0] * qgl_ModelMatrix[1][1] * qgl_ModelMatrix[2][2], 0.3333); - mat_scale = pow(determinant(mat3(qgl_ModelMatrix)), 0.333); - //mat3 mm = transpose(mat3(qgl_ModelMatrix)); - //mat_scale = min(min(dot(vec3(1), mm[0]), dot(vec3(1), mm[1])), dot(vec3(1), mm[2])); -} - - -// geom // - -layout (lines) in; -layout (triangle_strip, max_vertices = 4) out; - -in float mat_scale[]; -in vec4 object_color_g[]; -out vec4 object_color; - -uniform float line_width, z_offset; -uniform mat4 qgl_ProjMatrix; - -void main(void) { - object_color = object_color_g[0]; - vec2 dir = normalize(gl_in[0].gl_Position.xy - gl_in[1].gl_Position.xy); - vec2 side = cross(vec3(dir, 0), vec3(0, 0, 1)).xy; - vec4 vo = vec4(0, 0, z_offset, 0); - float dts = 0.05 * line_width * mat_scale[0]; - dir *= dts; - side *= dts; - gl_Position = gl_in[0].gl_Position + vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); - gl_Position = gl_in[0].gl_Position + vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); - gl_Position = gl_in[1].gl_Position - vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); - gl_Position = gl_in[1].gl_Position - vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex(); - EndPrimitive(); -} - - -// frag // - -in vec4 object_color; -uniform float scale; - -void main(void) { - qgl_FragColor = object_color; -} diff --git a/qglengine/shaders/service_line.glsl b/qglengine/shaders/service_line.glsl deleted file mode 100644 index 2cfec5d..0000000 --- a/qglengine/shaders/service_line.glsl +++ /dev/null @@ -1,17 +0,0 @@ -// vert // - -out vec4 object_color; - -void main(void) { - gl_Position = qgl_ftransform(); - object_color = qgl_ObjectColor; -} - - -// frag // - -in vec4 object_color; - -void main(void) { - qgl_FragColor = object_color; -} diff --git a/qglengine/shaders/sum.glsl b/qglengine/shaders/sum.glsl deleted file mode 100644 index e12fd95..0000000 --- a/qglengine/shaders/sum.glsl +++ /dev/null @@ -1,25 +0,0 @@ -// vert // - -layout(location = 1) in ivec2 qgl_Vertex; - -flat out vec4 color; - -uniform sampler2D tex; - -void main(void) { - color = texelFetch(tex, qgl_Vertex, 0); - gl_Position = vec4(0,0,0,1); -} - - -// frag // - -out vec4 qgl_FragData[gl_MaxDrawBuffers]; - -flat in vec4 color; - -uniform float pcnt; - -void main(void) { - qgl_FragData[0] = color;// / pcnt; -} diff --git a/qglengine/tonemapping_proc.cpp b/qglengine/tonemapping_proc.cpp deleted file mode 100644 index b12b67c..0000000 --- a/qglengine/tonemapping_proc.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - QGL TonemappingProc - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#define GL_GLEXT_PROTOTYPES -#include -#include "tonemapping_proc.h" -#include "qglview.h" -#include - -using namespace QGLEngineShaders; - - -TonemappingProc::TonemappingProc(Renderer * rend): QThread(), r(rend), - fbo_1x1(r->view, 1, false, GL_RGB32F), - fbomm(r->fbo_out, Renderer::obrSum, 3), - buffer_vbo(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW) { - shader_sum = 0; - timer_delim = 0; - frame_max = cur_max = 1.; - need_render_sum = exit_ = false; - enabled = false; - timer_tone = startTimer(10); -} - - -TonemappingProc::~TonemappingProc() { - exit_ = true; - if (!wait(1000)) - terminate(); - killTimer(timer_tone); - if (shader_sum) delete shader_sum; -} - - -void TonemappingProc::init() { - QOpenGLExtraFunctions * f = r->view; - buffer_vbo.init(f); - f->glGenVertexArrays(1, &vbo_vao); - f->glBindVertexArray(vbo_vao); - buffer_vbo.bind(f); - f->glEnableVertexAttribArray(1); - f->glVertexAttribIPointer(1, 2, GL_UNSIGNED_INT, 0, 0); - buffer_vbo.release(f); - f->glBindVertexArray(0); - fbomm.lastPlane().enablePixelBuffer(); - fbo_1x1.resize(1, 1); - resize(); - if (!isRunning()) start(); -} - - -void TonemappingProc::resize() { - QOpenGLExtraFunctions * f = r->view; - fbomm.resize(); - int pcnt = fbomm.width(fbomm.lastLevel()) * fbomm.height(fbomm.lastLevel()); - QVector _data; - _data.resize(pcnt); - pcnt = -1; - for (int x = 0; x < fbomm.width(fbomm.lastLevel()); ++x) - for (int y = 0; y < fbomm.height(fbomm.lastLevel()); ++y) - _data[++pcnt] = Vector2i(x,y); - buffer_vbo.bind(f); - buffer_vbo.resize(f, _data.size() * sizeof(Vector2i)); - buffer_vbo.load(f, _data.constData(), _data.size() * sizeof(Vector2i)); -} - - -void TonemappingProc::timerEvent(QTimerEvent * e) { - if (!fbo_1x1.isInit() || !enabled) return; - if (timer_delim == 0) - need_render_sum = true; - timer_delim = (timer_delim + 1) % 10; - mutex.lock(); - float fmax = frame_max; - mutex.unlock(); - float dt = 0.01f, a = dt * 5.f, b = 1.f - a; - cur_max = fmax * a + cur_max * b; -} - - -void TonemappingProc::renderSum(Framebuffer & fbo_src, int index) { - QOpenGLExtraFunctions * f = r->view; - int pcnt = fbo_src.width() * fbo_src.height(); - fbo_src.bindColorTexture(index); - fbo_1x1.bind(); - //glClearFramebuffer(Qt::white, false); - glClearFramebuffer(); - if (shader_sum) { - if (shader_sum->isLinked()) { - if (shader_sum->bind()) { - shader_sum->setUniformValue("tex", 0); - shader_sum->setUniformValue("pcnt", float(pcnt)); - f->glBindVertexArray(vbo_vao); - f->glEnable(GL_BLEND); - f->glBlendFunc(GL_ONE, GL_ONE); - f->glBlendEquation(GL_MAX); - f->glDrawArrays(GL_POINTS, 0, pcnt); - f->glBlendEquation(GL_FUNC_ADD); - f->glDisable(GL_BLEND); - f->glBindVertexArray(0); - } - } - } - fbo_1x1.release(); - //fbo_src.bind(); -} - - -void TonemappingProc::run() { - while (!exit_) { - if (!enabled) { - msleep(100); - continue; - } - mutex.lock(); - if (last_data.isEmpty()) { - mutex.unlock(); - msleep(10); - continue; - } - QVector data = last_data; - last_data.clear(); - mutex.unlock(); - float max = calcHistogram(data); - last_max << max; - if (last_max.size() > 5) - last_max.removeAt(0); - float cm = last_max[0]; - for (int i = 1; i < last_max.size(); ++i) - cm += last_max[i]; - cm /= last_max.size(); - mutex.lock(); - frame_max = cm; - mutex.unlock(); - } -} - - -float TonemappingProc::calcHistogram(const QVector & data) { - if (data.isEmpty()) return 1.f; - float max = 0.; - QVector3D luma(0.299, 0.587, 0.114); - foreach (const QVector4D & p, data) { - float l = QVector3D::dotProduct(p.toVector3D(), luma); - max = qMax(max, l); - } - return max; -} - - -bool TonemappingProc::process() { - if (!need_render_sum || !enabled) return false; - need_render_sum = false; - Framebuffer & fbo(fbomm.lastPlane()); - if (fbo.queriedPoints() > 0) { - QVector data = fbo.getPointsFloat(); - mutex.lock(); - last_data = data; - mutex.unlock(); - } - fbomm.create(); - fbo.queryPoints(0, fbo.rect(), GL_FLOAT); - //renderSum(fbomm.plane(fbomm.lastLevel()), 0); - return true; -} - - -float TonemappingProc::frameMax() { - if (!enabled) return 1.f; - return cur_max; -} diff --git a/qglengine/tonemapping_proc.h b/qglengine/tonemapping_proc.h deleted file mode 100644 index b6f99d5..0000000 --- a/qglengine/tonemapping_proc.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - QGL TonemappingProc - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef TONEMAPPING_PROC_H -#define TONEMAPPING_PROC_H - -#include "glframebuffer_mipmap.h" -#include - - -class TonemappingProc: public QThread -{ - friend class Renderer; - friend class QGLView; -public: - TonemappingProc(Renderer * rend); - virtual ~TonemappingProc(); - - void init(); - void resize(); - void prepareSum(); - void renderSum(Framebuffer & fbo_src, int index); - - bool process(); - float frameMax(); - -protected: - void timerEvent(QTimerEvent * e); - void run() override; - float calcHistogram(const QVector & data); - -private: - Renderer * r; - QMutex mutex; - QVector last_data; - QVector last_max; - - float frame_max, cur_max; - bool need_render_sum, enabled; - std::atomic_bool exit_; - int timer_tone, timer_delim; - Framebuffer fbo_1x1; - FramebufferMipmap fbomm; - - QOpenGLShaderProgram * shader_sum; - Buffer buffer_vbo; - GLenum vbo_vao; - -}; - -#endif // RENDERER_H diff --git a/qglengine/widgets/CMakeLists.txt b/qglengine/widgets/CMakeLists.txt deleted file mode 100644 index 31b3b2e..0000000 --- a/qglengine/widgets/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -cmake_minimum_required(VERSION 3.0) -project(qglengine_widgets) -if (POLICY CMP0017) - cmake_policy(SET CMP0017 NEW) -endif() -find_qt(Qt5 Core Gui Widgets) -qt_sources(SRC) -qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM) -file(GLOB PHS "*_p.h") -list(REMOVE_ITEM out_HDR "${PHS}") -import_version(${PROJECT_NAME} qglengine) -set_deploy_property(${PROJECT_NAME} SHARED - LABEL "QGLEngine widgets library" - FULLNAME "${_DOMAIN}.${PROJECT_NAME}" - COMPANY "${_COMPANY}" - INFO "QGLEngine widgets library") -make_rc(${PROJECT_NAME} _RC) -qt_add_library(${PROJECT_NAME} SHARED out_CPP ${_RC}) -qt_generate_export_header(${PROJECT_NAME}) -list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h") -qt_target_link_libraries(${PROJECT_NAME} qad_utils qad_widgets qglengine_core) -qt_target_include_directories(${PROJECT_NAME} PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/../" "${CMAKE_CURRENT_SOURCE_DIR}/../core") -list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME}) -copy_to_parent("") -#message(STATUS "Building ${PROJECT_NAME}") -sdk_install("qglengine" FALSE "${PROJECT_NAME}" "${out_HDR}" "${out_QM}") diff --git a/qglengine/widgets/material_editor.cpp b/qglengine/widgets/material_editor.cpp deleted file mode 100644 index e6636fe..0000000 --- a/qglengine/widgets/material_editor.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - QGL MaterialEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "material_editor.h" -#include "ui_material_editor.h" -#include "glmaterial.h" - - -MaterialEditor::MaterialEditor(QWidget * parent): QWidget(parent) { - ui = new Ui::MaterialEditor(); - ui->setupUi(this); - ui->mapDiffuse ->configure(tr("Diffuse"), true); - ui->mapNormal ->configure(tr("Normal")); - ui->mapMetalness->configure(tr("Metalness")); - ui->mapRoughness->configure(tr("Roughness")); - ui->mapEmission ->configure(tr("Emission"), true); - ui->mapRelief ->configure(tr("Relief")); - ui->checkGlass->hide(); - ui->frameReflection->hide(); - ui->label_13->hide(); - mat = 0; - active = true; - ignore_next = 0; -} - - -void MaterialEditor::changeEvent(QEvent * e) { - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} - - -void MaterialEditor::materialChanged() { - if (!active || !mat) return; - ignore_next = 2; - mat->_changed = true; - mat->color_diffuse = ui->mapDiffuse ->color(); - mat->color_emission = ui->mapEmission->color(); - mat->transparency = ui->spinTransparent->value(); - mat->reflectivity = ui->spinReflect->value(); - mat->iof = ui->spinIOF->value(); - mat->dispersion = ui->spinDispersion->value(); - mat->glass = ui->checkGlass->isChecked(); - //emit changed(); -} - - -void MaterialEditor::setMaterial(Material * m) { - if (ignore_next > 0) { - //ignore_next = false; - return; - } - active = false; - mat = m; - setEnabled(m); - if (!mat) return; - ui->mapDiffuse ->setColor(mat->color_diffuse ); - ui->mapEmission->setColor(mat->color_emission); - ui->spinTransparent->setValue(mat->transparency); - ui->spinReflect->setValue(mat->reflectivity); - ui->spinIOF->setValue(mat->iof); - ui->spinDispersion->setValue(mat->dispersion); - ui->checkGlass->setChecked(mat->glass); - ui->mapDiffuse ->setMap(&(mat->map_diffuse )); - ui->mapNormal ->setMap(&(mat->map_normal )); - ui->mapMetalness->setMap(&(mat->map_metalness)); - ui->mapRoughness->setMap(&(mat->map_roughness)); - ui->mapEmission ->setMap(&(mat->map_emission )); - ui->mapRelief ->setMap(&(mat->map_relief )); - /*ui->lineReflFront->setProperty("GLpath", mat->map_reflection.path(0)); ui->lineReflFront->setText(QFileInfo(mat->map_reflection.path(0)).fileName()); - ui->lineReflBack->setProperty("GLpath", mat->map_reflection.path(1)); ui->lineReflBack->setText(QFileInfo(mat->map_reflection.path(1)).fileName()); - ui->lineReflLeft->setProperty("GLpath", mat->map_reflection.path(2)); ui->lineReflLeft->setText(QFileInfo(mat->map_reflection.path(2)).fileName()); - ui->lineReflRight->setProperty("GLpath", mat->map_reflection.path(3)); ui->lineReflRight->setText(QFileInfo(mat->map_reflection.path(3)).fileName()); - ui->lineReflTop->setProperty("GLpath", mat->map_reflection.path(4)); ui->lineReflTop->setText(QFileInfo(mat->map_reflection.path(4)).fileName()); - ui->lineReflBottom->setProperty("GLpath", mat->map_reflection.path(5)); ui->lineReflBottom->setText(QFileInfo(mat->map_reflection.path(5)).fileName()); - */active = true; -} - -/* -Material MaterialEditor::material() { - Material m; - mat->color_diffuse = ui->colorDiffuse ->color(); - mat->color_specular = ui->colorSpecular->color(); - mat->color_emission = ui->colorEmission->color(); - mat->transparency = ui->spinTransparent->value(); - mat->reflectivity = ui->spinReflect->value(); - mat->iof = ui->spinIOF->value(); - mat->dispersion = ui->spinDispersion->value(); - mat->glass = ui->checkGlass->isChecked(); - mat->map_diffuse = ui->mapDiffuse->map(); - mat->map_normal = ui->mapNormal->map(); - mat->map_specular = ui->mapSpecular->map(); - mat->map_roughness = ui->mapRoughness->map(); - mat->map_emission = ui->mapEmission->map(); - mat->map_relief = ui->mapRelief->map(); - mat->map_reflection.setPath(0, ui->lineReflFront->property("GLpath").toString()); - mat->map_reflection.setPath(1, ui->lineReflBack->property("GLpath").toString()); - mat->map_reflection.setPath(2, ui->lineReflLeft->property("GLpath").toString()); - mat->map_reflection.setPath(3, ui->lineReflRight->property("GLpath").toString()); - mat->map_reflection.setPath(4, ui->lineReflTop->property("GLpath").toString()); - mat->map_reflection.setPath(5, ui->lineReflBottom->property("GLpath").toString()); - return m; -} -*/ - -void MaterialEditor::on_buttonReflFrontSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflFront->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineReflFront->setProperty("GLpath", str); - ui->lineReflFront->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflBackSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflBack->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineReflBack->setProperty("GLpath", str); - ui->lineReflBack->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflLeftSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflLeft->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineReflLeft->setProperty("GLpath", str); - ui->lineReflLeft->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflRightSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflRight->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineReflRight->setProperty("GLpath", str); - ui->lineReflRight->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflTopSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflTop->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineReflTop->setProperty("GLpath", str); - ui->lineReflTop->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflBottomSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflBottom->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineReflBottom->setProperty("GLpath", str); - ui->lineReflBottom->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflFrontClear_clicked() { - ui->lineReflFront->setText(""); - ui->lineReflFront->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflBackClear_clicked() { - ui->lineReflBack->setText(""); - ui->lineReflBack->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflLeftClear_clicked() { - ui->lineReflLeft->setText(""); - ui->lineReflLeft->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflRightClear_clicked() { - ui->lineReflRight->setText(""); - ui->lineReflRight->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflTopClear_clicked() { - ui->lineReflTop->setText(""); - ui->lineReflTop->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonReflBottomClear_clicked() { - ui->lineReflBottom->setText(""); - ui->lineReflBottom->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonLoadCubeDir_clicked() { - QString dir = QFileDialog::getExistingDirectory(this, "Select directory", ui->lineReflFront->property("GLpath").toString()); - if (dir.isEmpty()) return; - /*CubeTexture cb(0); - cb.loadPathesFromDirectory(dir); - active = false; - ui->lineReflFront->setProperty("GLpath", cb.path(0)); ui->lineReflFront->setText(QFileInfo(cb.path(0)).fileName()); - ui->lineReflBack->setProperty("GLpath", cb.path(1)); ui->lineReflBack->setText(QFileInfo(cb.path(1)).fileName()); - ui->lineReflLeft->setProperty("GLpath", cb.path(2)); ui->lineReflLeft->setText(QFileInfo(cb.path(2)).fileName()); - ui->lineReflRight->setProperty("GLpath", cb.path(3)); ui->lineReflRight->setText(QFileInfo(cb.path(3)).fileName()); - ui->lineReflTop->setProperty("GLpath", cb.path(4)); ui->lineReflTop->setText(QFileInfo(cb.path(4)).fileName()); - ui->lineReflBottom->setProperty("GLpath", cb.path(5)); ui->lineReflBottom->setText(QFileInfo(cb.path(5)).fileName());*/ - active = true; - materialChanged(); -} diff --git a/qglengine/widgets/material_editor.h b/qglengine/widgets/material_editor.h deleted file mode 100644 index 16bc29d..0000000 --- a/qglengine/widgets/material_editor.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - QGL MaterialEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef MATERIAL_EDITOR_H -#define MATERIAL_EDITOR_H - -#include -#include "gltypes.h" - -namespace Ui { - class MaterialEditor; -} - -class MaterialEditor: public QWidget -{ - friend class MaterialsEditor; - Q_OBJECT -public: - explicit MaterialEditor(QWidget * parent = 0); - - void setMaterial(Material * m); - -protected: - void changeEvent(QEvent * e); - - bool active; - int ignore_next; - Ui::MaterialEditor * ui; - Material * mat; - -private slots: - void materialChanged(); - void on_buttonReflFrontSelect_clicked(); - void on_buttonReflFrontClear_clicked(); - void on_buttonReflBackSelect_clicked(); - void on_buttonReflBackClear_clicked(); - void on_buttonReflLeftSelect_clicked(); - void on_buttonReflLeftClear_clicked(); - void on_buttonReflRightSelect_clicked(); - void on_buttonReflRightClear_clicked(); - void on_buttonReflTopSelect_clicked(); - void on_buttonReflTopClear_clicked(); - void on_buttonReflBottomSelect_clicked(); - void on_buttonReflBottomClear_clicked(); - void on_buttonLoadCubeDir_clicked(); - -signals: - void changed(); - -}; - -#endif // MATERIAL_EDITOR_H diff --git a/qglengine/widgets/material_editor.ui b/qglengine/widgets/material_editor.ui deleted file mode 100644 index 307d6a7..0000000 --- a/qglengine/widgets/material_editor.ui +++ /dev/null @@ -1,637 +0,0 @@ - - - MaterialEditor - - - - 0 - 0 - 435 - 535 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - font:normal; - - - - - - - Qt::Horizontal - - - - - - - font:normal; - - - - - - - Qt::Horizontal - - - - - - - font:normal; - - - - - - - Qt::Horizontal - - - - - - - font:normal; - - - - - - - Qt::Horizontal - - - - - - - font:normal; - - - - - - - Qt::Horizontal - - - - - - - font:normal; - - - - - - - Qt::Horizontal - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Glass - - - - - - - Transparency - - - - - - - 1.000000000000000 - - - 2 - - - 0.010000000000000 - - - 0.100000000000000 - - - - - - - Reflectivity - - - - - - - 1.000000000000000 - - - 2 - - - 0.010000000000000 - - - 0.100000000000000 - - - - - - - IOF - - - - - - - 2.000000000000000 - - - 1.000000000000000 - - - 2 - - - 0.010000000000000 - - - 0.100000000000000 - - - - - - - Dispersion - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - 2 - - - 0.010000000000000 - - - 0.100000000000000 - - - - - - - Reflection map - - - - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - Front: - - - - - - - Back: - - - - - - - Left: - - - - - - - Right: - - - - - - - Top: - - - - - - - Bottom: - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - load from directory - - - - - - - - - - - - - SpinSlider - QWidget -
    spinslider.h
    -
    - - MaterialMapEditor - QWidget -
    material_map_editor.h
    - 1 - - changed() - -
    -
    - - - - spinTransparent - valueChanged(double) - MaterialEditor - materialChanged() - - - 433 - 468 - - - 283 - 149 - - - - - spinReflect - valueChanged(double) - MaterialEditor - materialChanged() - - - 433 - 497 - - - 284 - 174 - - - - - spinIOF - valueChanged(double) - MaterialEditor - materialChanged() - - - 433 - 526 - - - 284 - 236 - - - - - checkGlass - toggled(bool) - MaterialEditor - materialChanged() - - - 433 - 439 - - - 284 - 84 - - - - - spinDispersion - valueChanged(double) - MaterialEditor - materialChanged() - - - 433 - 555 - - - 326 - 288 - - - - - mapDiffuse - changed() - MaterialEditor - materialChanged() - - - 421 - 69 - - - 434 - 63 - - - - - mapMetalness - changed() - MaterialEditor - materialChanged() - - - 421 - 189 - - - 434 - 143 - - - - - mapEmission - changed() - MaterialEditor - materialChanged() - - - 421 - 338 - - - 434 - 216 - - - - - mapNormal - changed() - MaterialEditor - materialChanged() - - - 421 - 129 - - - 434 - 260 - - - - - mapRelief - changed() - MaterialEditor - materialChanged() - - - 421 - 398 - - - 434 - 304 - - - - - mapRoughness - changed() - MaterialEditor - materialChanged() - - - 421 - 249 - - - 434 - 250 - - - - - - materialChanged() - -
    diff --git a/qglengine/widgets/material_map_editor.cpp b/qglengine/widgets/material_map_editor.cpp deleted file mode 100644 index 3768d82..0000000 --- a/qglengine/widgets/material_map_editor.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - QGL MaterialMapEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "material_map_editor.h" -#include "ui_material_map_editor.h" -#include "gltexture_manager.h" -#include "glmaterial.h" - - -MaterialMapEditor::MaterialMapEditor(QWidget * parent): QWidget(parent) { - ui = new Ui::MaterialMapEditor(); - ui->setupUi(this); - ui->widgetMap->hide(); - active = true; -} - - -void MaterialMapEditor::changeEvent(QEvent * e) { - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} - - -void MaterialMapEditor::resizeEvent(QResizeEvent * e) { - QSize sz = preferredIconSize(6, this); - ui->iconedLabel->setFixedSize(sz); - ui->iconedLabel->setIconSize(sz); -} - - -void MaterialMapEditor::updateIcon() { - ui->iconedLabel->setIcon(QIcon(TextureManager::findFile(ui->linePath->property("GLpath").toString()))); -} - - -void MaterialMapEditor::mapChanged() { - if (!active || !map) return; - active = false; - map->use_bitmap = ui->checkMap->isChecked(); - if (ui->checkMap->isChecked()) { - map->color_amount = ui->sliderAmount->value(); - map->color_offset = ui->sliderOffset->value(); - } else { - map->color_amount = ui->sliderValue->value(); - map->color_offset = 0.f; - } - map->bitmap_scale.setX(ui->spinScaleX->value()); - map->bitmap_scale.setY(ui->spinScaleY->value()); - active = true; - emit changed(); -} - - -void MaterialMapEditor::setMap(Map * m) { - active = false; - map = m; - setEnabled(m); - if (!map) return; - ui->stackedWidget->setCurrentIndex(map->use_bitmap ? 1 : 0); - ui->checkMap->setChecked(map->use_bitmap); - ui->sliderValue->setValue(map->color_amount); - ui->sliderAmount->setValue(map->color_amount); - ui->sliderOffset->setValue(map->color_offset); - ui->spinScaleX->setValue(map->bitmap_scale.x()); - ui->spinScaleY->setValue(map->bitmap_scale.y()); - ui->linePath->setProperty("GLpath", map->bitmap_path); ui->linePath->setText(QFileInfo(map->bitmap_path).fileName()); - updateIcon(); - active = true; -} - - -void MaterialMapEditor::configure(QString title, bool has_color) { - ui->labelTitle->setText(title); - ui->colorButton->setVisible(has_color); -} - - -void MaterialMapEditor::setColor(QColor c) { - active = false; - ui->colorButton->setColor(c); - active = true; -} - - -QColor MaterialMapEditor::color() const { - return ui->colorButton->color(); -} - -/* -Map MaterialMapEditor::map() { - Map m; - map->color_amount = ui->sliderAmount->value(); - map->color_offset = ui->sliderOffset->value(); - map->bitmap_scale.setX(ui->spinScaleX->value()); - map->bitmap_scale.setY(ui->spinScaleY->value()); - map->bitmap_path = ui->linePath->property("GLpath").toString(); - return m; -} -*/ - -void MaterialMapEditor::on_buttonSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->linePath->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->linePath->setProperty("GLpath", str); - ui->linePath->setText(QFileInfo(str).fileName()); - map->setBitmapPath(str); - updateIcon(); - mapChanged(); -} - - -void MaterialMapEditor::on_buttonClear_clicked() { - ui->linePath->setText(""); - ui->linePath->setProperty("GLpath", ""); - map->clearBitmap(); - updateIcon(); - mapChanged(); -} - - -void MaterialMapEditor::on_checkMap_toggled(bool checked) { - if (checked) { - ui->sliderAmount->setValue(ui->sliderValue->value()); - resizeEvent(0); - } else - ui->sliderValue->setValue(ui->sliderAmount->value()); - ui->stackedWidget->setCurrentIndex(checked ? 1 : 0); - mapChanged(); -} diff --git a/qglengine/widgets/material_map_editor.h b/qglengine/widgets/material_map_editor.h deleted file mode 100644 index 8175247..0000000 --- a/qglengine/widgets/material_map_editor.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - QGL MaterialMapEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef MATERIAL_MAP_EDITOR_H -#define MATERIAL_MAP_EDITOR_H - -#include -#include "gltypes.h" - -namespace Ui { - class MaterialMapEditor; -} - -class MaterialMapEditor: public QWidget -{ - Q_OBJECT -public: - explicit MaterialMapEditor(QWidget * parent = 0); - - void setMap(Map * m); - void configure(QString title, bool has_color = false); - void setColor(QColor c); - QColor color() const; - -protected: - void changeEvent(QEvent * e); - void resizeEvent(QResizeEvent * e); - void updateIcon(); - - bool active; - Ui::MaterialMapEditor * ui; - Map * map; - -private slots: - void mapChanged(); - void on_buttonSelect_clicked(); - void on_buttonClear_clicked(); - void on_checkMap_toggled(bool checked); - -signals: - void changed(); - -}; - -#endif // MATERIAL_MAP_EDITOR_H diff --git a/qglengine/widgets/material_map_editor.ui b/qglengine/widgets/material_map_editor.ui deleted file mode 100644 index 33ca383..0000000 --- a/qglengine/widgets/material_map_editor.ui +++ /dev/null @@ -1,506 +0,0 @@ - - - MaterialMapEditor - - - - 0 - 0 - 725 - 218 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - 0 - 0 - - - - font: bold; - - - title: - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - 2 - - - 0.050000000000000 - - - 0.200000000000000 - - - 0.000000000000000 - - - 1.000000000000000 - - - - - - - - - - - - - 0 - 0 - - - - Map - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - IconedLabel::RightToLeft - - - - - - - - - 2 - - - - - - - - - :/icons/edit-delete.png:/icons/edit-delete.png - - - - - - - - :/icons/document-open.png:/icons/document-open.png - - - - - - - - - Amount: - - - - - - - -1.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - 2 - - - 0.050000000000000 - - - 0.200000000000000 - - - -99.000000000000000 - - - 99.000000000000000 - - - - - - - Offset: - - - - - - - -1.000000000000000 - - - 1.000000000000000 - - - 2 - - - 0.050000000000000 - - - 0.200000000000000 - - - -99.000000000000000 - - - 99.000000000000000 - - - - - - - - - - 0 - 0 - - - - Scale X: - - - - - - - 9999.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 20 - 20 - - - - - - - - - 0 - 0 - - - - Scale Y: - - - - - - - 9999.000000000000000 - - - 0.100000000000000 - - - 1.000000000000000 - - - - - - - Qt::Horizontal - - - QSizePolicy::Expanding - - - - 1 - 20 - - - - - - - - - - - - - - - - SpinSlider - QWidget -
    spinslider.h
    -
    - - ColorButton - QPushButton -
    colorbutton.h
    -
    - - IconedLabel - QFrame -
    iconedlabel.h
    -
    -
    - - - - - - - linePath - textChanged(QString) - MaterialMapEditor - mapChanged() - - - 598 - 55 - - - 99 - 73 - - - - - sliderAmount - valueChanged(double) - MaterialMapEditor - mapChanged() - - - 655 - 87 - - - 512 - 37 - - - - - sliderOffset - valueChanged(double) - MaterialMapEditor - mapChanged() - - - 655 - 116 - - - 511 - 65 - - - - - spinScaleX - valueChanged(double) - MaterialMapEditor - mapChanged() - - - 491 - 146 - - - 332 - 164 - - - - - spinScaleY - valueChanged(double) - MaterialMapEditor - mapChanged() - - - 647 - 146 - - - 493 - 164 - - - - - checkMap - toggled(bool) - sliderValue - setHidden(bool) - - - 693 - 15 - - - 626 - 14 - - - - - checkMap - toggled(bool) - widgetMap - setVisible(bool) - - - 686 - 9 - - - 695 - 62 - - - - - sliderValue - valueChanged(double) - MaterialMapEditor - mapChanged() - - - 99 - 15 - - - 130 - 28 - - - - - colorButton - colorChanged(QColor) - MaterialMapEditor - mapChanged() - - - 60 - 11 - - - 75 - 27 - - - - - - mapChanged() - -
    diff --git a/qglengine/widgets/materials_editor.cpp b/qglengine/widgets/materials_editor.cpp deleted file mode 100644 index 467e613..0000000 --- a/qglengine/widgets/materials_editor.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - QGL MaterialsEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "materials_editor.h" -#include "ui_materials_editor.h" -#include "material_editor.h" -#include "qglview.h" -#include "glmaterial.h" -#include -#include -#include - - -MaterialsEditor::MaterialsEditor(QWidget * parent): QWidget(parent) { - ui = new Ui::MaterialsEditor(); - ui->setupUi(this); - ui->widgetMaterial->setMaterial(0); - ui->scrollArea->viewport()->setAutoFillBackground(false); - ui->scrollAreaWidgetContents->setAutoFillBackground(false); - view = 0; -} - - -void MaterialsEditor::assignQGLView(QGLView * v) { - view = v; - connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); - connect(view, SIGNAL(materialsChanged()), this, SLOT(materialsChanged())); - connect(view, SIGNAL(materialThumbnailCreated(Material*)), this, SLOT(materialThumbnailCreated(Material*))); - materialsChanged(); -} - - -bool MaterialsEditor::event(QEvent * e) { - if (e->type() == QEvent::FontChange || e->type() == QEvent::Polish) { - QSize sz = preferredIconSize(1.5, this); - ui->comboMaterial->setIconSize(sz * 3); - ui->buttonRename->setIconSize(sz); - ui->buttonAdd ->setIconSize(sz); - ui->buttonClone ->setIconSize(sz); - ui->buttonDelete->setIconSize(sz); - ui->buttonAssign->setIconSize(sz); - ui->buttonUnset ->setIconSize(sz); - } - return QWidget::event(e); -} - - -void MaterialsEditor::changeEvent(QEvent * e) { - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} - - -Material * MaterialsEditor::currentMaterial() { - if (!view) return 0; - int ind = ui->comboMaterial->currentIndex(); - QVector mats = view->scene()->getMaterials(); - if (ind < 0 || ind >= mats.size()) return 0; - return mats[ind]; -} - - -void MaterialsEditor::selectMaterial(Material * m) { - if (!m) { - ui->comboMaterial->setCurrentIndex(-1); - return; - } - for (int i = 0; i < ui->comboMaterial->count(); ++i) { - if ((Material*)(ui->comboMaterial->itemData(i, Qt::UserRole + 1).value()) == m) { - ui->comboMaterial->setCurrentIndex(i); - break; - } - } -} - - -int MaterialsEditor::indexByMaterial(Material * m) { - if (!m) return -1; - for (int i = 0; i < ui->comboMaterial->count(); ++i) { - if ((Material*)(ui->comboMaterial->itemData(i, Qt::UserRole + 1).value()) == m) - return i; - } - return -1; -} - - -void MaterialsEditor::selectionChanged() { - if (!view) return; - //qDebug() << "selectionChanged"; - ObjectBase * o = view->selectedObject(); - if (o) selectMaterial(o->material()); -} - - -void MaterialsEditor::materialsChanged() { - if (ui->widgetMaterial->ignore_next > 0) { - ui->widgetMaterial->ignore_next--; - return; - } - Material * cm = currentMaterial(); - ui->comboMaterial->clear(); - if (!view) return; - QVector mats = view->scene()->getMaterials(); - for (int i = 0; i < mats.size(); ++i) { - Material * m = mats[i]; - ui->comboMaterial->addItem(QString("[%1] " + m->name).arg(i + 1), QVariant(m->name)); - ui->comboMaterial->setItemData(i, QVariant(quintptr(m)), Qt::UserRole + 1); - ui->comboMaterial->setItemIcon(i, QIcon(QPixmap::fromImage(view->materialThumbnail(m)))); - if (cm == m) ui->comboMaterial->setCurrentIndex(i); - } - -} - - -void MaterialsEditor::materialThumbnailCreated(Material * m) { - //qDebug() << "materialThumbnailCreated" << m; - int i = indexByMaterial(m); - if (i < 0 || !view) return; - //qDebug() << "materialThumbnailCreated set to" << i; - ui->comboMaterial->setItemIcon(i, QIcon(QPixmap::fromImage(view->materialThumbnail(m)))); -} - - -void MaterialsEditor::on_comboMaterial_currentIndexChanged(int index) { - ui->widgetMaterial->setMaterial(currentMaterial()); -} - - -void MaterialsEditor::on_buttonRename_clicked() { - Material * m = currentMaterial(); - if (!m) return; - QString nn = QInputDialog::getText(this, "Materials editor", "Input new name:", QLineEdit::Normal, m->name); - if (nn.isEmpty()) return; - m->name = nn; - int ind = ui->comboMaterial->currentIndex(); - ui->comboMaterial->setItemText(ind, QString("[%1] " + nn).arg(ind + 1)); - ui->comboMaterial->setItemData(ind, nn); -} - - -void MaterialsEditor::on_buttonAdd_clicked() { - if (!view) return; - Material * m = view->scene()->newMaterial(); - materialsChanged(); - selectMaterial(m); -} - - -void MaterialsEditor::on_buttonClone_clicked() { - if (!view) return; - Material * curm = currentMaterial(); - if (!curm) return; - Material * m = view->scene()->newMaterial(curm->name); - QString nm = m->name; - *m = *curm; - m->name = nm; - m->_changed = true; - materialsChanged(); - selectMaterial(m); -} - - -void MaterialsEditor::on_buttonDelete_clicked() { - if (!view) return; - Material * m = currentMaterial(); - if (!m) return; - view->scene()->removeMaterial(m); - materialsChanged(); -} - - -void MaterialsEditor::on_buttonAssign_clicked() { - if (!view) return; - Material * m = currentMaterial(); - ObjectBaseList ol = view->selectedObjects(); - foreach (ObjectBase * o, ol) - o->setMaterial(m, true); -} - - -void MaterialsEditor::on_buttonUnset_clicked() { - if (!view) return; - ObjectBaseList ol = view->selectedObjects(); - foreach (ObjectBase * o, ol) - o->setMaterial(0, true); -} diff --git a/qglengine/widgets/materials_editor.h b/qglengine/widgets/materials_editor.h deleted file mode 100644 index 5cd704d..0000000 --- a/qglengine/widgets/materials_editor.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - QGL MaterialsEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef MATERIALS_EDITOR_H -#define MATERIALS_EDITOR_H - -#include -#include "gltypes.h" - -namespace Ui { - class MaterialsEditor; -} - -class MaterialsEditor: public QWidget -{ - Q_OBJECT -public: - explicit MaterialsEditor(QWidget * parent = 0); - - void assignQGLView(QGLView * v); - -protected: - bool event(QEvent * e); - void changeEvent(QEvent * e); - Material * currentMaterial(); - void selectMaterial(Material * m); - int indexByMaterial(Material * m); - - Ui::MaterialsEditor * ui; - QGLView * view; - Material * mat; - -private slots: - void selectionChanged(); - void materialsChanged(); - void materialThumbnailCreated(Material * m); - - void on_comboMaterial_currentIndexChanged(int index); - void on_buttonRename_clicked(); - void on_buttonAdd_clicked(); - void on_buttonClone_clicked(); - void on_buttonDelete_clicked(); - void on_buttonAssign_clicked(); - void on_buttonUnset_clicked(); - -signals: - void changed(); - -}; - -#endif // MATERIALS_EDITOR_H diff --git a/qglengine/widgets/materials_editor.ui b/qglengine/widgets/materials_editor.ui deleted file mode 100644 index e416569..0000000 --- a/qglengine/widgets/materials_editor.ui +++ /dev/null @@ -1,251 +0,0 @@ - - - MaterialsEditor - - - - 0 - 0 - 386 - 520 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - 0 - 0 - - - - QComboBox::AdjustToMinimumContentsLengthWithIcon - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 40 - 10 - - - - - - - - Unset - - - - :/icons/dialog-cancel.png:/icons/dialog-cancel.png - - - - - - - Assign - - - - :/icons/go-jump.png:/icons/go-jump.png - - - - - - - Add - - - - :/icons/list-add.png:/icons/list-add.png - - - - - - - Delete - - - - :/icons/edit-delete.png:/icons/edit-delete.png - - - - - - - Rename ... - - - - :/icons/edit-rename.png:/icons/edit-rename.png - - - - - - - Clone - - - - :/icons/edit-copy.png:/icons/edit-copy.png - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - - - - - QFrame::NoFrame - - - true - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - 0 - 0 - 386 - 440 - - - - true - - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::Vertical - - - - 20 - 421 - - - - - - - - - - - - - EComboBox - QComboBox -
    ecombobox.h
    -
    - - MaterialEditor - QWidget -
    material_editor.h
    - 1 -
    -
    - - - - - - - - - materialChanged() - -
    diff --git a/qglengine/widgets/object_editor.cpp b/qglengine/widgets/object_editor.cpp deleted file mode 100644 index 6507ead..0000000 --- a/qglengine/widgets/object_editor.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - QGL ObjectEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "object_editor.h" -#include "ui_object_editor.h" -#include "qglview.h" -#include -#include - - -ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) { - ui = new Ui::ObjectEditor(); - ui->setupUi(this); - view = 0; - active = true; - ignore_next = false; - on_comboLightType_currentIndexChanged(0); - ui->widgetMain->setEnabled(false); - ui->labelAimDist->hide(); - ui->spinAimDist->hide(); - - QObjectList ol; - ol << ui->spinPosX << ui->spinPosY << ui->spinPosZ << - ui->spinRotationX << ui->spinRotationY << ui->spinRotationZ << - ui->spinScaleX << ui->spinScaleY << ui->spinScaleZ; - foreach (QObject * o, ol) - connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinChanged(double))); - - ol.clear(); - ol << ui->spinLightIntensity << ui->spinLightDecayConst << ui->spinLightDecayLinear << - ui->spinLightDecayQuadratic << ui->spinLightAngleStart << ui->spinLightAngleEnd << - ui->spinAimDist; - foreach (QObject * o, ol) - connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinLightChanged(double))); - - ol.clear(); - ol << ui->spinCameraFOV << ui->spinCameraDepthStart << ui->spinCameraRoll << ui->spinAimDist; - foreach (QObject * o, ol) - connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinCameraChanged(double))); - - ol.clear(); - ol << ui->checkVisible << ui->checkCastShadows << ui->checkReceiveShadows << - ui->checkAcceptLight << ui->checkAcceptFog << - ui->checkCameraMirrorX << ui->checkCameraMirrorY; - foreach (QObject * o, ol) - connect(o, SIGNAL(toggled(bool)), this, SLOT(checkChanged(bool))); - -} - - -void ObjectEditor::assignQGLView(QGLView * v) { - view = v; - connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); - connect(view, SIGNAL(objectsPositionChanged()), this, SLOT(selectionChanged())); - connect(view->scene(), SIGNAL(treeChanged()), this, SLOT(selectionChanged())); - selectionChanged(); -} - - -void ObjectEditor::changeEvent(QEvent * e) { - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} - - -void ObjectEditor::selectionChanged() { - if (ignore_next) { - ignore_next = false; - return; - } - ui->widgetMain->setEnabled(false); - if (!view) return; - ObjectBaseList sol = view->selectedObjects(true); - if (sol.isEmpty()) { - ui->labelTitle->setText(tr("[No selected]")); - return; - } - ui->widgetMain->setEnabled(true); - if (sol.size() == 1) { - setObject(sol[0]); - return; - } - bool hl = !view->selectedLights().isEmpty(), hc = !view->selectedCameras().isEmpty(); - ui->groupLight ->setVisible(hl); - ui->groupCamera ->setVisible(hc); - ui->labelAimDist->setVisible(hl || hc); - ui->spinAimDist ->setVisible(hl || hc); - ui->labelTitle->setText(tr("[%1 objects]").arg(sol.size())); -} - - -void ObjectEditor::setObject(ObjectBase * o) { - active = false; - ui->labelTitle->setText(o->name()); - ui->spinPosX->setValue(o->posX()); - ui->spinPosY->setValue(o->posY()); - ui->spinPosZ->setValue(o->posZ()); - ui->spinRotationX->setValue(o->rotationX()); - ui->spinRotationY->setValue(o->rotationY()); - ui->spinRotationZ->setValue(o->rotationZ()); - ui->spinScaleX->setValue(o->scaleX()); - ui->spinScaleY->setValue(o->scaleY()); - ui->spinScaleZ->setValue(o->scaleZ()); - ui->checkVisible->setChecked(o->isVisible()); - ui->checkAcceptLight->setChecked(o->isAcceptLight()); - ui->checkAcceptFog->setChecked(o->isAcceptFog()); - ui->checkCastShadows->setChecked(o->isCastShadows()); - ui->checkReceiveShadows->setChecked(o->isReceiveShadows()); - ui->buttonColor->setColor(o->color()); - bool is_l = o->type() == ObjectBase::glLight; - bool is_c = o->type() == ObjectBase::glCamera; - ui->labelAimDist->setVisible(is_l || is_c); - ui->spinAimDist ->setVisible(is_l || is_c); - ui->groupLight ->setVisible(is_l); - ui->groupCamera ->setVisible(is_c); - if (is_l) { - Light * l = globject_cast(o); - //bool is_dir = l->light_type == Light::Directional, is_cone = l->light_type == Light::Cone; - ui->comboLightType->setCurrentIndex(l->light_type); - ui->spinLightIntensity->setValue(l->intensity); - ui->spinLightDecayConst->setValue(l->decay_const); - ui->spinLightDecayLinear->setValue(l->decay_linear); - ui->spinLightDecayQuadratic->setValue(l->decay_quadratic); - ui->spinLightAngleStart->setValue(l->angle_start); - ui->spinLightAngleEnd->setValue(l->angle_end); - ui->spinAimDist->setValue(l->distance()); - on_comboLightType_currentIndexChanged(ui->comboLightType->currentIndex()); - } - if (is_c) { - Camera * c = globject_cast(o); - ui->checkCameraMirrorX->setChecked(c->isMirrorX()); - ui->checkCameraMirrorY->setChecked(c->isMirrorY()); - ui->spinCameraFOV->setValue(c->FOV()); - ui->spinCameraRoll->setValue(c->angleRoll()); - ui->spinCameraDepthStart->setValue(c->depthStart()); - ui->spinAimDist->setValue(c->distance()); - } - active = true; -} - - -void ObjectEditor::on_spinLightAngleStart_valueChanged(double v) { - if (ui->spinLightAngleEnd->value() < v) - ui->spinLightAngleEnd->setValue(v); -} - - -void ObjectEditor::on_spinLightAngleEnd_valueChanged(double v) { - if (ui->spinLightAngleStart->value() > v) - ui->spinLightAngleStart->setValue(v); -} - - -void ObjectEditor::on_comboLightType_currentIndexChanged(int index) { - bool ang = (index == Light::Cone); - ui->labelLightAngle ->setVisible(ang); - ui->labelLightAngleDash->setVisible(ang); - ui->spinLightAngleStart->setVisible(ang); - ui->spinLightAngleEnd ->setVisible(ang); - if (!view || !active) return; - QList sll = view->selectedLights(); - foreach (Light * o, sll) { - o->light_type = (Light::Type)index; - o->apply(); - } -} - - -void ObjectEditor::on_buttonColor_colorChanged(const QColor & v) { - if (!view || !active) return; - ObjectBaseList sol = view->selectedObjects(); - foreach (ObjectBase * o, sol) - o->setColor(v); - QList sll = view->selectedLights(); - foreach (Light * o, sll) - o->apply(); -} - - -void ObjectEditor::spinChanged(double v) { - if (!view || !active) return; - ObjectBaseList sol = view->selectedObjects(true); - QObject * s = sender(); - foreach (ObjectBase * o, sol) { - if (s == ui->spinPosX ) o->setPosX (v); - if (s == ui->spinPosY ) o->setPosY (v); - if (s == ui->spinPosZ ) o->setPosZ (v); - if (s == ui->spinRotationX) o->setRotationX(v); - if (s == ui->spinRotationY) o->setRotationY(v); - if (s == ui->spinRotationZ) o->setRotationZ(v); - if (s == ui->spinScaleX ) o->setScaleX (v); - if (s == ui->spinScaleY ) o->setScaleY (v); - if (s == ui->spinScaleZ ) o->setScaleZ (v); - } - ignore_next = true; -} - - -void ObjectEditor::spinLightChanged(double v) { - if (!view || !active) return; - QList sll = view->selectedLights(); - QObject * s = sender(); - foreach (Light * o, sll) { - if (s == ui->spinLightIntensity ) o->intensity = v; - if (s == ui->spinLightDecayConst ) o->decay_const = v; - if (s == ui->spinLightDecayLinear ) o->decay_linear = v; - if (s == ui->spinLightDecayQuadratic) o->decay_quadratic = v; - if (s == ui->spinLightAngleStart ) o->angle_start = v; - if (s == ui->spinLightAngleEnd ) o->angle_end = v; - if (s == ui->spinAimDist ) o->setDistance(v); - o->apply(); - } - ignore_next = true; -} - - -void ObjectEditor::spinCameraChanged(double v) { - if (!view || !active) return; - QList scl = view->selectedCameras(); - QObject * s = sender(); - foreach (Camera * o, scl) { - if (s == ui->spinCameraFOV ) o->setFOV (v); - if (s == ui->spinCameraRoll ) o->setAngleRoll (v); - if (s == ui->spinCameraDepthStart) o->setDepthStart(v); - if (s == ui->spinAimDist ) o->setDistance (v); - } - ignore_next = true; -} - - -void ObjectEditor::checkChanged(bool v) { - if (!view || !active) return; - ObjectBaseList sol = view->selectedObjects(); - QList scl = view->selectedCameras(); - QObject * s = sender(); - foreach (ObjectBase * o, sol) { - if (s == ui->checkVisible ) o->setVisible (v); - if (s == ui->checkCastShadows ) o->setCastShadows (v); - if (s == ui->checkReceiveShadows) o->setReceiveShadows(v); - if (s == ui->checkAcceptLight ) o->setAcceptLight (v); - if (s == ui->checkAcceptFog ) o->setAcceptFog (v); - } - foreach (Camera * o, scl) { - if (s == ui->checkCameraMirrorX ) o->setMirrorX(v); - if (s == ui->checkCameraMirrorY ) o->setMirrorY(v); - } -} diff --git a/qglengine/widgets/object_editor.h b/qglengine/widgets/object_editor.h deleted file mode 100644 index 89311f1..0000000 --- a/qglengine/widgets/object_editor.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - QGL ObjectEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef OBJECT_EDITOR_H -#define OBJECT_EDITOR_H - -#include -#include "globject.h" - -namespace Ui { - class ObjectEditor; -} - -class ObjectEditor: public QWidget -{ - Q_OBJECT -public: - explicit ObjectEditor(QWidget * parent = 0); - - void assignQGLView(QGLView * v); - -protected: - void changeEvent(QEvent * e); - void setObject(ObjectBase * o); - - Ui::ObjectEditor * ui; - QGLView * view; - bool active, ignore_next; - -private slots: - void selectionChanged(); - void on_spinLightAngleStart_valueChanged(double v); - void on_spinLightAngleEnd_valueChanged(double v); - - void on_comboLightType_currentIndexChanged(int index); - void on_buttonColor_colorChanged(const QColor &v); - void spinChanged(double v); - void spinLightChanged(double v); - void spinCameraChanged(double v); - void checkChanged(bool v); - -signals: - void changed(); - -}; - -#endif // OBJECT_EDITOR_H diff --git a/qglengine/widgets/object_editor.ui b/qglengine/widgets/object_editor.ui deleted file mode 100644 index 58ec410..0000000 --- a/qglengine/widgets/object_editor.ui +++ /dev/null @@ -1,782 +0,0 @@ - - - ObjectEditor - - - - 0 - 0 - 466 - 778 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - font: bold; - - - [No selected] - - - Qt::AlignCenter - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Position - - - - - - - 0 - 0 - - - - X: - - - - - - - - - - - 0 - 0 - - - - Y: - - - - - - - - - - - 0 - 0 - - - - Z: - - - - - - - - - - - - - Rotation - - - - - - - 0 - 0 - - - - X: - - - - - - - -360.000000000000000 - - - 360.000000000000000 - - - 1 - - - 4.500000000000000 - - - 90.000000000000000 - - - ° - - - QSlider::TicksAbove - - - 90 - - - - - - - - 0 - 0 - - - - Y: - - - - - - - -360.000000000000000 - - - 360.000000000000000 - - - 4.500000000000000 - - - 90.000000000000000 - - - ° - - - QSlider::TicksAbove - - - 90 - - - - - - - - 0 - 0 - - - - Z: - - - - - - - -360.000000000000000 - - - 360.000000000000000 - - - 4.500000000000000 - - - 90.000000000000000 - - - ° - - - QSlider::TicksAbove - - - 90 - - - - - - - - - - Scale - - - - - - - 0 - 0 - - - - X: - - - - - - - - - - - 0 - 0 - - - - Y: - - - - - - - - - - - 0 - 0 - - - - Z: - - - - - - - - - - - - - - - Accept fog - - - - - - - Accept light - - - - - - - Visible - - - - - - - Cast shadows - - - - - - - Receive shadows - - - - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - 0 - 0 - - - - Color: - - - - - - - - - - - 0 - 0 - - - - Aim distance: - - - - - - - - - - - - Light - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Type: - - - - - - - - Omni - - - - - Cone - - - - - Directional - - - - - - - - Intensity: - - - - - - - 0.000000000000000 - - - 10.000000000000000 - - - 1.000000000000000 - - - 3 - - - 0.100000000000000 - - - 1.000000000000000 - - - true - - - 999.000000000000000 - - - - - - - Decay ^0: - - - - - - - 0.000000000000000 - - - 10.000000000000000 - - - 1.000000000000000 - - - 3 - - - 0.100000000000000 - - - 1.000000000000000 - - - true - - - 999.000000000000000 - - - - - - - Decay ^1: - - - - - - - 0.000000000000000 - - - 10.000000000000000 - - - 0.000000000000000 - - - 3 - - - 0.100000000000000 - - - 1.000000000000000 - - - true - - - 999.000000000000000 - - - - - - - Decay ^2: - - - - - - - 0.000000000000000 - - - 10.000000000000000 - - - 0.000000000000000 - - - 3 - - - 0.100000000000000 - - - 1.000000000000000 - - - true - - - 999.000000000000000 - - - - - - - Angle: - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0.000000000000000 - - - 180.000000000000000 - - - 1 - - - 5.000000000000000 - - - 30.000000000000000 - - - ° - - - - - - - - - - - - - - - 0.000000000000000 - - - 180.000000000000000 - - - 1 - - - 5.000000000000000 - - - 30.000000000000000 - - - ° - - - - - - - - - - - - - Camera - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Depth start: - - - - - - - FOV: - - - - - - - 1.000000000000000 - - - 179.900000000000006 - - - 60.000000000000000 - - - 1 - - - 5.000000000000000 - - - 30.000000000000000 - - - ° - - - - - - - - - Mirror Y - - - - - - - Mirror X - - - - - - - - - 5 - - - 999999999.000000000000000 - - - 0.100000000000000 - - - - - - - -180.000000000000000 - - - 180.000000000000000 - - - 0.000000000000000 - - - 1 - - - 5.000000000000000 - - - 30.000000000000000 - - - ° - - - - - - - Roll: - - - - - - - - - - - - - - SpinSlider - QWidget -
    spinslider.h
    -
    - - ColorButton - QPushButton -
    colorbutton.h
    -
    - - ScrollSpinBox - QWidget -
    scroll_spin_box.h
    -
    -
    - - - - objectChanged() - -
    diff --git a/qglengine/widgets/primitiveeditor.cpp b/qglengine/widgets/primitiveeditor.cpp deleted file mode 100644 index 4613004..0000000 --- a/qglengine/widgets/primitiveeditor.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - QGL PrimitiveEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "primitiveeditor.h" -#include "ui_primitiveeditor.h" -#include -#include "glprimitives.h" -#include "glmesh.h" - - -PrimitiveEditor::PrimitiveEditor(QWidget *parent) : QWidget(parent), ui(new Ui::PrimitiveEditor) { - view = 0; - can_replace = false; - ui->setupUi(this); -#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) - ui->spinSegments->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); - ui->spinSegments2->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); -#endif - editors[Plane] << ui->widgetWidth; - editors[Plane] << ui->widgetLength; - editors[Cube] << ui->widgetWidth; - editors[Cube] << ui->widgetLength; - editors[Cube] << ui->widgetHeight; - editors[Ellipsoid] << ui->widgetRadius1; - editors[Ellipsoid] << ui->widgetSegments; - editors[Ellipsoid] << ui->widgetSegments2; - editors[Ellipsoid] << ui->widgetAngle; - editors[Disc] << ui->widgetRadius1; - editors[Disc] << ui->widgetSegments; - editors[Disc] << ui->widgetAngle; - editors[Cone] << ui->widgetRadius1; - editors[Cone] << ui->widgetHeight; - editors[Cone] << ui->widgetSegments; - editors[Cylinder] << ui->widgetRadius1; - editors[Cylinder] << ui->widgetHeight; - editors[Cylinder] << ui->widgetSegments; - editors[Cylinder] << ui->widgetAngle; - editors[Torus] << ui->widgetRadius1; - editors[Torus] << ui->widgetRadius2; - editors[Torus] << ui->widgetSegments; - editors[Torus] << ui->widgetSegments2; - editors[Torus] << ui->widgetAngle; - QSet all; - QMetaEnum me = metaObject()->enumerator(0); - for (int i=0; icomboPrimitives->addItem(me.key(i)); - all.unite(editors[(PrimitiveType)me.value(i)].toSet()); - } - all_editors = all.toList(); - foreach (QWidget * w, all_editors) { - if (w->layout()) w->layout()->setContentsMargins(0, layout()->spacing(), 0, 0); - } - - ui->comboPrimitives->setCurrentIndex(Plane); - on_comboPrimitives_currentIndexChanged(ui->comboPrimitives->currentIndex()); -} - - -PrimitiveEditor::~PrimitiveEditor() { - delete ui; -} - - -void PrimitiveEditor::assignQGLView(QGLView * v) { - view = v; - connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); - selectionChanged(); -} - - -Mesh * PrimitiveEditor::createMesh(QVariantList & params) { - Mesh * m = 0; - PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex(); - params << pt; - switch (pt) { - case Plane: - m = Primitive::plane(ui->spinWidth->value(), - ui->spinLength->value()); - params << ui->spinWidth->value() - << ui->spinLength->value(); - break; - case Cube: - m = Primitive::cube(ui->spinWidth->value(), - ui->spinLength->value(), - ui->spinHeight->value()); - params << ui->spinWidth->value() - << ui->spinLength->value() - << ui->spinHeight->value(); - break; - case Ellipsoid: - m = Primitive::ellipsoid(ui->spinSegments->value(), - ui->spinSegments2->value(), - ui->spinRadius->value(), - ui->spinAngle->value()); - params << ui->spinSegments->value() - << ui->spinSegments2->value() - << ui->spinRadius->value() - << ui->spinAngle->value(); - break; - case Disc: - m = Primitive::disc(ui->spinSegments->value(), - ui->spinRadius->value(), - ui->spinAngle->value()); - params << ui->spinSegments->value() - << ui->spinRadius->value() - << ui->spinAngle->value(); - break; - case Cone: - m = Primitive::cone(ui->spinSegments->value(), - ui->spinRadius->value(), - ui->spinHeight->value()); - params << ui->spinSegments->value() - << ui->spinRadius->value() - << ui->spinHeight->value(); - break; - case Cylinder: - m = Primitive::cylinder(ui->spinSegments->value(), - ui->spinRadius->value(), - ui->spinHeight->value(), - ui->spinAngle->value()); - params << ui->spinSegments->value() - << ui->spinRadius->value() - << ui->spinHeight->value() - << ui->spinAngle->value(); - break; - case Torus: - m = Primitive::torus(ui->spinSegments->value(), - ui->spinSegments2->value(), - ui->spinRadius->value(), - ui->spinRadius2->value(), - ui->spinAngle->value()); - params << ui->spinSegments->value() - << ui->spinSegments2->value() - << ui->spinRadius->value() - << ui->spinRadius2->value() - << ui->spinAngle->value(); - break; - default: return 0; - } - params << ui->flipNormals->isChecked(); - params << ui->colorButton->color(); - if (ui->flipNormals->isChecked()) - m->flipNormals(); - return m; -} - - -void PrimitiveEditor::showEditors() { - foreach (QWidget * w, all_editors) w->hide(); - PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex(); - QList wds = editors[pt]; - foreach (QWidget * w, wds) w->show(); -} - - -void PrimitiveEditor::selectionChanged() { - ObjectBase * so = view->selectedObject();\ - can_replace = false; - if (so) { - QVariantList vl = so->property("primitive", &can_replace).toList(); - if (can_replace && !vl.isEmpty()) { - PrimitiveType pt = (PrimitiveType)vl.takeFirst().toInt(); - ui->comboPrimitives->setCurrentIndex(pt); - switch (pt) { - case Plane: - ui->spinWidth->setValue(vl.takeFirst().toDouble()); - ui->spinLength->setValue(vl.takeFirst().toDouble()); - break; - case Cube: - ui->spinWidth->setValue(vl.takeFirst().toDouble()); - ui->spinLength->setValue(vl.takeFirst().toDouble()); - ui->spinHeight->setValue(vl.takeFirst().toDouble()); - break; - case Ellipsoid: - ui->spinSegments->setValue(vl.takeFirst().toDouble()); - ui->spinSegments2->setValue(vl.takeFirst().toDouble()); - ui->spinRadius->setValue(vl.takeFirst().toDouble()); - ui->spinAngle->setValue(vl.takeFirst().toDouble()); - break; - case Disc: - ui->spinSegments->setValue(vl.takeFirst().toDouble()); - ui->spinRadius->setValue(vl.takeFirst().toDouble()); - ui->spinAngle->setValue(vl.takeFirst().toDouble()); - break; - case Cone: - ui->spinSegments->setValue(vl.takeFirst().toDouble()); - ui->spinRadius->setValue(vl.takeFirst().toDouble()); - ui->spinHeight->setValue(vl.takeFirst().toDouble()); - break; - case Cylinder: - ui->spinSegments->setValue(vl.takeFirst().toDouble()); - ui->spinRadius->setValue(vl.takeFirst().toDouble()); - ui->spinHeight->setValue(vl.takeFirst().toDouble()); - ui->spinAngle->setValue(vl.takeFirst().toDouble()); - break; - case Torus: - ui->spinSegments->setValue(vl.takeFirst().toDouble()); - ui->spinSegments2->setValue(vl.takeFirst().toDouble()); - ui->spinRadius->setValue(vl.takeFirst().toDouble()); - ui->spinRadius2->setValue(vl.takeFirst().toDouble()); - ui->spinAngle->setValue(vl.takeFirst().toDouble()); - break; - } - ui->flipNormals->setChecked(vl.takeFirst().toBool()); - ui->colorButton->setColor(vl.takeFirst().value()); - } - } -} - - -void PrimitiveEditor::replaceMesh() { - if (!view) return; - if (!can_replace) return; - ObjectBase * so = view->selectedObject(); - if (!so) return; - QVariantList params; - Mesh * m = createMesh(params); - if (!m) return; - so->setMesh(m); - so->setColor(ui->colorButton->color()); - so->setName(ui->comboPrimitives->currentText()); - so->setProperty("primitive", params); - delete m; -} - - -void PrimitiveEditor::on_buttonAdd_clicked() { - if (!view) return; - QVariantList params; - Mesh * m = createMesh(params); - if (!m) return; - ObjectBase * o = new ObjectBase(m); - o->setColor(ui->colorButton->color()); - o->setName(ui->comboPrimitives->currentText()); - o->setProperty("primitive", params); - view->scene()->addObject(o); - view->scene()->selectObject(o); - delete m; -} - - -void PrimitiveEditor::on_comboPrimitives_currentIndexChanged(int index) { - showEditors(); -} diff --git a/qglengine/widgets/primitiveeditor.h b/qglengine/widgets/primitiveeditor.h deleted file mode 100644 index d91c77f..0000000 --- a/qglengine/widgets/primitiveeditor.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - QGL PrimitiveEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef PRIMITIVEEDITOR_H -#define PRIMITIVEEDITOR_H - -#include -#include "qglview.h" - - -namespace Ui { -class PrimitiveEditor; -} - - -class PrimitiveEditor : public QWidget { - Q_OBJECT -public: - enum PrimitiveType { - Plane, - Cube, - Ellipsoid, - Disc, - Cone, - Cylinder, - Torus - }; - Q_ENUMS(PrimitiveType) - - explicit PrimitiveEditor(QWidget *parent = nullptr); - ~PrimitiveEditor(); - - void assignQGLView(QGLView * v); - -protected: - Mesh * createMesh(QVariantList & params); - void showEditors(); - - Ui::PrimitiveEditor *ui; - QGLView * view; - QMap > editors; - QList all_editors; - bool can_replace; - -private slots: - void selectionChanged(); - void replaceMesh(); - void on_buttonAdd_clicked(); - void on_comboPrimitives_currentIndexChanged(int index); -}; - - -#endif // PRIMITIVEEDITOR_H diff --git a/qglengine/widgets/primitiveeditor.ui b/qglengine/widgets/primitiveeditor.ui deleted file mode 100644 index 2d2c9d9..0000000 --- a/qglengine/widgets/primitiveeditor.ui +++ /dev/null @@ -1,597 +0,0 @@ - - - PrimitiveEditor - - - - 0 - 0 - 360 - 536 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - - - 0 - - - 0 - - - - - Width: - - - - - - - 1.000000000000000 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Length: - - - - - - - 1.000000000000000 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Height - - - - - - - 1.000000000000000 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Radius 1: - - - - - - - 1.000000000000000 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Radius 2: - - - - - - - 1.000000000000000 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Angle: - - - - - - - 360.000000000000000 - - - 360.000000000000000 - - - 4.500000000000000 - - - 90.000000000000000 - - - ° - - - QSlider::TicksAbove - - - 90 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Segments: - - - - - - - 1 - - - 1000 - - - 1 - - - 16 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Segments 2: - - - - - - - 1 - - - 1000 - - - 1 - - - 16 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - Color: - - - - - - - - 255 - 255 - 255 - - - - - - - - - - - - - - Flip normals - - - - - - - Qt::Vertical - - - - 20 - 176 - - - - - - - - - - Add - - - - :/icons/list-add.png:/icons/list-add.png - - - - - - - - - - SpinSlider - QWidget -
    spinslider.h
    -
    - - ColorButton - QPushButton -
    colorbutton.h
    -
    - - EComboBox - QComboBox -
    ecombobox.h
    -
    - - ScrollSpinBox - QWidget -
    scroll_spin_box.h
    -
    -
    - - - - - - spinWidth - valueChanged(double) - PrimitiveEditor - replaceMesh() - - - 331 - 51 - - - 368 - 45 - - - - - spinLength - valueChanged(double) - PrimitiveEditor - replaceMesh() - - - 330 - 84 - - - 369 - 82 - - - - - spinHeight - valueChanged(double) - PrimitiveEditor - replaceMesh() - - - 334 - 116 - - - 366 - 114 - - - - - spinRadius - valueChanged(double) - PrimitiveEditor - replaceMesh() - - - 332 - 144 - - - 370 - 145 - - - - - spinRadius2 - valueChanged(double) - PrimitiveEditor - replaceMesh() - - - 334 - 186 - - - 371 - 181 - - - - - spinAngle - valueChanged(double) - PrimitiveEditor - replaceMesh() - - - 335 - 210 - - - 372 - 213 - - - - - spinSegments - valueChanged(int) - PrimitiveEditor - replaceMesh() - - - 329 - 246 - - - 370 - 247 - - - - - spinSegments2 - valueChanged(int) - PrimitiveEditor - replaceMesh() - - - 336 - 284 - - - 372 - 279 - - - - - flipNormals - toggled(bool) - PrimitiveEditor - replaceMesh() - - - 70 - 344 - - - 370 - 341 - - - - - comboPrimitives - currentIndexChanged(int) - PrimitiveEditor - replaceMesh() - - - 348 - 9 - - - 367 - 9 - - - - - colorButton - colorChanged(QColor) - PrimitiveEditor - replaceMesh() - - - 271 - 285 - - - 179 - 267 - - - - - - replaceMesh() - -
    diff --git a/qglengine/widgets/propertyeditor.cpp b/qglengine/widgets/propertyeditor.cpp deleted file mode 100644 index b4c568e..0000000 --- a/qglengine/widgets/propertyeditor.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* - QGL PropertyEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "propertyeditor.h" - - -QWidget * Delegate::widgetForProperty(QWidget * parent, const QModelIndex & index) const { - QWidget * w = 0; - int type = 0; - QVariant value = index.data(Qt::UserRole); - if (index.data(Qt::UserRole + 2).toString() == "__flags") return 0; - if (index.data(Qt::UserRole + 1).toString() == "__flag") { - qulonglong key = index.data(Qt::UserRole).toULongLong(); - value = index.parent().data(Qt::UserRole); - //QMetaProperty prop = index.parent().data(Qt::UserRole + 1).value(); - w = new QCheckBox(parent); type = 14; ((QCheckBox*)w)->setChecked(((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0)); - ((QCheckBox*)w)->setText("0x" + QString::number(key, 16).toUpper()); - connect((QCheckBox*)w, SIGNAL(clicked(bool)), this, SLOT(changedFlag())); - //qDebug() << prop.enumerator().name(); - } else { - if (value.canConvert()) { - PropertyValuePair prop = value.value(); - if (prop.first.isEnumType()) { - w = new QComboBox(parent); type = 13; ((QComboBox*)w)->setCurrentIndex(value.toInt()); - w->setProperty("__prop", QVariant::fromValue(prop.first)); - QMetaEnum menum = prop.first.enumerator(); - for (int i = 0; i < menum.keyCount(); ++i) { - ((QComboBox*)w)->addItem(QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")", menum.value(i)); - if (menum.value(i) == prop.second.toInt()) - ((QComboBox*)w)->setCurrentIndex(i); - } - connect((QComboBox*)w, SIGNAL(currentIndexChanged(int)), this, SLOT(changed())); - } - } else { - switch (value.type()) { - case QVariant::Int: w = new QSpinBox(parent); type = 2; ((QSpinBox*)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; - case QVariant::UInt: w = new QSpinBox(parent); type = 3; ((QSpinBox*)w)->setRange(0, 0xFFFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; - case QVariant::LongLong: w = new QSpinBox(parent); type = 4; ((QSpinBox*)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; - case QVariant::ULongLong: w = new QSpinBox(parent); type = 5; ((QSpinBox*)w)->setRange(0, 0xFFFFFFFF); connect((QSpinBox*)w, SIGNAL(valueChanged(int)), this, SLOT(changed())); break; - case QVariant::Double: w = new QDoubleSpinBox(parent); type = 6; ((QDoubleSpinBox*)w)->setRange(-999999999, 999999999); ((QDoubleSpinBox*)w)->setDecimals(3); connect((QDoubleSpinBox*)w, SIGNAL(valueChanged(double)), this, SLOT(changed())); break; - case QVariant::Bool: w = new QCheckBox(parent); type = 7; ((QCheckBox*)w)->setChecked(value.toBool()); connect((QCheckBox*)w, SIGNAL(toggled(bool)), this, SLOT(changed())); break; - case QVariant::Color: w = new ColorButton(parent); type = 8; ((ColorButton*)w)->setUseAlphaChannel(true); ((ColorButton*)w)->setColor(value.value()); connect((ColorButton*)w, SIGNAL(colorChanged(QColor)), this, SLOT(changed())); break; - case QVariant::Point: w = new QPointEdit(parent); type = 9; ((QPointEdit*)w)->setDecimals(0); ((QPointEdit*)w)->setValue(QPointF(value.toPoint())); connect((QPointEdit*)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed())); break; - case QVariant::PointF: w = new QPointEdit(parent); type = 10; ((QPointEdit*)w)->setDecimals(3); ((QPointEdit*)w)->setValue(value.toPointF()); connect((QPointEdit*)w, SIGNAL(valueChanged(QPointF)), this, SLOT(changed())); break; - case QVariant::Rect: w = new QRectEdit(parent); type = 11; ((QRectEdit*)w)->setDecimals(0); ((QRectEdit*)w)->setValue(QRectF(value.toRect())); connect((QRectEdit*)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed())); break; - case QVariant::RectF: w = new QRectEdit(parent); type = 12; ((QRectEdit*)w)->setDecimals(3); ((QRectEdit*)w)->setValue(value.toRectF()); connect((QRectEdit*)w, SIGNAL(valueChanged(QRectF)), this, SLOT(changed())); break; - case QVariant::String: default: w = new CLineEdit(parent); type = 1; ((CLineEdit*)w)->setDefaultText(value.toString()); connect((CLineEdit*)w, SIGNAL(textChanged(QString)), this, SLOT(changed())); break; - } - } - } - if (w == 0) return 0; - /*QPalette pal = w->palette(); - pal.setColor(QPalette::Window, Qt::white); - w->setPalette(pal);*/ - w->setAutoFillBackground(true); - w->setProperty("__type", type); - return w; -} - - -void Delegate::setWidgetProperty(QWidget * w, const QVariant & value) const { - if (w == 0) return; - switch (w->property("__type").toInt()) { - case 1: ((CLineEdit*)w)->setText(value.toString()); break; - case 2: case 3: case 4: case 5: ((QSpinBox*)w)->setValue(value.toInt()); break; - case 6: ((QDoubleSpinBox*)w)->setValue(value.toDouble()); break; - case 7: ((QCheckBox*)w)->setChecked(value.toBool()); break; - case 8: ((ColorButton*)w)->setColor(value.value()); break; - case 9: ((QPointEdit*)w)->setValue(value.value()); break; - case 10: ((QPointEdit*)w)->setValue(value.value()); break; - case 11: ((QRectEdit*)w)->setValue(value.value()); break; - case 12: ((QRectEdit*)w)->setValue(value.value()); break; - } -} - - -const QVariant Delegate::widgetProperty(QWidget * w) const { - if (w == 0) return QVariant(); - switch (w->property("__type").toInt()) { - case 1: return QVariant::fromValue(((CLineEdit*)w)->text()); break; - case 2: return QVariant::fromValue(((QSpinBox*)w)->value()); break; - case 3: return QVariant::fromValue(((QSpinBox*)w)->value()); break; - case 4: return QVariant::fromValue(((QSpinBox*)w)->value()); break; - case 5: return QVariant::fromValue(((QSpinBox*)w)->value()); break; - case 6: return QVariant::fromValue(((QDoubleSpinBox*)w)->value()); break; - case 7: return QVariant::fromValue(((QCheckBox*)w)->isChecked()); break; - case 8: return QVariant::fromValue(((ColorButton*)w)->color()); break; - case 9: return QVariant::fromValue(((QPointEdit*)w)->value().toPoint()); break; - case 10: return QVariant::fromValue(((QPointEdit*)w)->value()); break; - case 11: return QVariant::fromValue(((QRectEdit*)w)->value().toRect()); break; - case 12: return QVariant::fromValue(((QRectEdit*)w)->value()); break; - case 13: return QVariant::fromValue(PropertyValuePair(w->property("__prop").value(), ((QComboBox*)w)->itemData(((QComboBox*)w)->currentIndex()))); break; - default: return QVariant(); break; - } - return QVariant(); -} - - -void Delegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const { - if (index.data(Qt::UserRole + 1).toString() != "__flag") - model->setData(index, widgetProperty(editor), Qt::UserRole); -} - - -void Delegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { - QStyledItemDelegate::paint(painter, option, index); - QVariant value = index.data(Qt::UserRole); - QStyle * style = QApplication::style(); - QStyleOption * so = 0; - QStyleOptionComplex * soc = 0; - QString text; - QRect rect; - QPalette::ColorRole role = (option.state.testFlag(QStyle::State_Selected) && option.state.testFlag(QStyle::State_Active) ? QPalette::HighlightedText : QPalette::WindowText); - if (index.data(Qt::UserRole + 2).toString() == "__flags") { - text = "0x" + QString::number(value.toInt(), 16).toUpper(); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - return; - } - if (index.data(Qt::UserRole + 1) == "__flag") { - qulonglong key = index.data(Qt::UserRole).toULongLong(); - value = index.parent().data(Qt::UserRole); - so = new QStyleOptionButton(); - so->rect = option.rect; - so->palette = option.palette; - so->fontMetrics = option.fontMetrics; - ((QStyleOptionButton*)so)->state = (((value.toULongLong() & key) == key && key != 0) || (value.toULongLong() == 0 && key == 0) ? QStyle::State_On : QStyle::State_Off) | option.state; - ((QStyleOptionButton*)so)->text = "0x" + QString::number(key, 16).toUpper(); - if (option.state.testFlag(QStyle::State_Selected)) - so->palette.setColor(QPalette::WindowText, so->palette.color(QPalette::HighlightedText)); - style->drawControl(QStyle::CE_CheckBox, so, painter); - } else { - if (value.canConvert()) { - PropertyValuePair prop = value.value(); - if (prop.first.isEnumType()) { - QMetaEnum menum = prop.first.enumerator(); - for (int i = 0; i < menum.keyCount(); ++i) { - if (menum.value(i) == prop.second.toInt()) { - text = QString(menum.key(i)) + " (0x" + QString::number(menum.value(i), 16).toUpper() + ")"; - break; - } - } - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - } - } else { - switch (value.type()) { - case QVariant::Int: - text.setNum(value.toInt()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::UInt: - text.setNum(value.toUInt()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::LongLong: - text.setNum(value.toLongLong()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::ULongLong: - text.setNum(value.toULongLong()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::Double: - text.setNum(value.toDouble(), 'f', 3); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::Bool: - so = new QStyleOptionButton(); - so->rect = option.rect; - so->state = option.state; - so->palette = option.palette; - so->fontMetrics = option.fontMetrics; - ((QStyleOptionButton*)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off) | option.state; - style->drawControl(QStyle::CE_CheckBox, so, painter); - break; - case QVariant::Color: - rect = option.rect;//style->subElementRect(QStyle::QStyle::SE_FrameContents, so); - rect.setRect(rect.x() + 3, rect.y() + 3, rect.width() - 6, rect.height() - 6); - painter->fillRect(rect, ab); - painter->fillRect(rect, value.value()); - break; - case QVariant::Point: - text = pointString(value.toPoint()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::PointF: - text = pointString(value.toPointF()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::Rect: - text = rectString(value.toRect()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::RectF: - text = rectString(value.toRectF()); - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, text), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text, role); - break; - case QVariant::String: default: - style->drawItemText(painter, style->itemTextRect(option.fontMetrics, option.rect, Qt::AlignLeft | Qt::AlignVCenter, true, value.toString()), - Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, value.toString(), role); - break; - } - } - } - /*so = new QStyleOptionFrame(); - so->rect = option.rect; - so->state = option.state; - so->palette = option.palette; - so->fontMetrics = option.fontMetrics; - ((QStyleOptionFrame*)so)->state = (value.toBool() ? QStyle::State_On : QStyle::State_Off); - style->drawPrimitive(QStyle::PE_PanelLineEdit, so, painter); - style->drawPrimitive(QStyle::PE_FrameLineEdit, so, painter); - break;*/ - if (so != 0) delete so; - if (soc != 0) delete soc; - -} - - -void Delegate::changedFlag() { - QAbstractItemModel * model = const_cast(cmi.model()); - model->setData(cmi, qobject_cast(sender())->isChecked(), Qt::UserRole + 3); - QModelIndex p = cmi.parent(), mi; - int row = 0; - qulonglong val = 0; - QList chldr; - mi = p.child(row, 1); - while (mi.isValid()) { - chldr << mi; - model->setData(mi, !mi.data(Qt::UserRole + 4).toBool(), Qt::UserRole + 4); - mi = p.child(++row, 1); - } - bool cc = cmi.data(Qt::UserRole + 3).toBool(); - qulonglong cv = cmi.data(Qt::UserRole).toULongLong(); - //qDebug() << "*****"; - if (cc && cv == 0) { - val = 0; - //qDebug() << "null" << cv; - } else { - if (!cc && cv != 0) { - //qDebug() << "uncheck" << cv; - for (int i = 0; i < chldr.size(); ++i) { - if (chldr[i] == cmi) continue; - //qDebug() << (chldr[i].data(Qt::UserRole).toULongLong() & cv); - if (chldr[i].data(Qt::UserRole).toULongLong() & cv) - model->setData(chldr[i], false, Qt::UserRole + 3); - } - } - for (int i = 0; i < chldr.size(); ++i) { - //qDebug() << chldr[i].data(Qt::UserRole + 3).toBool(); - if (chldr[i].data(Qt::UserRole + 3).toBool()) - val |= chldr[i].data(Qt::UserRole).toULongLong(); - } - } - for (int i = 0; i < chldr.size(); ++i) { - if (chldr[i] == cmi) continue; - cv = chldr[i].data(Qt::UserRole).toULongLong(); - model->setData(chldr[i], ((val & cv) == cv && cv != 0) || (val == 0 && cv == 0), Qt::UserRole + 3); - } - //qDebug() << val; - model->setData(p, val, Qt::UserRole); - model->setData(p.sibling(p.row(), 1), val, Qt::UserRole); -} - - - -PropertyEditor::PropertyEditor(QWidget * parent): QTreeWidget(parent) { - object = 0; - active_ = false; - configTree(); - connect(this, SIGNAL(itemClicked(QTreeWidgetItem * , int)), this, SLOT(itemClicked(QTreeWidgetItem * , int))); - connect(this, SIGNAL(itemChanged(QTreeWidgetItem * , int)), this, SLOT(itemChanged(QTreeWidgetItem * , int))); -} - - -PropertyEditor::~PropertyEditor() { - -} - - -void PropertyEditor::changeEvent(QEvent * e) { - QTreeWidget::changeEvent(e); - if (e->type() == QEvent::LanguageChange) { - configTree(); - return; - } -} - - -void PropertyEditor::configTree() { - setColumnCount(2); - setRootIsDecorated(false); - setColumnWidth(0, 170); - setColumnWidth(1, 10); - header()->setStretchLastSection(true); - QStringList lbls; - lbls << tr("Property") << tr("Value"); - setHeaderLabels(lbls); - setAlternatingRowColors(true); - setItemDelegateForColumn(1, new Delegate()); - -} - - -void PropertyEditor::itemClicked(QTreeWidgetItem * item, int column) { - if (column == 0) - item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); - else { - item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable); - editItem(item, 1); - } -} - - -void PropertyEditor::itemChanged(QTreeWidgetItem * item, int column) { - if (!active_) return; - if (column != 1) return; - QVariant value = item->data(1, Qt::UserRole); - if (value.canConvert()) { - value = value.value().second; - } - object->setProperty(item->text(0).toLatin1(), value); -} - - -void PropertyEditor::rebuild() { - clear(); - configTree(); - if (object == 0) return; - active_ = false; - const QMetaObject * mo = object->metaObject(); - QList mol; - while (mo != 0) { - mol.push_front(mo); - mo = mo->superClass(); - } - int ps, pe; - QTreeWidgetItem * ti, * tli, * tfi; - QVariant value; -// QWidget * pw = 0; - int chue = 0; - QColor bc; - font_b = font(); - font_b.setBold(true); - foreach (const QMetaObject * o, mol) { - ps = o->propertyOffset(); - pe = o->propertyCount();// - ps; - //qDebug() << i->className() << ps << pe; - tli = new QTreeWidgetItem(); - tli->setText(0, o->className()); - tli->setFont(0, font_b); - setItemBackColor(tli, Qt::darkGray); - setItemForeColor(tli, Qt::white); - addTopLevelItem(tli); - setFirstItemColumnSpanned(tli, true); - tli->setExpanded(true); - for (int i = ps; i < pe; ++i) { - props << o->property(i); - value = o->property(i).read(object); - ti = new QTreeWidgetItem(); - ti->setSizeHint(1, QSize(20, 20)); - bc.setHsv(chue, 60, 245 + (i % 2) * 20 - 10); - setItemBackColor(ti, bc); - ti->setText(0, o->property(i).name()); - if (props.back().isFlagType()) { - QMetaEnum menum = props.back().enumerator(); - for (int j = 0; j < menum.keyCount(); ++j) { - tfi = new QTreeWidgetItem(); - tfi->setText(0, menum.key(j)); - tfi->setData(1, Qt::UserRole, menum.value(j)); - tfi->setData(1, Qt::UserRole + 1, "__flag"); - tfi->setData(1, Qt::UserRole + 2, value.toULongLong()); - tfi->setData(1, Qt::UserRole + 3, (value.toULongLong() & menum.value(j)) > 0); - tfi->setSizeHint(1, QSize(20, 20)); - bc.setHsv(chue, 60, 245 + ((i + j + 1) % 2) * 20 - 10); - setItemBackColor(tfi, bc); - ti->addChild(tfi); - } - ti->setData(0, Qt::UserRole, value); - ti->setData(1, Qt::UserRole, value); - ti->setData(1, Qt::UserRole + 2, "__flags"); - ti->setData(0, Qt::UserRole + 1, QVariant::fromValue(props.back())); - } - else if (props.back().isEnumType()) - value.setValue(PropertyValuePair(props.back(), value)); - //ti->setText(1, value.toString()); - ti->setData(1, Qt::UserRole, value); - tli->addChild(ti); - //const_cast(indexFromItem(ti, 1)).; - //if (pw != 0) setItemWidget(ti, 1, pw); - } - chue += 60; - chue %= 360; - } - active_ = true; -} - - -void PropertyEditor::refresh() { - -} diff --git a/qglengine/widgets/propertyeditor.h b/qglengine/widgets/propertyeditor.h deleted file mode 100644 index 143e32c..0000000 --- a/qglengine/widgets/propertyeditor.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - QGL PropertyEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef PROPERTYEDITOR_H -#define PROPERTYEDITOR_H - -#include -#include -#include -#include -#include -#include -#include - - -class Delegate: public QStyledItemDelegate { - Q_OBJECT -public: - Delegate(QObject * parent = 0): QStyledItemDelegate() {ab = QBrush(QImage(":/icons/alpha.png"));} - - QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {cmi = const_cast(index); return widgetForProperty(parent, index);} - void setEditorData(QWidget * editor, const QModelIndex & index) const {setWidgetProperty(editor, index.data(Qt::UserRole));} - void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const; - void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const {editor->setGeometry(option.rect);} - void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const; - -private: - QWidget * widgetForProperty(QWidget * parent, const QModelIndex & index) const; - void setWidgetProperty(QWidget * w, const QVariant & value) const; - const QVariant widgetProperty(QWidget * w) const; - QString pointString(const QPoint & p) const {return QString::number(p.x()) + " x " + QString::number(p.y());} - QString pointString(const QPointF & p) const {return QString::number(p.x()) + " x " + QString::number(p.y());} - QString rectString(const QRect & r) const {return QString::number(r.x()) + " x " + QString::number(r.y()) + " : " + - QString::number(r.width()) + " x " + QString::number(r.height());} - QString rectString(const QRectF & r) const {return QString::number(r.x()) + " x " + QString::number(r.y()) + " : " + - QString::number(r.width()) + " x " + QString::number(r.height());} - - QBrush ab; - mutable QModelIndex cmi; - -private slots: - void changed() {setModelData((QWidget * )sender(), const_cast(cmi.model()), cmi);} - void changedFlag(); - -}; - -typedef QPair PropertyValuePair; -Q_DECLARE_METATYPE (PropertyValuePair) -Q_DECLARE_METATYPE (QMetaProperty) - -class PropertyEditor: public QTreeWidget { - Q_OBJECT -public: - explicit PropertyEditor(QWidget * parent = 0); - virtual ~PropertyEditor(); - - void assignObject(QObject * o) {object = o; rebuild();} - -protected: - void changeEvent(QEvent * e); - -private: - void configTree(); - void setItemBackColor(QTreeWidgetItem * i, const QColor & c) {i->setBackgroundColor(0, c); i->setBackgroundColor(1, c);} - void setItemForeColor(QTreeWidgetItem * i, const QColor & c) {i->setForeground(0, c); i->setForeground(1, c);} - void rebuild(); - void refresh(); - - QObject * object; - QFont font_b; - QList props; - bool active_; - -private slots: - void itemClicked(QTreeWidgetItem * item, int column); - void itemChanged(QTreeWidgetItem * item, int column); - -}; - -#endif // PROPERTYEDITOR_H diff --git a/qglengine/widgets/scene_tree.cpp b/qglengine/widgets/scene_tree.cpp deleted file mode 100644 index b137d53..0000000 --- a/qglengine/widgets/scene_tree.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/* - QGL SceneTree - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "scene_tree.h" -#include "ui_scene_tree.h" -#include "glcamera.h" -#include "qglview.h" -#include -#include -#include -#include - -enum Column { - cName, - cVis, - cMaterial -}; -enum ItemRole { - irObject = Qt::UserRole, - irType = Qt::UserRole + 1, -}; - -enum ObjectType { - otNode = 1, - otMesh = 2, - otLight = 4, - otCamera = 8, -}; - - -QAction * newSeparator() { - QAction * s = new QAction(); - s->setSeparator(true); - return s; -} - - -SceneTree::SceneTree(QWidget * parent): QWidget(parent) { - ui = new Ui::SceneTree(); - ui->setupUi(this); - ui->treeObjects->header()->setSectionResizeMode(cVis, QHeaderView::ResizeToContents); - ui->treeObjects->header()->setSectionsMovable(false); - ui->treeObjects->header()->swapSections(cName, cVis); - icon_empty = QIcon(":/icons/type-empty.png"); - icon_geo = QIcon(":/icons/type-geo.png"); - icon_camera = QIcon(":/icons/type-camera.png"); - icon_light = QIcon(":/icons/type-light.png"); - icon_vis[0] = QIcon(":/icons/layer-visible-off.png"); - icon_vis[1] = QIcon(":/icons/layer-visible-on.png"); - ui->treeObjects->addActions(actionsSelection()); - ui->treeObjects->addAction (newSeparator()); - ui->treeObjects->addActions(actionsAdd()); - ui->buttonFilter->addActions(QList() << ui->actionFilter_node << ui->actionFilter_mesh << ui->actionFilter_light << ui->actionFilter_camera); - view = 0; - hidden_by_filter = obj_count = 0; - block_tree = false; - connect(ui->treeObjects->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(treeObjects_selectionCnahged())); -} - - -SceneTree::~SceneTree() { - delete ui; -} - - -void SceneTree::assignQGLView(QGLView * v) { - view = v; - objectsTreeChanged(); - if (!view) return; - connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); - connect(view, SIGNAL(materialsChanged()), this, SLOT(materialsChanged())); - connect(view->scene(), SIGNAL(treeChanged()), this, SLOT(objectsTreeChanged())); - connect(view->scene(), SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*))); - view->setContextActions(actionsSelection()); - checkActions(); -} - - -QList SceneTree::actionsAdd() { - QList ret; - ret << ui->actionAdd_node << ui->actionAdd_light << ui->actionAdd_camera; - return ret; -} - - -QList SceneTree::actionsSelection() { - QList ret; - ret << ui->actionFocus << newSeparator() - << ui->actionGroup << ui->actionClone << newSeparator() - << ui->actionSelect_parent << ui->actionSelect_by_mesh << ui->actionSelect_by_material << newSeparator() - << ui->actionTransfer_transform_to_children << newSeparator() - << ui->actionActive_camera << ui->actionDefault_camera << newSeparator() - << ui->actionRemove; - return ret; -} - - -void SceneTree::changeEvent(QEvent * e) { - QWidget::changeEvent(e); - if (e->type() == QEvent::LanguageChange) { - ui->retranslateUi(this); - return; - } -} - - -void SceneTree::rememberExpanded(QTreeWidgetItem * ti) { - for (int i = 0; i < ti->childCount(); ++i) { - QTreeWidgetItem * ci = ti->child(i); - if (ci->isExpanded()) - expanded_ << itemObject(ci); - rememberExpanded(ci); - } -} - - -void SceneTree::restoreExpanded(QTreeWidgetItem * ti) { - for (int i = 0; i < ti->childCount(); ++i) { - QTreeWidgetItem * ci = ti->child(i); - ci->setExpanded(expanded_.contains(itemObject(ci))); - restoreExpanded(ci); - } -} - - -void SceneTree::makeObjetTree(ObjectBase * o, QTreeWidgetItem * ti) { - ++obj_count; - for (int i = 0; i < o->childCount(); ++i) { - ObjectBase * co = o->child(i); - QTreeWidgetItem * ci = new QTreeWidgetItem(ti); - ci->setText(cName, co->name()); - ci->setCheckState(cVis, co->isVisible() ? Qt::Checked : Qt::Unchecked); - ci->setIcon(cVis, icon_vis[co->isVisible(true)]); - if (co->material()) - ci->setText(cMaterial, co->material()->name); - ci->setFlags(ci->flags() | Qt::ItemIsEditable); - ObjectType t = otNode; - switch (co->type()) { - case ObjectBase::glMesh: - if (co->mesh()) { - t = otMesh; - ci->setIcon(cName, icon_geo); - geo_items << ci; - } else { - ci->setIcon(cName, icon_empty); - } - break; - case ObjectBase::glLight: - t = otLight; - ci->setIcon(cName, icon_light); - break; - case ObjectBase::glCamera: - t = otCamera; - ci->setIcon(cName, icon_camera); - ci->setText(cVis, (co == view->camera()) ? "*" : ""); - cam_items << ci; - break; - default: break; - } - ci->setData(cName, irObject, quintptr(co)); - ci->setData(cName, irType, int(t)); - ci->setSelected(co->isSelected()); - makeObjetTree(co, ci); - } -} - - -ObjectBase * SceneTree::itemObject(QTreeWidgetItem * item) const { - if (!item) return 0; - return (ObjectBase*)(item->data(cName, irObject).toULongLong()); -} - - -int SceneTree::itemType(QTreeWidgetItem * item) const { - if (!item) return otNode; - return item->data(cName, irType).toInt(); -} - - -void SceneTree::selectionChanged() { - if (block_tree) return; - block_tree = true; - QList il = ui->treeObjects->findItems("", Qt::MatchContains | Qt::MatchRecursive); - const ObjectBase * fo = 0; - if (view->selectedObjects().size() == 1) - fo = view->selectedObject(); - foreach (QTreeWidgetItem * i, il) { - ObjectBase * o = itemObject(i); - i->setSelected(o->isSelected()); - if (fo && (fo == o)) { - ui->treeObjects->setCurrentItem(i); - } - } - block_tree = false; - checkActions(); -} - - -void SceneTree::materialsChanged() { - foreach (QTreeWidgetItem * i, geo_items) { - ObjectBase * o = itemObject(i); - if (!o) continue; - if (o->material()) - i->setText(cMaterial, o->material()->name); - } -} - - -void SceneTree::cameraChanged() { - if (!view) return; - foreach (QTreeWidgetItem * i, cam_items) { - ObjectBase * o = itemObject(i); - if (!o) continue; - i->setText(cVis, (o == view->camera()) ? "*" : ""); - } -} - - -bool SceneTree::filterTree(QTreeWidgetItem * ti, const QString & filter, int types) { - bool ret = false; - for (int i = 0; i < ti->childCount(); ++i) { - QTreeWidgetItem * ci = ti->child(i); - QString cit = ci->text(cName); - int t = itemType(ci); - if (ci->childCount() > 0) { - if (!filterTree(ci, filter, types)) { - ci->setHidden(true); - ++hidden_by_filter; - continue; - } - ci->setHidden(false); - ret = true; - } else { - bool f = false; - if (filter.isEmpty()) { - f = true; - } else { - f = f || cit.contains(filter, Qt::CaseInsensitive); - } - if ((types & t) != t) - f = false; - ci->setHidden(!f); - if (f) ret = true; - else ++hidden_by_filter; - } - } - return ret; -} - - -void SceneTree::checkActions() { - bool has_1 = false, has_m = false; - if (view) { - has_1 = !view->selectedObjects().isEmpty(); - has_m = view->selectedObjects().size() > 1; - } - ui->actionFocus ->setEnabled(has_1); - ui->actionRemove->setEnabled(has_1); - ui->actionClone ->setEnabled(has_1); - ui->actionGroup->setEnabled(has_m); - ui->actionTransfer_transform_to_children->setEnabled(has_1); - ui->actionSelect_parent->setEnabled(has_1); - ui->actionSelect_by_mesh->setEnabled(has_1); - ui->actionSelect_by_material->setEnabled(has_1); - ui->actionActive_camera->setEnabled(has_1); -} - - -void SceneTree::treeObjects_selectionCnahged() { - if (block_tree || !view) return; - block_tree = true; - view->scene()->clearSelection(); - ObjectBaseList sol; - QList til = ui->treeObjects->selectedItems(); - foreach (QTreeWidgetItem * i, til) - sol << itemObject(i); - view->scene()->selectObjects(sol); - block_tree = false; - checkActions(); -} - - -void SceneTree::filter() { - int types = 0; - if (ui->actionFilter_node ->isChecked()) types |= otNode ; - if (ui->actionFilter_mesh ->isChecked()) types |= otMesh ; - if (ui->actionFilter_light ->isChecked()) types |= otLight ; - if (ui->actionFilter_camera->isChecked()) types |= otCamera; - if (types == 0) types = 0xFF; - hidden_by_filter = 0; - filterTree(ui->treeObjects->invisibleRootItem(), ui->lineFilter->text(), types); - ui->treeObjects->invisibleRootItem()->setHidden(false); - ui->labelCounts->setText(tr("%1 objects, %2 hide by filter").arg(obj_count).arg(hidden_by_filter)); -} - - -void SceneTree::__objectDeleted(ObjectBase * o) { - for (int i = 0; i < geo_items.size(); ++i) - if (itemObject(geo_items[i]) == o) { - geo_items.removeAt(i); - --i; - } - for (int i = 0; i < cam_items.size(); ++i) - if (itemObject(cam_items[i]) == o) { - cam_items.removeAt(i); - --i; - } -} - - -void SceneTree::on_treeObjects_itemChanged(QTreeWidgetItem * item, int column) { - if (block_tree) return; - if (column == cName) { - ObjectBase * o = itemObject(item); - if (o) o->setName(item->text(cName)); - } - if (column == cVis) { - bool vis = item->checkState(cVis) == Qt::Checked; - QList til = ui->treeObjects->selectedItems(); - if (!til.contains(item)) { - til.clear(); - til << item; - } - foreach (QTreeWidgetItem * ti, til) { - //itemObject(ti)->setVisible(vis); - itemObject(ti)->setVisible(vis); - } - } -} - - -void SceneTree::on_treeObjects_itemMoved(QTreeWidgetItem * item, QTreeWidgetItem * new_parent) { - ObjectBase * co = itemObject(item); - if (!co->hasParent()) return; - //co->parent()->removeChild(co); - if (new_parent == ui->treeObjects->invisibleRootItem()) { - view->scene()->rootObject()->addChild(co); - } else { - ObjectBase * po = itemObject(new_parent); - if (po) - po->addChild(co); - } -} - - -void SceneTree::on_actionAdd_node_triggered() { - if (!view) return; - ObjectBase * no = new ObjectBase(); - view->scene()->addObject(no); - view->scene()->selectObject(no); -} - - -void SceneTree::on_actionAdd_light_triggered() { - if (!view) return; - ObjectBase * no = new Light(); - view->scene()->addObject(no); - view->scene()->selectObject(no); -} - - -void SceneTree::on_actionAdd_camera_triggered() { - if (!view) return; - ObjectBase * no = new Camera(); - view->scene()->addObject(no); - view->scene()->selectObject(no); -} - - -void SceneTree::on_actionClone_triggered() { - if (!view) return; - QList sil = ui->treeObjects->selectedItems(); - ObjectBaseList col; - foreach (QTreeWidgetItem * i, sil) { - ObjectBase * o = itemObject(i); - if (!o) continue; - ObjectBase * no = o->clone(); - o->parent()->addChild(no); - col << no; - } - view->scene()->selectObjects(col); -} - - -void SceneTree::on_actionGroup_triggered() { - if (!view) return; - ObjectBaseList sol = view->scene()->selectedObjects(true); - ObjectBase * cp = sol[0]->parent(); - ObjectBase * nr = new ObjectBase(); - cp->addChild(nr); - foreach (ObjectBase * o, sol) - nr->addChild(o); - view->scene()->selectObject(nr); -} - - -void SceneTree::on_actionTransfer_transform_to_children_triggered() { - if (!view) return; - ObjectBaseList sol = view->scene()->selectedObjects(true); - foreach (ObjectBase * o, sol) - o->transferTransformToChildren(); -} - - -void SceneTree::on_actionActive_camera_triggered() { - if (!view) return; - ObjectBase * o = view->scene()->selectedObject(); - if (!o) return; - if (o->type() != ObjectBase::glCamera) return; - view->setCamera((Camera *)o); - cameraChanged(); -} - - -void SceneTree::on_actionDefault_camera_triggered() { - if (!view) return; - view->setDefaultCamera(); - cameraChanged(); -} - - -void SceneTree::on_actionSelect_parent_triggered() { - if (!view) return; - ObjectBaseList sol = view->scene()->selectedObjects(true); - QSet nsl; - foreach (ObjectBase * o, sol) { - ObjectBase * po = o->parent(); - if (po != view->scene()->rootObject()) - o = po; - nsl << o; - } - view->scene()->selectObjects(nsl.toList()); -} - - -void SceneTree::on_actionSelect_by_mesh_triggered() { - view->scene()->selectObjectsByMesh(); -} - - -void SceneTree::on_actionSelect_by_material_triggered() { - view->scene()->selectObjectsByMaterial(); -} - - -void SceneTree::removeObjects() { - if (!view) return; - QList sil = ui->treeObjects->selectedItems(); - foreach (QTreeWidgetItem * i, sil) { - ObjectBase * o = itemObject(i); - if (o) delete o; - } - qDeleteAll(sil); -} - - -void SceneTree::focusObjects() { - if (!view) return; - if (!view->camera()) return; - Box3D bb; - ObjectBaseList ol = view->selectedObjects(); - foreach (ObjectBase * o, ol) { - o->calculateBoundingBox(); - bb |= o->boundingBox(); - } - view->focusOn(bb); -} - - -void SceneTree::objectsTreeChanged() { - int vpos = ui->treeObjects->verticalScrollBar()->value(); - expanded_.clear(); - geo_items.clear(); - cam_items.clear(); - rememberExpanded(ui->treeObjects->invisibleRootItem()); - block_tree = true; - ui->treeObjects->clear(); - block_tree = false; - if (!view) return; - block_tree = true; - obj_count = 0; - makeObjetTree(view->scene()->rootObject(), ui->treeObjects->invisibleRootItem()); - --obj_count; - restoreExpanded(ui->treeObjects->invisibleRootItem()); - block_tree = false; - filter(); - QApplication::processEvents(); - ui->treeObjects->verticalScrollBar()->setValue(vpos); -} diff --git a/qglengine/widgets/scene_tree.h b/qglengine/widgets/scene_tree.h deleted file mode 100644 index bf16a55..0000000 --- a/qglengine/widgets/scene_tree.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - QGL SceneTree - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef SCENE_TREE_H -#define SCENE_TREE_H - -#include -#include -#include "glscene.h" - -class QTreeWidgetItem; - -namespace Ui { - class SceneTree; -} - -class SceneTree: public QWidget -{ - Q_OBJECT -public: - SceneTree(QWidget * parent = 0); - ~SceneTree(); - - void assignQGLView(QGLView * v); - QList actionsAdd(); - QList actionsSelection(); - -private: - void changeEvent(QEvent * e); - void rememberExpanded(QTreeWidgetItem * ti); - void restoreExpanded(QTreeWidgetItem * ti); - void makeObjetTree(ObjectBase * o, QTreeWidgetItem * ti); - ObjectBase * itemObject(QTreeWidgetItem * item) const; - int itemType(QTreeWidgetItem * item) const; - bool filterTree(QTreeWidgetItem * ti, const QString & filter, int types); - void checkActions(); - - Ui::SceneTree * ui; - bool block_tree; - int hidden_by_filter, obj_count; - QIcon icon_empty, icon_geo, icon_camera, icon_light, icon_vis[2]; - QSet expanded_; - QList geo_items, cam_items; - QGLView * view; - -private slots: - void treeObjects_selectionCnahged(); - void on_treeObjects_itemChanged(QTreeWidgetItem * item, int column); - void on_treeObjects_itemMoved (QTreeWidgetItem * item, QTreeWidgetItem * new_parent); - - void on_actionAdd_node_triggered(); - void on_actionAdd_light_triggered(); - void on_actionAdd_camera_triggered(); - - void on_actionFocus_triggered() {focusObjects();} - void on_actionRemove_triggered() {removeObjects();} - void on_actionClone_triggered(); - void on_actionGroup_triggered(); - void on_actionTransfer_transform_to_children_triggered(); - - void on_actionActive_camera_triggered(); - void on_actionDefault_camera_triggered(); - - void on_actionSelect_parent_triggered(); - void on_actionSelect_by_mesh_triggered(); - void on_actionSelect_by_material_triggered(); - - void removeObjects(); - void focusObjects(); - void objectsTreeChanged(); - void selectionChanged(); - void materialsChanged(); - void cameraChanged(); - void filter(); - void __objectDeleted(ObjectBase * o); - -public slots: - -signals: - -private: - -}; - -#endif // SCENE_TREE_H diff --git a/qglengine/widgets/scene_tree.ui b/qglengine/widgets/scene_tree.ui deleted file mode 100644 index ec57188..0000000 --- a/qglengine/widgets/scene_tree.ui +++ /dev/null @@ -1,425 +0,0 @@ - - - SceneTree - - - - 0 - 0 - 442 - 606 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - Filter: - - - - - - - - - - - :/icons/configure.png:/icons/configure.png - - - QToolButton::InstantPopup - - - - - - - Qt::Vertical - - - - - - - Expand tree - - - - :/icons/expand.png:/icons/expand.png - - - - - - - Collapse tree - - - - :/icons/collapse.png:/icons/collapse.png - - - - - - - - - - - - - - - - Qt::ActionsContextMenu - - - QAbstractItemView::InternalMove - - - QAbstractItemView::ExtendedSelection - - - QAbstractItemView::ScrollPerPixel - - - true - - - false - - - - Name - - - - - Vis - - - - - Material - - - - - - - - - :/icons/type-camera.png:/icons/type-camera.png - - - Focus - - - - - - :/icons/edit-delete.png:/icons/edit-delete.png - - - Remove - - - - - - :/icons/edit-copy.png:/icons/edit-copy.png - - - Clone - - - - - - :/icons/group.png:/icons/group.png - - - Group - - - - - - :/icons/go-top.png:/icons/go-top.png - - - Select parent - - - - - - :/icons/type-geo.png:/icons/type-geo.png - - - Select by mesh - - - - - - :/icons/format-fill-color.png:/icons/format-fill-color.png - - - Select by material - - - - - - :/icons/add-type-empty.png:/icons/add-type-empty.png - - - Add node - - - - - - :/icons/add-type-light.png:/icons/add-type-light.png - - - Add light - - - - - - :/icons/add-type-camera.png:/icons/add-type-camera.png - - - Add camera - - - - - true - - - - :/icons/type-empty.png:/icons/type-empty.png - - - Nodes - - - - - true - - - - :/icons/type-geo.png:/icons/type-geo.png - - - Meshes - - - - - true - - - - :/icons/type-light.png:/icons/type-light.png - - - Lights - - - - - true - - - - :/icons/type-camera.png:/icons/type-camera.png - - - Cameras - - - - - Transfer transform to children - - - - - - :/icons/type-camera.png:/icons/type-camera.png - - - Active camera - - - - - - :/icons/type-camera.png:/icons/type-camera.png - - - Default camera - - - - - - CLineEdit - QLineEdit -
    clineedit.h
    -
    - - InternalMoveTreeWidget - QTreeWidget -
    treewidget_p.h
    -
    -
    - - - - - - - - - - buttonExpand - clicked() - treeObjects - expandAll() - - - 395 - 164 - - - 299 - 359 - - - - - buttonCollapse - clicked() - treeObjects - collapseAll() - - - 427 - 164 - - - 332 - 369 - - - - - lineFilter - textChanged(QString) - SceneTree - filter() - - - 273 - 130 - - - 355 - 37 - - - - - actionFilter_camera - toggled(bool) - SceneTree - filter() - - - -1 - -1 - - - 414 - 302 - - - - - actionFilter_mesh - toggled(bool) - SceneTree - filter() - - - -1 - -1 - - - 414 - 302 - - - - - actionFilter_light - toggled(bool) - SceneTree - filter() - - - -1 - -1 - - - 414 - 302 - - - - - actionFilter_node - toggled(bool) - SceneTree - filter() - - - -1 - -1 - - - 414 - 302 - - - - - - removeObjects() - focusObjects() - filter() - -
    diff --git a/qglengine/widgets/treewidget_p.h b/qglengine/widgets/treewidget_p.h deleted file mode 100644 index 18cce4b..0000000 --- a/qglengine/widgets/treewidget_p.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - QGL SceneTree - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef TREEWIDGET_H -#define TREEWIDGET_H - -#include -#include -#include -#include - -class InternalMoveTreeWidget: public QTreeWidget -{ - Q_OBJECT -public: - InternalMoveTreeWidget(QWidget * parent = 0): QTreeWidget(parent) {} - -protected: - virtual void dropEvent(QDropEvent * e) { - QList sil = selectedItems(); - if (sil.isEmpty()) return; - QTreeWidget::dropEvent(e); - foreach (QTreeWidgetItem * ti, sil) { - QTreeWidgetItem * ti_p = ti->parent(); - if (!ti_p) ti_p = invisibleRootItem(); - int ti_ppos = ti_p->indexOfChild(ti); - emit itemMoved(ti, ti_p, ti_ppos); - } - } - -signals: - void itemMoved(QTreeWidgetItem * item, QTreeWidgetItem * new_parent, int new_index); - -}; - -#endif // TREEWIDGET_H diff --git a/qglengine/widgets/view_editor.cpp b/qglengine/widgets/view_editor.cpp deleted file mode 100644 index ab48597..0000000 --- a/qglengine/widgets/view_editor.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - QGL ViewEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#include "view_editor.h" -#include "ui_view_editor.h" -#include -#include -#include - - -ViewEditor::ViewEditor(QWidget * parent): QWidget(parent) { - ui = new Ui::ViewEditor(); - ui->setupUi(this); - view = 0; - active = true; - ui->checkCameraLight->setCheckState(Qt::PartiallyChecked); -#if QT_VERSION >= QT_VERSION_CHECK(5,12,0) - ui->spinDepthStart->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType); -#endif -} - - -void ViewEditor::assignQGLView(QGLView * v) { - view = v; - if (!view) return; - active = false; - ui->spinFOV->setValue(view->FOV()); - ui->spinDepthStart->setValue(view->depthStart()); - ui->groupHoverHalo->setChecked(view->isHoverHaloEnabled()); - ui->groupSelectionHalo->setChecked(view->isSelectionHaloEnabled()); - ui->spinHoverHaloFill->setValue(view->hoverHaloFillAlpha()); - ui->spinSelectionHaloFill->setValue(view->selectionHaloFillAlpha()); - ui->colorHoverHalo->setColor(view->hoverHaloColor()); - ui->colorSelectionHalo->setColor(view->selectionHaloColor()); - ui->checkFXAA->setChecked(view->isFeatureEnabled(QGLView::qglFXAA)); - ui->checkCameraOrbit->setChecked(view->isCameraOrbit()); - ui->checkCameraLight->setCheckState((Qt::CheckState)view->cameraLightMode()); - ui->checkService->setChecked(view->isServiceMode()); - ui->lineHDR->setProperty("GLpath", view->environmentMapFile()); - ui->lineHDR->setText(QFileInfo(view->environmentMapFile()).fileName()); - active = true; -} - - -void ViewEditor::changeEvent(QEvent * e) { - QWidget::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } -} - - -void ViewEditor::on_spinFOV_valueChanged(double val) { - if (!view || !active) return; - view->setFOV(val); -} - - -void ViewEditor::on_spinDepthStart_valueChanged(double val) { - if (!view || !active) return; - view->setDepthStart(val); -} - - -void ViewEditor::on_spinViewGamma_valueChanged(double val) { - if (!view || !active) return; - view->setGamma(val); -} - - -void ViewEditor::on_comboViewRenderMode_currentIndexChanged(int val) { - if (!view || !active) return; - static int modes[] = {GL_POINT, GL_LINE, GL_FILL}; - view->setRenderMode((ObjectBase::RenderMode)modes[val]); -} - - -void ViewEditor::on_groupHoverHalo_clicked(bool val) { - if (!view || !active) return; - view->setHoverHaloEnabled(val); -} - - -void ViewEditor::on_groupSelectionHalo_clicked(bool val) { - if (!view || !active) return; - view->setSelectionHaloEnabled(val); -} - - -void ViewEditor::on_spinHoverHaloFill_valueChanged(double val) { - if (!view || !active) return; - view->setHoverHaloFillAlpha(val); -} - - -void ViewEditor::on_spinSelectionHaloFill_valueChanged(double val) { - if (!view || !active) return; - view->setSelectionHaloFillAlpha(val); -} - - -void ViewEditor::on_colorHoverHalo_colorChanged(QColor color) { - if (!view || !active) return; - view->setHoverHaloColor(color); -} - - -void ViewEditor::on_colorSelectionHalo_colorChanged(QColor color) { - if (!view || !active) return; - view->setSelectionHaloColor(color); -} - - -void ViewEditor::on_checkAutoExposure_toggled(bool val) { - if (!view || !active) return; - view->setAutoExposure(val); -} - - -void ViewEditor::on_checkFXAA_clicked(bool val) { - if (!view || !active) return; - view->setFeature(QGLView::qglFXAA, val); -} - - -void ViewEditor::on_checkCameraOrbit_clicked(bool val) { - if (!view || !active) return; - view->setCameraOrbit(val); -} - - -void ViewEditor::on_checkService_clicked(bool val) { - if (!view || !active) return; - view->setServiceMode(val); -} - - -void ViewEditor::on_checkCameraLight_stateChanged(int s) { - if (!view || !active) return; - view->setCameraLightMode((QGLView::CameraLightMode)s); - -} - - -void ViewEditor::on_buttonHDRClear_clicked() { - if (!view || !active) return; - ui->lineHDR->setText(""); - ui->lineHDR->setProperty("GLpath", ""); - view->setEnvironmentMapFile(""); -} - - -void ViewEditor::on_buttonHDRSelect_clicked() { - if (!view || !active) return; - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineHDR->property("GLpath").toString(), "Radiance HDR(*.hdr)"); - if (str.isEmpty()) return; - ui->lineHDR->setText(QFileInfo(str).fileName()); - ui->lineHDR->setProperty("GLpath", str); - view->setEnvironmentMapFile(str); -} diff --git a/qglengine/widgets/view_editor.h b/qglengine/widgets/view_editor.h deleted file mode 100644 index 405fa4b..0000000 --- a/qglengine/widgets/view_editor.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - QGL ViewEditor - Ivan Pelipenko peri4ko@yandex.ru - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - -#ifndef VIEW_EDITOR_H -#define VIEW_EDITOR_H - -#include -#include "qglview.h" - -namespace Ui { - class ViewEditor; -} - -class ViewEditor: public QWidget -{ - Q_OBJECT -public: - explicit ViewEditor(QWidget * parent = 0); - - void assignQGLView(QGLView * v); - -protected: - void changeEvent(QEvent * e); - - Ui::ViewEditor * ui; - QGLView * view; - bool active; - -private slots: - void on_spinFOV_valueChanged(double val); - void on_spinDepthStart_valueChanged(double val); - void on_spinViewGamma_valueChanged(double val); - void on_comboViewRenderMode_currentIndexChanged(int val); - void on_groupHoverHalo_clicked(bool val); - void on_groupSelectionHalo_clicked(bool val); - void on_spinHoverHaloFill_valueChanged(double val); - void on_spinSelectionHaloFill_valueChanged(double val); - void on_colorHoverHalo_colorChanged(QColor color); - void on_colorSelectionHalo_colorChanged(QColor color); - void on_checkAutoExposure_toggled(bool val); - void on_checkFXAA_clicked(bool val); - void on_checkCameraOrbit_clicked(bool val); - void on_checkService_clicked(bool val); - void on_checkCameraLight_stateChanged(int s); - void on_buttonHDRClear_clicked(); - void on_buttonHDRSelect_clicked(); - -signals: - -}; - -#endif // VIEW_EDITOR_H diff --git a/qglengine/widgets/view_editor.ui b/qglengine/widgets/view_editor.ui deleted file mode 100644 index 744b0a5..0000000 --- a/qglengine/widgets/view_editor.ui +++ /dev/null @@ -1,511 +0,0 @@ - - - ViewEditor - - - - 0 - 0 - 328 - 538 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Draw mode: - - - - - - - 2 - - - - Point - - - - - Wireframe - - - - - Solid - - - - - - - - Gamma: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0.010000000000000 - - - 5.000000000000000 - - - 1.000000000000000 - - - 2 - - - - - - - Env HDR: - - - - - - - 2 - - - - - - - - - :/icons/edit-delete.png:/icons/edit-delete.png - - - - - - - - :/icons/document-open.png:/icons/document-open.png - - - - - - - - - - - - - - FXAA - - - - - - - Auto exposure - - - - - - - Service mode - - - true - - - - - - - Camera light - - - true - - - - - - - - - Camera - - - - - - - - Orbit - - - true - - - - - - - Qt::Horizontal - - - QSizePolicy::Preferred - - - - 40 - 1 - - - - - - - - FOV: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0.100000000000000 - - - 179.900000000000006 - - - 60.000000000000000 - - - - - - - - - - - Depth start: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 3 - - - 999999999.000000000000000 - - - 1.000000000000000 - - - - - - - - - - - - Hover halo - - - true - - - - - - Fill: - - - - - - - 0.000000000000000 - - - 1.000000000000000 - - - 0.300000000000000 - - - 2 - - - 0.050000000000000 - - - 0.100000000000000 - - - - - - - - 255 - 0 - 251 - - - - true - - - - - - - - - - Selection halo - - - true - - - - - - Fill: - - - - - - - 0.000000000000000 - - - 1.000000000000000 - - - 0.300000000000000 - - - 2 - - - 0.050000000000000 - - - 0.100000000000000 - - - - - - - - 0 - 143 - 239 - - - - true - - - - - - - - - - - - - 0 - 0 - - - - Fog - - - - QFormLayout::AllNonFixedFieldsGrow - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - Density: - - - - - - - - - 0.000000000000000 - - - 10.000000000000000 - - - 0.000000000000000 - - - 3 - - - 0.050000000000000 - - - 0.100000000000000 - - - - - - - - 128 - 128 - 128 - - - - - - - - - - Decay: - - - - - - - 0.000000000000000 - - - 9999.000000000000000 - - - 10.000000000000000 - - - 2 - - - 0.050000000000000 - - - 0.100000000000000 - - - true - - - 9999.000000000000000 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 1 - - - - - - - - - SpinSlider - QWidget -
    spinslider.h
    -
    - - ColorButton - QPushButton -
    colorbutton.h
    -
    -
    - - - - - -
    diff --git a/qglengine/widgets/widgets.qrc b/qglengine/widgets/widgets.qrc deleted file mode 100644 index c83819f..0000000 --- a/qglengine/widgets/widgets.qrc +++ /dev/null @@ -1,18 +0,0 @@ - - - ../icons/go-jump.png - ../icons/dialog-close.png - ../icons/dialog-cancel.png - ../icons/edit-clear.png - ../icons/configure.png - ../icons/document-save.png - ../icons/edit-find.png - ../icons/list-add.png - ../icons/edit-delete.png - ../icons/edit-copy.png - ../icons/edit-paste.png - ../icons/document-edit.png - ../icons/group.png - ../icons/format-fill-color.png - - diff --git a/qglview/LICENSE.txt b/qglview/LICENSE.txt deleted file mode 100644 index 0a04128..0000000 --- a/qglview/LICENSE.txt +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/qglview/icons/alpha.png b/qglview/icons/alpha.png deleted file mode 100644 index 543566938cf5681db007530efc6b64c4ae67c096..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPaBR`)C--V~^b^?X8JzX3_G|ngA*^(*DZ1&*w>+aAw xosBLAs~RN^{P_RBevQy<^L#m8)nAzm45u$~80FZyPX%gY@O1TaS?83{1ONw+E@}V( diff --git a/qglview/icons/application-exit.png b/qglview/icons/application-exit.png deleted file mode 100644 index ed5f8b2515e72608d2de9d45fb80ff481926066e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1134 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 diff --git a/qglview/icons/document-save.png b/qglview/icons/document-save.png deleted file mode 100644 index 8072aea3268164eb2028a0cebfe44da82b4f4aca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 563 zcmV-30?hr1P)XvKK@k7Ytwo{YB(9F? z;2_0Ku;{F~yQsL?!9iy?1;;|c4%SjZ%{70TwwHKcBH=J-%EN&+{;d zhN(E7P<- zOhP?!y}wyJm`;b*`kqJvqBiX|nL~L2fd*Ux1d!eYF6Tbg5P<9ZC&&uF5~UDVJ~Kya z$B9GKW9yGCk1)gXRIvtRXipPk@<6(R{ z10;&Qkze=csdPHpgO1qUX}3Wtm&>>~JBMXkI4Be#D>XTZ+DDB(A$cT#*xhj)kQiey zO%sM;K-YE1@`TY9(UZv}-m29|6TcYK$LKUNox!$kO4I`&Fl}aA7Py>1;e44jn~%EA z#v7jv1002ovPDHLkV1jI` B^11*3 diff --git a/qglview/icons/edit-clear-locationbar-rtl.png b/qglview/icons/edit-clear-locationbar-rtl.png deleted file mode 100644 index 6c4b83b7ac6e451f461973dac0c9a6c53dedef25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJbFq_W2nPqp?T7vkfLzW3kH}&M z2FBeW%xLxI@gtz1WQl7;NpOBzNqJ&XDnogBxn5>oc5!lIL8@MUQTpt6Hc~*(*`Bv~l~6?FSDYJaY8Nv17;1UpRl|%9VTf?mc|? z@cHxSFJHcV_3G8zw{Jgu`0)Aj=PzHr{QC9l_wV0-{`@KR`o0Pn77`^ve!&d#@_Ksq z_8}pusXI=cy7Kht(+?kh{P_EqYvr0*Ks9qcT^vIsBJkEM|1so z>*;dxIy;s3ojI&$kq&AP_I<(sjrDEsaU~GX3SIsdMei7bh)})pLEh`3!Xi^UM4W+LIZr$zxaOz7mw|A28X|&gK2(h zZfSoyEkX7Ar7SOshe$kJ@wtDv=f<5!bjpH@N4L9nR{6W;bYuBbX#H42w#$q|FGoYkR7TQxAVVC~AgvlcDbQ{K}v zz)cqHtE#WH+tMnPL>x$^K&cL@=%%l{d{cK)X)1KPX3v;gl4lwwgdERi@@M$WfsL{? zP3)eLTi{~|fOrH9%Ru@V9LpV0qngA+;sn5whQ6+jjvrr!>i^mx(;;26*la$T(-0mV zM6EV|5;_BFz$$UjH5GQd1)8dx zW$%Zmk#1*hIjlV+=?;EPa9k=7g`$b#;sWMW{kp}nRc!428shS@9j29Ip{OZjyKMj{ zG9;eH^E^zu)Bdikvh?_!mu@q(n3*v73Z?HG|HJ$KtcH9J10IQl4im gAunrc0{^W1Pl-(m{G3O!W1aTUgGKN%6@}cL`d0sS5o>yped=IE{-7;x28@w z?{(Ng;8?o(vZal2UCV9SDn2q^kz14h;ArvQ8^O9iIQDs;w`*7+VDp{f_ZlWKjr z)#jWRvnDK(uc_Jn=1hKh7{h^v8aJ_m2#-3&dS~D8ALfP$ET*!d=Iaj$ESaLv%HXJJ zadX**`|pc8)DD~|l;Q1I%+aL4pv!&XZJDLtiIt|8wDsLQZsnLs95p=my!g*?kHg2f ze}skYh-*HqEXlpecGB}onN3VDlz0sp?)p^E4K+@`E$^}V!kg~`uY(tgCWzj2SkAUA zhv5~wSpvTuPll7r+MOC)9ESz0WW}p&`9(OEY-(cc;=5QH8+dok<}z*b-~0I2y#2;5 zm%ceYifxa*+WiUnz4IqbQQ=IBY~#^CEhHY#9paTJbKGK|^!~uRnp-kXG?@4ro-by5 zaqMZ<%Gv6Zf0wV?sdn1z0IR9imMNmDb$a0zwKG0V)~~O%Gci?|KU*m}BkiApw!tmN Y4DJ^lh1J@%z&K#=boFyt=akR{0F^SkGXMYp diff --git a/qglview/icons/edit-delete.png b/qglview/icons/edit-delete.png deleted file mode 100644 index 87cd0b0125d6193c16c59f25b88396493e885f6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJbFq_W2nPqp?T7vkfLzW3kH}&M z2FBeW%xLxI@gtz1WQl7;NpOBzNqJ&XDnogBxn5>oc5!lIL8@MUQTpt6Hc~*<;sHJ( zuK)l4Z(v|p!N9PVfuWs&p^JfGA_Kz=28KBd467IzAX4jDSb*GiKE6H%hCBv_Tn2_L z28Klp4AZo=>*d6nRHQFelpgl-Jed$XS6*hniPlkf`z7+iOXNkDC`v6+mRl+(v`kK5 zwTk$9b?ME9YMZs?_j%bL_HsDk<9sU2r$Je2`?nP^4n zy$lTd7#Q|j8XpwoI%I5o$k*ermDN#8qhmrm$Ax%K+S#3Uu|MtSb;ix@0t3SZA)d=& zVVA>0E~h43Ns7Cc5PLm2@wTwQZ4try!urld@myOUR3yfXZwfVuCELX$$gHBz;HAv3GxeOFfuao00U1?PcLu(fWV*& z*YDnY^6b^8FJFJbz;6)v0|bBn{{8pwYTmshp#IsOE{-7*lD!9A#hMrxSP$@P+)yej zFHd4mDu4d>{K5|<=XpdH-eIeeoFkI5#Mch*eE5E3q& zsDJ)QWe~HZu=JPqwHHm!J!tPMoAuVM<=A|yGuL0$MD)r}t=B23K4h_=$wxfq{j{s6 zvbJ;1RM`0b{&%I*Q{~<_^9mg*KC_8ox^*ST366Hw_&MDTLh{a=g|okJNlO7blfl!~ K&t;ucLK6VLNBNWh diff --git a/qglview/icons/edit-find.png b/qglview/icons/edit-find.png deleted file mode 100644 index 9a462c0b9a40035c6c0cccb0491276d18098ac6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 634 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJbFq_W2nPqp?T7vk7#J9t0(?ST z|Ns9Flpzl=GBN@+vaqmlae?d=5D*X)6y)aS=HufN5)zV@mX?>72dWVk78Vs16%!K^ z7Z;b1kN}Fy$jB%wE32resHrNetE+2hXlQF|>*(m{>gpO98JQRvnrX&tshF9W zS!l>x>ZsZnXt+8#cqlS>d3pKz`ub^d`uX_<8_R?S2Ze=&MS9p~MEGW8WMqcBWoBk( zWn~o=vQON3vRn3KWzqag8Vm&QB{TPb^AhC@(M9%goCzPEIUH)ypqRpZ(583aDtGr;B5V z#MI;j1+D__&jtn`IEoMd$ocec)*P8x?>^-S*iBzCZ{MahYc{Q$ry<^PUhnzJ?6r@c ztw>t?TJt!ch=9q~LgNj=AsY+}HXDkvWCav`{CMp`Sm@PjAHEd^K1vcOGB7Ou6mb1w z;O7D(<3fQXf$bakxeCGr1p^Deac?shPo7|~?Gyi(Nr{OQKXQH9YC0+5!PO#O&aF?9 z6CP~l;Vr!SC^g~HbfYO^326xlViU}!JV|G|b^639jzYybjq(f(=Z{Mqoh4|b5A+Fx Mr>mdKI;Vst0N7E%9smFU diff --git a/qglview/icons/edit-guides.png b/qglview/icons/edit-guides.png deleted file mode 100644 index d26483960a4dcbadb1f43e5338886914f179d9e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmV+*0^j|KP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L00!&;00!&<9(6c100007bV*G`2iXV< z7c?snYm~(R00E#$L_t(|+KrMwYZO5khoASIo!yNm$8O|E8he{GqNU=uNN;Zus-Gb4P}#Y7A?ygXPKr96UOJL@!>R*>ELDtA1kf(LUSRwVPELmLx=%zus$aSl7`2@O146zfYCK8uCTp@eddeLoc{v>-MjzqkF`<&0000j6lR&1TgAAr&ZD!k+qP}W%jJ@CJRS#CRRM9ND9TBQ-xjmkjMQ-h5{U#%r&Fla zYOo82VSMr$Ij3T=SddLTjly+Z+O#GUI#oqsWi!YTYX~Mp1c=N6n29LEN`M@2&z|S8 zz?K6UxCItq2SjA@zXAxJ_(ltgM1XRn1uCLIxCJIj9r$!Vb_lQ|29qtzg5l3_{kb(5 zjm9I~{uX%RpAOcb`;j_K(Y$)So_lkBnZvay{frS1X+EDb*~^{h3eETC3$-v9491ub zaDdSvvJPx#24YJ`L;wH)0002_L%V+f000SaNLh0L00VXa00VXbebs`@00007bV*G`2ipf2 z5f1MO_vl!NDy2!q(wRLC{lU>hk|7A?&#&NUx#3*NsEGh#?SNe z;e`kO5T(>j03J~;Y!}|myq)P3w~KYQF!|eTeA>7-S(}XK_vV#SNQYh!3z!VQ7k4G!;ogP ziSPSFQA8qV{b)8Hm!|3QJxm*tUCM>uMWb@|N zk(VREhnPkjVsVErLm!x?xwOB(zj$zP(C_m3JQEWW%g!z5DgQg-IL=C=(Rh4XTRNSl zQmJfOmNnaMw^wVm+T0+Yo}S(;7K^j8wzhU$E|-%)Ut1ikil9pxRc^=(v7tizPbUN6!eXiEiT>GUh2m+!gLPXFsjUWil)S61AP)hZ=mP{rC zUDq#anuds=RL^xbn;p`6nrAYZ-hg2kD~{tVA08h5rfqzDd>Oznj3vi$7SH1-rQ}~U Z{sb_v1Uf{wNjd-k002ovPDHLkV1mj;9L)d# diff --git a/qglview/icons/item.png b/qglview/icons/item.png deleted file mode 100644 index 50bfddbfa29e1b8edd2d07e365d3d554eb40581b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 448 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6U4S$Y z{B+)352QE?JR*x37?{gIn6dV1(;1*3dx@v7EBkGB2|+ytC)E5ZC#9Ta_AqPjcJ8oi=#E=; z?DoPf3(O=mmZtwX|FHcq`=9Rt<{pz$>aFI+E!JSV_`J$!X2Q-Gxt!Z^{9-JQ3gX?Y z9ULw#%Q6f0-=C<$8FT&Z-OYIdZHhjZT>?ckP777eQ$B6v68PmY_ui&WI)ZJAU5gxI zuS@j0CGIgTv)5&$)aq-#J#eXJ_2{`!`Fhj@H=?B%}-8@m+M``_=&9uH*Pa^sRo>+4-6M^5QY@6L)8`()!D z8fv>uG3?t>wHBal3X8;U3up(2hH7+uIwX<3@#U_6BHG40$;U0f=WUPf&NZ7|$&es% lY+CWY$}R0vCe8Z)0JRB|3DF3=|YfF7jDEZ>IVpdRI~vVL~%?rHj{Mb-aA4?aN$HkpY6+e zIJ}%A@;qlRND8>Ne);a1hpoZcM@ORNcT0CDpm2lpt8;$t;5m`HA+Mts_V&s9W~>cf zetj;y8B(ff-fq3o6i^ss-tluMK}bpJ9RCvtKmqnoV4WvU2M7e2b^n@kK&}DWEA7Qj z+`01X%TpaFO`sJG5esISB#+&7>@2gVH>sP%}a+DuI`p-7R~pI$1Y5x z9J%rcDSiulyep{dI#Oy%ghc%waq@#~ax=Pj`qhjEu-38}b?Q6+eS$+ zxgkjtHlh#o1_P#oDl|xq z)$=3opuA-AQ-@kiO_W*dZ1Abw6Jy@#*R^Fg!5P*sA&3jgil^7k&X>BCo8zhBfN|0000j diff --git a/qglview/icons/node-add.png b/qglview/icons/node-add.png deleted file mode 100644 index 80b5c61c6e67c8a593e30a12114e28a2a61bb3b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 694 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

    Q!t<|C}rxlUYes)3aq;oaHjZFQ6)* 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 Ag8%>k diff --git a/qglview/icons/view-grid.png b/qglview/icons/view-grid.png deleted file mode 100644 index 0f1d70c0011a6a5be4931cc6a60684779fe04121..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 691 zcmZ8fZAepL6uxsdb0%sbX{caP>5oavqOAF`G1HOS{3y~Q)>I;>C20TpF$?lLs3;?- z2m;MynFR`EV1FVF(^N{CsdMh$ZTIfp-LKu~EQdcYOOq?nITHLN!8`?=p5W^0+A7AZt-IFOoa=th)A$ z-9%_J04aD-)B}|aqZo#gB1(za<^~p&ypVLnhq--B#K%Pan8y#5m2uRC`#d-VD-(W< zAcz2g1xS(%;51D$l$W7!h9VdMScYLCIF1E?qXQgE^FcpPlRN`S@hru2Ojr;^o)iUM z1VG{_Nnj;Wlq4w<=AsfGjfk?y%Mvd~Lb4nM0s}-I$RdC>5C90nB>*A-Kq~_Pw4ok& zbVS`&Q&o#3BqklsFDxo9(H6!YgI$I7beYk%H>r9zG~Y}{eO=moqs7wH+^#%#N~KcW z`=ooJOYuvYva?%PtG_USq?~zszIxF9rlG~$tv6Wj#xLyHpOu-SwC&R7=MARY8nQ3F zJ`kL%e{9y+zC8b9+Bv6PdSGrpwDNnrf*Hm$PIlTmRAcwY)B7L2%KYAIiBhvirdjvJ u#=&`}$)5F4Wz8KypA;;;wDrx;G2l7IA&y5dTpJOVmGCB;F+kXKm7Lqgo diff --git a/qglview/icons/zoom-fit-best.png b/qglview/icons/zoom-fit-best.png deleted file mode 100644 index 07cfc9847cb6821043d1da127b99273a637b07a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmV+$0_6RPP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L00!&;00!&<9(6c100007bV*G`2iOG+ z3Mv{e5wxxV00EmxL_t(|+Le(#OT$nUhToeAqSPt~7F=}E#m&jxk6AiZaa0lNq(4P} zfH)N?Iu^vKpin^+#eYycXiYUqwMmnEJh|qgUb6VW!%Z%{Cnx6!d^5(*;eR}`Z%A3D zf0AUt3?L=Bt5&OcX}2K&OcV-OT3iH#fJjXcY%Z76kFfBIHit{464ut&@$&o(%d%kG zHf%mwez&n(k>~~l%>WEIr1U}yH&26j?*UCmqS;}c7-zQH5XsWG;o0^C8zPoE9-x+R<0fk-=e?aDu)R;z_Zqk()ruN)c~ z1ruc!Na%Fw_nitCi$x^xkg>PFe*xgi+=80=&ap@Na)&mLe2Qbq##F1-NJ>eb=TUjL zd=Fp}8nb}og|vF$(W@6FA+@%8y-u#{>hKISMuAMiD5mSX2in@+I?wvD-pM#SuimqX d*h@Bm!56}ZCMId;HE{p{002ovPDHLkV1lrt=VJf> diff --git a/qglview/plugin/qglview_designerplugin.cpp b/qglview/plugin/qglview_designerplugin.cpp deleted file mode 100644 index 708776b..0000000 --- a/qglview/plugin/qglview_designerplugin.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "qglview_designerplugin.h" -#include "qglviewplugin.h" - - -QGLViewDesignerPlugin::QGLViewDesignerPlugin(QObject * parent): QObject(parent) -{ - m_widgets.append(new QGLViewPlugin(this)); -} - - -QList QGLViewDesignerPlugin::customWidgets() const { - return m_widgets; -} - diff --git a/qglview/plugin/qglview_designerplugin.h b/qglview/plugin/qglview_designerplugin.h deleted file mode 100644 index db6fc67..0000000 --- a/qglview/plugin/qglview_designerplugin.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef QGLVIEW_DESIGNERPLUGIN_H -#define QGLVIEW_DESIGNERPLUGIN_H - -#include -#include - - -class QGLViewDesignerPlugin: public QObject, public QDesignerCustomWidgetCollectionInterface -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "qad.qglview") - Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) -public: - QGLViewDesignerPlugin(QObject * parent = 0); - virtual QList customWidgets() const; - -private: - QList m_widgets; - -}; - -#endif // QGLVIEW_DESIGNERPLUGIN_H diff --git a/qglview/plugin/qglviewplugin.h b/qglview/plugin/qglviewplugin.h deleted file mode 100644 index 6516afb..0000000 --- a/qglview/plugin/qglviewplugin.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef QGLVIEWPLUGIN_H -#define QGLVIEWPLUGIN_H - -#include -#include - - -class QGLViewPlugin: public QObject, public QDesignerCustomWidgetInterface -{ - Q_OBJECT - Q_INTERFACES(QDesignerCustomWidgetInterface) - -public: - explicit QGLViewPlugin(QObject * parent = 0); - - bool isContainer() const; - bool isInitialized() const; - QIcon icon() const; - QString domXml() const; - QString group() const; - QString includeFile() const; - QString name() const; - QString toolTip() const; - QString whatsThis() const; - QWidget * createWidget(QWidget * parent); - void initialize(QDesignerFormEditorInterface * core); - -private: - bool m_initialized; - -}; - -#endif //QGLVIEWPLUGIN_H diff --git a/qglview/shaders/fxaa_v3.h b/qglview/shaders/fxaa_v3.h deleted file mode 100644 index 633482e..0000000 --- a/qglview/shaders/fxaa_v3.h +++ /dev/null @@ -1,2048 +0,0 @@ -/*============================================================================ - - - NVIDIA FXAA 3.11 by TIMOTHY LOTTES - - ------------------------------------------------------------------------------- -COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. ------------------------------------------------------------------------------- -TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED -*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA -OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR -LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, -OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE -THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - ------------------------------------------------------------------------------- - INTEGRATION CHECKLIST ------------------------------------------------------------------------------- -(1.) -In the shader source, setup defines for the desired configuration. -When providing multiple shaders (for different presets), -simply setup the defines differently in multiple files. -Example, - - #define FXAA_PC 1 - #define FXAA_HLSL_5 1 - #define FXAA_QUALITY__PRESET 12 - -Or, - - #define FXAA_360 1 - -Or, - - #define FXAA_PS3 1 - -Etc. - -(2.) -Then include this file, - - #include "Fxaa3_11.h" - -(3.) -Then call the FXAA pixel shader from within your desired shader. -Look at the FXAA Quality FxaaPixelShader() for docs on inputs. -As for FXAA 3.11 all inputs for all shaders are the same -to enable easy porting between platforms. - - return FxaaPixelShader(...); - -(4.) -Insure pass prior to FXAA outputs RGBL (see next section). -Or use, - - #define FXAA_GREEN_AS_LUMA 1 - -(5.) -Setup engine to provide the following constants -which are used in the FxaaPixelShader() inputs, - - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir - -Look at the FXAA Quality FxaaPixelShader() for docs on inputs. - -(6.) -Have FXAA vertex shader run as a full screen triangle, -and output "pos" and "fxaaConsolePosPos" -such that inputs in the pixel shader provide, - - // {xy} = center of pixel - FxaaFloat2 pos, - - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - FxaaFloat4 fxaaConsolePosPos, - -(7.) -Insure the texture sampler(s) used by FXAA are set to bilinear filtering. - - ------------------------------------------------------------------------------- - INTEGRATION - RGBL AND COLORSPACE ------------------------------------------------------------------------------- -FXAA3 requires RGBL as input unless the following is set, - - #define FXAA_GREEN_AS_LUMA 1 - -In which case the engine uses green in place of luma, -and requires RGB input is in a non-linear colorspace. - -RGB should be LDR (low dynamic range). -Specifically do FXAA after tonemapping. - -RGB data as returned by a texture fetch can be non-linear, -or linear when FXAA_GREEN_AS_LUMA is not set. -Note an "sRGB format" texture counts as linear, -because the result of a texture fetch is linear data. -Regular "RGBA8" textures in the sRGB colorspace are non-linear. - -If FXAA_GREEN_AS_LUMA is not set, -luma must be stored in the alpha channel prior to running FXAA. -This luma should be in a perceptual space (could be gamma 2.0). -Example pass before FXAA where output is gamma 2.0 encoded, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.rgb = sqrt(color.rgb); // gamma 2.0 color output - color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma - return color; - -Another example where output is linear encoded, -say for instance writing to an sRGB formated render target, -where the render target does the conversion back to sRGB after blending, - - color.rgb = ToneMap(color.rgb); // linear color output - return color; - -To use FXAA, - - color.rgb = ToneMap(color.rgb); // linear color output - color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma - return color; - -Getting luma correct is required for the algorithm to work correctly. - - ------------------------------------------------------------------------------- - BEING LINEARLY CORRECT? ------------------------------------------------------------------------------- -Applying FXAA to a framebuffer with linear RGB color will look worse. -This is very counter intuitive, but happends to be true in this case. -The reason is because dithering artifacts will be more visiable -in a linear colorspace. - - ------------------------------------------------------------------------------- - COMPLEX INTEGRATION ------------------------------------------------------------------------------- -Q. What if the engine is blending into RGB before wanting to run FXAA? - -A. In the last opaque pass prior to FXAA, - have the pass write out luma into alpha. - Then blend into RGB only. - FXAA should be able to run ok - assuming the blending pass did not any add aliasing. - This should be the common case for particles and common blending passes. - -A. Or use FXAA_GREEN_AS_LUMA. - -============================================================================*/ - -/*============================================================================ - - INTEGRATION KNOBS - -============================================================================*/ -// -// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE). -// FXAA_360_OPT is a prototype for the new optimized 360 version. -// -// 1 = Use API. -// 0 = Don't use API. -// -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PS3 - #define FXAA_PS3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360 - #define FXAA_360 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_360_OPT - #define FXAA_360_OPT 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_PC - // - // FXAA Quality - // The high quality PC algorithm. - // - #define FXAA_PC 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_PC_CONSOLE - // - // The console algorithm for PC is included - // for developers targeting really low spec machines. - // Likely better to just run FXAA_PC, and use a really low preset. - // - #define FXAA_PC_CONSOLE 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_120 - #define FXAA_GLSL_120 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GLSL_130 - #define FXAA_GLSL_130 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_3 - #define FXAA_HLSL_3 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_4 - #define FXAA_HLSL_4 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_HLSL_5 - #define FXAA_HLSL_5 0 -#endif -/*==========================================================================*/ -#ifndef FXAA_GREEN_AS_LUMA - // - // For those using non-linear color, - // and either not able to get luma in alpha, or not wanting to, - // this enables FXAA to run using green as a proxy for luma. - // So with this enabled, no need to pack luma in alpha. - // - // This will turn off AA on anything which lacks some amount of green. - // Pure red and blue or combination of only R and B, will get no AA. - // - // Might want to lower the settings for both, - // fxaaConsoleEdgeThresholdMin - // fxaaQualityEdgeThresholdMin - // In order to insure AA does not get turned off on colors - // which contain a minor amount of green. - // - // 1 = On. - // 0 = Off. - // - #define FXAA_GREEN_AS_LUMA 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_EARLY_EXIT - // - // Controls algorithm's early exit path. - // On PS3 turning this ON adds 2 cycles to the shader. - // On 360 turning this OFF adds 10ths of a millisecond to the shader. - // Turning this off on console will result in a more blurry image. - // So this defaults to on. - // - // 1 = On. - // 0 = Off. - // - #define FXAA_EARLY_EXIT 1 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_DISCARD - // - // Only valid for PC OpenGL currently. - // Probably will not work when FXAA_GREEN_AS_LUMA = 1. - // - // 1 = Use discard on pixels which don't need AA. - // For APIs which enable concurrent TEX+ROP from same surface. - // 0 = Return unchanged color on pixels which don't need AA. - // - #define FXAA_DISCARD 0 -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_FAST_PIXEL_OFFSET - // - // Used for GLSL 120 only. - // - // 1 = GL API supports fast pixel offsets - // 0 = do not use fast pixel offsets - // - #ifdef GL_EXT_gpu_shader4 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_FAST_PIXEL_OFFSET 1 - #endif - #ifndef FXAA_FAST_PIXEL_OFFSET - #define FXAA_FAST_PIXEL_OFFSET 0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_GATHER4_ALPHA - // - // 1 = API supports gather4 on alpha channel. - // 0 = API does not support gather4 on alpha channel. - // - #if (FXAA_HLSL_5 == 1) - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_ARB_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifdef GL_NV_gpu_shader5 - #define FXAA_GATHER4_ALPHA 1 - #endif - #ifndef FXAA_GATHER4_ALPHA - #define FXAA_GATHER4_ALPHA 0 - #endif -#endif - -/*============================================================================ - FXAA CONSOLE PS3 - TUNING KNOBS -============================================================================*/ -#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS - // - // Consoles the sharpness of edges on PS3 only. - // Non-PS3 tuning is done with shader input. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 4 and 8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // - // 8.0 is sharper - // 4.0 is softer - // 2.0 is really soft (good for vector graphics inputs) - // - #if 1 - #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0 - #endif - #if 0 - #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0 - #endif - #if 0 - #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0 - #endif -#endif -/*--------------------------------------------------------------------------*/ -#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD - // - // Only effects PS3. - // Non-PS3 tuning is done with shader input. - // - // The minimum amount of local contrast required to apply algorithm. - // The console setting has a different mapping than the quality setting. - // - // This only applies when FXAA_EARLY_EXIT is 1. - // - // Due to the PS3 being ALU bound, - // there are only two safe values here: 0.25 and 0.125. - // These options use the shaders ability to a free *|/ by 2|4|8. - // - // 0.125 leaves less aliasing, but is softer - // 0.25 leaves more aliasing, and is sharper - // - #if 1 - #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125 - #else - #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25 - #endif -#endif - -/*============================================================================ - FXAA QUALITY - TUNING KNOBS ------------------------------------------------------------------------------- -NOTE the other tuning knobs are now in the shader function inputs! -============================================================================*/ -#ifndef FXAA_QUALITY__PRESET - // - // Choose the quality preset. - // This needs to be compiled into the shader as it effects code. - // Best option to include multiple presets is to - // in each shader define the preset, then include this file. - // - // OPTIONS - // ----------------------------------------------------------------------- - // 10 to 15 - default medium dither (10=fastest, 15=highest quality) - // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) - // 39 - no dither, very expensive - // - // NOTES - // ----------------------------------------------------------------------- - // 12 = slightly faster then FXAA 3.9 and higher edge quality (default) - // 13 = about same speed as FXAA 3.9 and better than 12 - // 23 = closest to FXAA 3.9 visually and performance wise - // _ = the lowest digit is directly related to performance - // _ = the highest digit is directly related to style - // - #define FXAA_QUALITY__PRESET 12 -#endif - - -/*============================================================================ - - FXAA QUALITY - PRESETS - -============================================================================*/ - -/*============================================================================ - FXAA QUALITY - MEDIUM DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 10) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 3.0 - #define FXAA_QUALITY__P2 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 11) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 3.0 - #define FXAA_QUALITY__P3 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 12) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 4.0 - #define FXAA_QUALITY__P4 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 13) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 4.0 - #define FXAA_QUALITY__P5 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 14) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 4.0 - #define FXAA_QUALITY__P6 12.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 15) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 12.0 -#endif - -/*============================================================================ - FXAA QUALITY - LOW DITHER PRESETS -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 20) - #define FXAA_QUALITY__PS 3 - #define FXAA_QUALITY__P0 1.5 - #define FXAA_QUALITY__P1 2.0 - #define FXAA_QUALITY__P2 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 21) - #define FXAA_QUALITY__PS 4 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 22) - #define FXAA_QUALITY__PS 5 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 23) - #define FXAA_QUALITY__PS 6 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 24) - #define FXAA_QUALITY__PS 7 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 3.0 - #define FXAA_QUALITY__P6 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 25) - #define FXAA_QUALITY__PS 8 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 4.0 - #define FXAA_QUALITY__P7 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 26) - #define FXAA_QUALITY__PS 9 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 4.0 - #define FXAA_QUALITY__P8 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 27) - #define FXAA_QUALITY__PS 10 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 4.0 - #define FXAA_QUALITY__P9 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 28) - #define FXAA_QUALITY__PS 11 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 4.0 - #define FXAA_QUALITY__P10 8.0 -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_QUALITY__PRESET == 29) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.5 - #define FXAA_QUALITY__P2 2.0 - #define FXAA_QUALITY__P3 2.0 - #define FXAA_QUALITY__P4 2.0 - #define FXAA_QUALITY__P5 2.0 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 -#endif - -/*============================================================================ - FXAA QUALITY - EXTREME QUALITY -============================================================================*/ -#if (FXAA_QUALITY__PRESET == 39) - #define FXAA_QUALITY__PS 12 - #define FXAA_QUALITY__P0 1.0 - #define FXAA_QUALITY__P1 1.0 - #define FXAA_QUALITY__P2 1.0 - #define FXAA_QUALITY__P3 1.0 - #define FXAA_QUALITY__P4 1.0 - #define FXAA_QUALITY__P5 1.5 - #define FXAA_QUALITY__P6 2.0 - #define FXAA_QUALITY__P7 2.0 - #define FXAA_QUALITY__P8 2.0 - #define FXAA_QUALITY__P9 2.0 - #define FXAA_QUALITY__P10 4.0 - #define FXAA_QUALITY__P11 8.0 -#endif - - - -/*============================================================================ - - API PORTING - -============================================================================*/ -#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) - #define FxaaBool bool - #define FxaaDiscard discard - #define FxaaFloat float - #define FxaaFloat2 vec2 - #define FxaaFloat3 vec3 - #define FxaaFloat4 vec4 - #define FxaaHalf float - #define FxaaHalf2 vec2 - #define FxaaHalf3 vec3 - #define FxaaHalf4 vec4 - #define FxaaInt2 ivec2 - #define FxaaSat(x) clamp(x, 0.0, 1.0) - #define FxaaTex sampler2D -#else - #define FxaaBool bool - #define FxaaDiscard clip(-1) - #define FxaaFloat float - #define FxaaFloat2 float2 - #define FxaaFloat3 float3 - #define FxaaFloat4 float4 - #define FxaaHalf half - #define FxaaHalf2 half2 - #define FxaaHalf3 half3 - #define FxaaHalf4 half4 - #define FxaaSat(x) saturate(x) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_GLSL_120 == 1) - // Requires, - // #version 120 - // And at least, - // #extension GL_EXT_gpu_shader4 : enable - // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9) - #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0) - #if (FXAA_FAST_PIXEL_OFFSET == 1) - #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) - #else - #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0) - #endif - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) - #define FxaaTexGreen4(t, p) textureGather(t, p, 1) - #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_GLSL_130 == 1) - // Requires "#version 130" or better - #define FxaaTexTop(t, p) textureLod(t, p, 0.0) - #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) - #if (FXAA_GATHER4_ALPHA == 1) - // use #extension GL_ARB_gpu_shader5 : enable - #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) - #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) - #define FxaaTexGreen4(t, p) textureGather(t, p, 1) - #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) - #endif -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) - #define FxaaInt2 float2 - #define FxaaTex sampler2D - #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0)) - #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0)) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_4 == 1) - #define FxaaInt2 int2 - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) -#endif -/*--------------------------------------------------------------------------*/ -#if (FXAA_HLSL_5 == 1) - #define FxaaInt2 int2 - struct FxaaTex { SamplerState smpl; Texture2D tex; }; - #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0) - #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o) - #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p) - #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o) - #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p) - #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o) -#endif - - -/*============================================================================ - GREEN AS LUMA OPTION SUPPORT FUNCTION -============================================================================*/ -#if (FXAA_GREEN_AS_LUMA == 0) - //FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; } - FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return dot(rgba.rgb, FxaaFloat3(0.299, 0.587, 0.114)); } -#else - FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; } -#endif - - - - -/*============================================================================ - - FXAA3 QUALITY - PC - -============================================================================*/ -#if (FXAA_PC == 1) -/*--------------------------------------------------------------------------*/ -FxaaFloat4 FxaaPixelShader( - // - // Use noperspective interpolation here (turn off perspective interpolation). - // {xy} = center of pixel - FxaaFloat2 pos, - // - // Used only for FXAA Console, and not used on the 360 version. - // Use noperspective interpolation here (turn off perspective interpolation). - // {xy__} = upper left of pixel - // {__zw} = lower right of pixel - FxaaFloat4 fxaaConsolePosPos, - // - // Input color texture. - // {rgb_} = color in linear or perceptual color space - // if (FXAA_GREEN_AS_LUMA == 0) - // {___a} = luma in perceptual color space (not linear) - FxaaTex tex, - // - // Only used on the optimized 360 version of FXAA Console. - // For everything but 360, just use the same input here as for "tex". - // For 360, same texture, just alias with a 2nd sampler. - // This sampler needs to have an exponent bias of -1. - FxaaTex fxaaConsole360TexExpBiasNegOne, - // - // Only used on the optimized 360 version of FXAA Console. - // For everything but 360, just use the same input here as for "tex". - // For 360, same texture, just alias with a 3nd sampler. - // This sampler needs to have an exponent bias of -2. - FxaaTex fxaaConsole360TexExpBiasNegTwo, - // - // Only used on FXAA Quality. - // This must be from a constant/uniform. - // {x_} = 1.0/screenWidthInPixels - // {_y} = 1.0/screenHeightInPixels - FxaaFloat2 fxaaQualityRcpFrame, - // - // Only used on FXAA Console. - // This must be from a constant/uniform. - // This effects sub-pixel AA quality and inversely sharpness. - // Where N ranges between, - // N = 0.50 (default) - // N = 0.33 (sharper) - // {x___} = -N/screenWidthInPixels - // {_y__} = -N/screenHeightInPixels - // {__z_} = N/screenWidthInPixels - // {___w} = N/screenHeightInPixels - FxaaFloat4 fxaaConsoleRcpFrameOpt, - // - // Only used on FXAA Console. - // Not used on 360, but used on PS3 and PC. - // This must be from a constant/uniform. - // {x___} = -2.0/screenWidthInPixels - // {_y__} = -2.0/screenHeightInPixels - // {__z_} = 2.0/screenWidthInPixels - // {___w} = 2.0/screenHeightInPixels - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - // - // Only used on FXAA Console. - // Only used on 360 in place of fxaaConsoleRcpFrameOpt2. - // This must be from a constant/uniform. - // {x___} = 8.0/screenWidthInPixels - // {_y__} = 8.0/screenHeightInPixels - // {__z_} = -4.0/screenWidthInPixels - // {___w} = -4.0/screenHeightInPixels - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__SUBPIX define. - // It is here now to allow easier tuning. - // Choose the amount of sub-pixel aliasing removal. - // This can effect sharpness. - // 1.00 - upper limit (softer) - // 0.75 - default amount of filtering - // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) - // 0.25 - almost off - // 0.00 - completely off - FxaaFloat fxaaQualitySubpix, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define. - // It is here now to allow easier tuning. - // The minimum amount of local contrast required to apply algorithm. - // 0.333 - too little (faster) - // 0.250 - low quality - // 0.166 - default - // 0.125 - high quality - // 0.063 - overkill (slower) - FxaaFloat fxaaQualityEdgeThreshold, - // - // Only used on FXAA Quality. - // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define. - // It is here now to allow easier tuning. - // Trims the algorithm from processing darks. - // 0.0833 - upper limit (default, the start of visible unfiltered edges) - // 0.0625 - high quality (faster) - // 0.0312 - visible limit (slower) - // Special notes when using FXAA_GREEN_AS_LUMA, - // Likely want to set this to zero. - // As colors that are mostly not-green - // will appear very dark in the green channel! - // Tune by looking at mostly non-green content, - // then start at zero and increase until aliasing is a problem. - FxaaFloat fxaaQualityEdgeThresholdMin, - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define. - // It is here now to allow easier tuning. - // This does not effect PS3, as this needs to be compiled in. - // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3. - // Due to the PS3 being ALU bound, - // there are only three safe values here: 2 and 4 and 8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // For all other platforms can be a non-power of two. - // 8.0 is sharper (default!!!) - // 4.0 is softer - // 2.0 is really soft (good only for vector graphics inputs) - FxaaFloat fxaaConsoleEdgeSharpness, - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define. - // It is here now to allow easier tuning. - // This does not effect PS3, as this needs to be compiled in. - // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3. - // Due to the PS3 being ALU bound, - // there are only two safe values here: 1/4 and 1/8. - // These options use the shaders ability to a free *|/ by 2|4|8. - // The console setting has a different mapping than the quality setting. - // Other platforms can use other values. - // 0.125 leaves less aliasing, but is softer (default!!!) - // 0.25 leaves more aliasing, and is sharper - FxaaFloat fxaaConsoleEdgeThreshold, - // - // Only used on FXAA Console. - // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define. - // It is here now to allow easier tuning. - // Trims the algorithm from processing darks. - // The console setting has a different mapping than the quality setting. - // This only applies when FXAA_EARLY_EXIT is 1. - // This does not apply to PS3, - // PS3 was simplified to avoid more shader instructions. - // 0.06 - faster but more aliasing in darks - // 0.05 - default - // 0.04 - slower and less aliasing in darks - // Special notes when using FXAA_GREEN_AS_LUMA, - // Likely want to set this to zero. - // As colors that are mostly not-green - // will appear very dark in the green channel! - // Tune by looking at mostly non-green content, - // then start at zero and increase until aliasing is a problem. - FxaaFloat fxaaConsoleEdgeThresholdMin, - // - // Extra constants for 360 FXAA Console only. - // Use zeros or anything else for other platforms. - // These must be in physical constant registers and NOT immedates. - // Immedates will result in compiler un-optimizing. - // {xyzw} = float4(1.0, -1.0, 0.25, -0.25) - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ - FxaaFloat2 posM; - posM.x = pos.x; - posM.y = pos.y; - #if (FXAA_GATHER4_ALPHA == 1) - #if (FXAA_DISCARD == 0) - FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); - #if (FXAA_GREEN_AS_LUMA == 0) - #define lumaM rgbyM.w - #else - #define lumaM rgbyM.y - #endif - #endif - #if (FXAA_GREEN_AS_LUMA == 0) - FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM); - FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1)); - #else - FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM); - FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1)); - #endif - #if (FXAA_DISCARD == 1) - #define lumaM luma4A.w - #endif - #define lumaE luma4A.z - #define lumaS luma4A.x - #define lumaSE luma4A.y - #define lumaNW luma4B.w - #define lumaN luma4B.z - #define lumaW luma4B.x - #else - FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); - #if (FXAA_GREEN_AS_LUMA == 0) - #define lumaM rgbyM.w - #else - #define lumaM rgbyM.y - #endif - FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); - #endif -/*--------------------------------------------------------------------------*/ - FxaaFloat maxSM = max(lumaS, lumaM); - FxaaFloat minSM = min(lumaS, lumaM); - FxaaFloat maxESM = max(lumaE, maxSM); - FxaaFloat minESM = min(lumaE, minSM); - FxaaFloat maxWN = max(lumaN, lumaW); - FxaaFloat minWN = min(lumaN, lumaW); - FxaaFloat rangeMax = max(maxWN, maxESM); - FxaaFloat rangeMin = min(minWN, minESM); - FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; - FxaaFloat range = rangeMax - rangeMin; - FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); - FxaaBool earlyExit = range < rangeMaxClamped; -/*--------------------------------------------------------------------------*/ - if(earlyExit) - #if (FXAA_DISCARD == 1) - FxaaDiscard; - #else - return rgbyM; - #endif -/*--------------------------------------------------------------------------*/ - #if (FXAA_GATHER4_ALPHA == 0) - FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); - #else - FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy)); - FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); - #endif -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNS = lumaN + lumaS; - FxaaFloat lumaWE = lumaW + lumaE; - FxaaFloat subpixRcpRange = 1.0/range; - FxaaFloat subpixNSWE = lumaNS + lumaWE; - FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; - FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNESE = lumaNE + lumaSE; - FxaaFloat lumaNWNE = lumaNW + lumaNE; - FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; - FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNWSW = lumaNW + lumaSW; - FxaaFloat lumaSWSE = lumaSW + lumaSE; - FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); - FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); - FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; - FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; - FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; - FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; -/*--------------------------------------------------------------------------*/ - FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; - FxaaFloat lengthSign = fxaaQualityRcpFrame.x; - FxaaBool horzSpan = edgeHorz >= edgeVert; - FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; -/*--------------------------------------------------------------------------*/ - if(!horzSpan) lumaN = lumaW; - if(!horzSpan) lumaS = lumaE; - if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; - FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; -/*--------------------------------------------------------------------------*/ - FxaaFloat gradientN = lumaN - lumaM; - FxaaFloat gradientS = lumaS - lumaM; - FxaaFloat lumaNN = lumaN + lumaM; - FxaaFloat lumaSS = lumaS + lumaM; - FxaaBool pairN = abs(gradientN) >= abs(gradientS); - FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); - if(pairN) lengthSign = -lengthSign; - FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); -/*--------------------------------------------------------------------------*/ - FxaaFloat2 posB; - posB.x = posM.x; - posB.y = posM.y; - FxaaFloat2 offNP; - offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; - offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; - if(!horzSpan) posB.x += lengthSign * 0.5; - if( horzSpan) posB.y += lengthSign * 0.5; -/*--------------------------------------------------------------------------*/ - FxaaFloat2 posN; - posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; - posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; - FxaaFloat2 posP; - posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; - posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; - FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; - FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); - FxaaFloat subpixE = subpixC * subpixC; - FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); -/*--------------------------------------------------------------------------*/ - if(!pairN) lumaNN = lumaSS; - FxaaFloat gradientScaled = gradient * 1.0/4.0; - FxaaFloat lumaMM = lumaM - lumaNN * 0.5; - FxaaFloat subpixF = subpixD * subpixE; - FxaaBool lumaMLTZero = lumaMM < 0.0; -/*--------------------------------------------------------------------------*/ - lumaEndN -= lumaNN * 0.5; - lumaEndP -= lumaNN * 0.5; - FxaaBool doneN = abs(lumaEndN) >= gradientScaled; - FxaaBool doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; - FxaaBool doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; -/*--------------------------------------------------------------------------*/ - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 3) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 4) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 5) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 6) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 7) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 8) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 9) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 10) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 11) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; -/*--------------------------------------------------------------------------*/ - #if (FXAA_QUALITY__PS > 12) - if(doneNP) { - if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); - if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); - if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; - if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; - doneN = abs(lumaEndN) >= gradientScaled; - doneP = abs(lumaEndP) >= gradientScaled; - if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; - if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; - doneNP = (!doneN) || (!doneP); - if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; - if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } - #endif -/*--------------------------------------------------------------------------*/ - } -/*--------------------------------------------------------------------------*/ - FxaaFloat dstN = posM.x - posN.x; - FxaaFloat dstP = posP.x - posM.x; - if(!horzSpan) dstN = posM.y - posN.y; - if(!horzSpan) dstP = posP.y - posM.y; -/*--------------------------------------------------------------------------*/ - FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; - FxaaFloat spanLength = (dstP + dstN); - FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; - FxaaFloat spanLengthRcp = 1.0/spanLength; -/*--------------------------------------------------------------------------*/ - FxaaBool directionN = dstN < dstP; - FxaaFloat dst = min(dstN, dstP); - FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; - FxaaFloat subpixG = subpixF * subpixF; - FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; - FxaaFloat subpixH = subpixG * fxaaQualitySubpix; -/*--------------------------------------------------------------------------*/ - FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; - FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); - if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; - if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; - #if (FXAA_DISCARD == 1) - return FxaaTexTop(tex, posM); - #else - return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); - #endif -} -/*==========================================================================*/ -#endif - - - - -/*============================================================================ - - FXAA3 CONSOLE - PC VERSION - ------------------------------------------------------------------------------- -Instead of using this on PC, I'd suggest just using FXAA Quality with - #define FXAA_QUALITY__PRESET 10 -Or - #define FXAA_QUALITY__PRESET 20 -Either are higher qualilty and almost as fast as this on modern PC GPUs. -============================================================================*/ -#if (FXAA_PC_CONSOLE == 1) -/*--------------------------------------------------------------------------*/ -FxaaFloat4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy)); - FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw)); - FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy)); - FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw)); -/*--------------------------------------------------------------------------*/ - FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy); - #if (FXAA_GREEN_AS_LUMA == 0) - FxaaFloat lumaM = rgbyM.w; - #else - FxaaFloat lumaM = rgbyM.y; - #endif -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw); - lumaNe += 1.0/384.0; - FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw); -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe); - FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe); -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw); - FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw); -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold; -/*--------------------------------------------------------------------------*/ - FxaaFloat lumaMinM = min(lumaMin, lumaM); - FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled); - FxaaFloat lumaMaxM = max(lumaMax, lumaM); - FxaaFloat dirSwMinusNe = lumaSw - lumaNe; - FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM; - FxaaFloat dirSeMinusNw = lumaSe - lumaNw; - if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM; -/*--------------------------------------------------------------------------*/ - FxaaFloat2 dir; - dir.x = dirSwMinusNe + dirSeMinusNw; - dir.y = dirSwMinusNe - dirSeMinusNw; -/*--------------------------------------------------------------------------*/ - FxaaFloat2 dir1 = normalize(dir.xy); - FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw); - FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw); -/*--------------------------------------------------------------------------*/ - FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness; - FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0); -/*--------------------------------------------------------------------------*/ - FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw); - FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw); -/*--------------------------------------------------------------------------*/ - FxaaFloat4 rgbyA = rgbyN1 + rgbyP1; - FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25); -/*--------------------------------------------------------------------------*/ - #if (FXAA_GREEN_AS_LUMA == 0) - FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax); - #else - FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax); - #endif - if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5; - return rgbyB; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - 360 PIXEL SHADER - ------------------------------------------------------------------------------- -This optimized version thanks to suggestions from Andy Luedke. -Should be fully tex bound in all cases. -As of the FXAA 3.11 release, I have still not tested this code, -however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10. -And note this is replacing the old unoptimized version. -If it does not work, please let me know so I can fix it. -============================================================================*/ -#if (FXAA_360 == 1) -/*--------------------------------------------------------------------------*/ -[reduceTempRegUsage(4)] -float4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ - float4 lumaNwNeSwSe; - #if (FXAA_GREEN_AS_LUMA == 0) - asm { - tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false - }; - #else - asm { - tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false - tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false - }; - #endif -/*--------------------------------------------------------------------------*/ - lumaNwNeSwSe.y += 1.0/384.0; - float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); - float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw); - float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y); - float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y); -/*--------------------------------------------------------------------------*/ - float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0)); - #if (FXAA_GREEN_AS_LUMA == 0) - float lumaMinM = min(lumaMin, rgbyM.w); - float lumaMaxM = max(lumaMax, rgbyM.w); - #else - float lumaMinM = min(lumaMin, rgbyM.y); - float lumaMaxM = max(lumaMax, rgbyM.y); - #endif - if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM; -/*--------------------------------------------------------------------------*/ - float2 dir; - dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx); - dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy); - dir = normalize(dir); -/*--------------------------------------------------------------------------*/ - float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw; -/*--------------------------------------------------------------------------*/ - float4 dir2; - float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness; - dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5); - dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw; -/*--------------------------------------------------------------------------*/ - float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0)); - float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0)); - float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0)); - float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0)); -/*--------------------------------------------------------------------------*/ - float4 rgbyA = rgbyN1 + rgbyP1; - float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5; -/*--------------------------------------------------------------------------*/ - float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; - rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; - return rgbyR; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT) - -============================================================================== -The code below does not exactly match the assembly. -I have a feeling that 12 cycles is possible, but was not able to get there. -Might have to increase register count to get full performance. -Note this shader does not use perspective interpolation. - -Use the following cgc options, - - --fenable-bx2 --fastmath --fastprecision --nofloatbindings - ------------------------------------------------------------------------------- - NVSHADERPERF OUTPUT ------------------------------------------------------------------------------- -For reference and to aid in debug, output of NVShaderPerf should match this, - -Shader to schedule: - 0: texpkb h0.w(TRUE), v5.zyxx, #0 - 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x - 4: texpkb h0.w(TRUE), v5.xwxx, #0 - 6: addh h0.z(TRUE), -h2, h0.w - 7: texpkb h1.w(TRUE), v5, #0 - 9: addh h0.x(TRUE), h0.z, -h1.w - 10: addh h3.w(TRUE), h0.z, h1 - 11: texpkb h2.w(TRUE), v5.zwzz, #0 - 13: addh h0.z(TRUE), h3.w, -h2.w - 14: addh h0.x(TRUE), h2.w, h0 - 15: nrmh h1.xz(TRUE), h0_n - 16: minh_m8 h0.x(TRUE), |h1|, |h1.z| - 17: maxh h4.w(TRUE), h0, h1 - 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n - 19: movr r1.zw(TRUE), v4.xxxy - 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww - 22: minh h5.w(TRUE), h0, h1 - 23: texpkb h0(TRUE), r2.xzxx, #0 - 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1 - 27: maxh h4.x(TRUE), h2.z, h2.w - 28: texpkb h1(TRUE), r0.zwzz, #0 - 30: addh_d2 h1(TRUE), h0, h1 - 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 33: texpkb h0(TRUE), r0, #0 - 35: minh h4.z(TRUE), h2, h2.w - 36: fenct TRUE - 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 39: texpkb h2(TRUE), r1, #0 - 41: addh_d2 h0(TRUE), h0, h2 - 42: maxh h2.w(TRUE), h4, h4.x - 43: minh h2.x(TRUE), h5.w, h4.z - 44: addh_d2 h0(TRUE), h0, h1 - 45: slth h2.x(TRUE), h0.w, h2 - 46: sgth h2.w(TRUE), h0, h2 - 47: movh h0(TRUE), h0 - 48: addx.c0 rc(TRUE), h2, h2.w - 49: movh h0(c0.NE.x), h1 - -IPU0 ------ Simplified schedule: -------- -Pass | Unit | uOp | PC: Op ------+--------+------+------------------------- - 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-; - | | | - 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; - | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0; - | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-; - | | | - 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; - | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0; - | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---; - | SCB1 | add | 10: ADDh h3.w, h0.---z, h1; - | | | - 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | SCB0 | add | 14: ADDh h0.x, h2.w---, h0; - | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-; - | | | - 5 | SCT1 | mov | 15: NRMh h1.xz, h0; - | SRB | nrm | 15: NRMh h1.xz, h0; - | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|; - | SCB1 | max | 17: MAXh h4.w, h0, h1; - | | | - 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0; - | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy; - | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-; - | SCB1 | min | 22: MINh h5.w, h0, h1; - | | | - 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; - | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0; - | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---; - | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1; - | | | - 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; - | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0; - | SCB0/1 | add | 30: ADDh/2 h1, h0, h1; - | | | - 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--; - | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0; - | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0; - | SCB1 | min | 35: MINh h4.z, h2, h2.--w-; - | | | - 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--; - | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0; - | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0; - | SCB0/1 | add | 41: ADDh/2 h0, h0, h2; - | | | - 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---; - | SCT1 | max | 42: MAXh h2.w, h4, h4.---x; - | SCB0/1 | add | 44: ADDh/2 h0, h0, h1; - | | | - 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2; - | SCT1 | set | 46: SGTh h2.w, h0, h2; - | SCB0/1 | mul | 47: MOVh h0, h0; - | | | - 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---; - | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1; - -Pass SCT TEX SCB - 1: 0% 100% 25% - 2: 0% 100% 25% - 3: 0% 100% 50% - 4: 0% 100% 50% - 5: 0% 0% 50% - 6: 100% 0% 75% - 7: 0% 100% 75% - 8: 0% 100% 100% - 9: 0% 100% 25% - 10: 0% 100% 100% - 11: 50% 0% 100% - 12: 50% 0% 100% - 13: 25% 0% 100% - -MEAN: 17% 61% 67% - -Pass SCT0 SCT1 TEX SCB0 SCB1 - 1: 0% 0% 100% 0% 100% - 2: 0% 0% 100% 0% 100% - 3: 0% 0% 100% 100% 100% - 4: 0% 0% 100% 100% 100% - 5: 0% 0% 0% 100% 100% - 6: 100% 100% 0% 100% 100% - 7: 0% 0% 100% 100% 100% - 8: 0% 0% 100% 100% 100% - 9: 0% 0% 100% 0% 100% - 10: 0% 0% 100% 100% 100% - 11: 100% 100% 0% 100% 100% - 12: 100% 100% 0% 100% 100% - 13: 100% 0% 0% 100% 100% - -MEAN: 30% 23% 61% 76% 100% -Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 -Results 13 cycles, 3 r regs, 923,076,923 pixels/s -============================================================================*/ -#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0) -/*--------------------------------------------------------------------------*/ -#pragma regcount 7 -#pragma disablepc all -#pragma option O3 -#pragma option OutColorPrec=fp16 -#pragma texformat default RGBA8 -/*==========================================================================*/ -half4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ -// (1) - half4 dir; - half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - lumaNe.w += half(1.0/512.0); - dir.x = -lumaNe.w; - dir.z = -lumaNe.w; - #else - lumaNe.y += half(1.0/512.0); - dir.x = -lumaNe.y; - dir.z = -lumaNe.y; - #endif -/*--------------------------------------------------------------------------*/ -// (2) - half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x += lumaSw.w; - dir.z += lumaSw.w; - #else - dir.x += lumaSw.y; - dir.z += lumaSw.y; - #endif -/*--------------------------------------------------------------------------*/ -// (3) - half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x -= lumaNw.w; - dir.z += lumaNw.w; - #else - dir.x -= lumaNw.y; - dir.z += lumaNw.y; - #endif -/*--------------------------------------------------------------------------*/ -// (4) - half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x += lumaSe.w; - dir.z -= lumaSe.w; - #else - dir.x += lumaSe.y; - dir.z -= lumaSe.y; - #endif -/*--------------------------------------------------------------------------*/ -// (5) - half4 dir1_pos; - dir1_pos.xy = normalize(dir.xyz).xz; - half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); -/*--------------------------------------------------------------------------*/ -// (6) - half4 dir2_pos; - dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0)); - dir1_pos.zw = pos.xy; - dir2_pos.zw = pos.xy; - half4 temp1N; - temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ -// (7) - temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); - half4 rgby1; - rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; -/*--------------------------------------------------------------------------*/ -// (8) - rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); - rgby1 = (temp1N + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (9) - half4 temp2N; - temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); -/*--------------------------------------------------------------------------*/ -// (10) - half4 rgby2; - rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); - rgby2 = (temp2N + rgby2) * 0.5; -/*--------------------------------------------------------------------------*/ -// (11) - // compilier moves these scalar ops up to other cycles - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w)); - half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w)); - #else - half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y)); - half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y)); - #endif - rgby2 = (rgby2 + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (12) - #if (FXAA_GREEN_AS_LUMA == 0) - bool twoTapLt = rgby2.w < lumaMin; - bool twoTapGt = rgby2.w > lumaMax; - #else - bool twoTapLt = rgby2.y < lumaMin; - bool twoTapGt = rgby2.y > lumaMax; - #endif -/*--------------------------------------------------------------------------*/ -// (13) - if(twoTapLt || twoTapGt) rgby2 = rgby1; -/*--------------------------------------------------------------------------*/ - return rgby2; } -/*==========================================================================*/ -#endif - - - -/*============================================================================ - - FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT) - -============================================================================== -The code mostly matches the assembly. -I have a feeling that 14 cycles is possible, but was not able to get there. -Might have to increase register count to get full performance. -Note this shader does not use perspective interpolation. - -Use the following cgc options, - - --fenable-bx2 --fastmath --fastprecision --nofloatbindings - -Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks). -Will look at fixing this for FXAA 3.12. ------------------------------------------------------------------------------- - NVSHADERPERF OUTPUT ------------------------------------------------------------------------------- -For reference and to aid in debug, output of NVShaderPerf should match this, - -Shader to schedule: - 0: texpkb h0.w(TRUE), v5.zyxx, #0 - 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x - 4: texpkb h1.w(TRUE), v5.xwxx, #0 - 6: addh h0.x(TRUE), h1.w, -h2.y - 7: texpkb h2.w(TRUE), v5.zwzz, #0 - 9: minh h4.w(TRUE), h2.y, h2 - 10: maxh h5.x(TRUE), h2.y, h2.w - 11: texpkb h0.w(TRUE), v5, #0 - 13: addh h3.w(TRUE), -h0, h0.x - 14: addh h0.x(TRUE), h0.w, h0 - 15: addh h0.z(TRUE), -h2.w, h0.x - 16: addh h0.x(TRUE), h2.w, h3.w - 17: minh h5.y(TRUE), h0.w, h1.w - 18: nrmh h2.xz(TRUE), h0_n - 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z| - 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w - 21: movr r1.zw(TRUE), v4.xxxy - 22: maxh h2.w(TRUE), h0, h1 - 23: fenct TRUE - 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz - 26: texpkb h0(TRUE), r0, #0 - 28: maxh h5.x(TRUE), h2.w, h5 - 29: minh h5.w(TRUE), h5.y, h4 - 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz - 32: texpkb h2(TRUE), r1, #0 - 34: addh_d2 h2(TRUE), h0, h2 - 35: texpkb h1(TRUE), v4, #0 - 37: maxh h5.y(TRUE), h5.x, h1.w - 38: minh h4.w(TRUE), h1, h5 - 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 41: texpkb h0(TRUE), r0, #0 - 43: addh_m8 h5.z(TRUE), h5.y, -h4.w - 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz - 46: texpkb h3(TRUE), r2, #0 - 48: addh_d2 h0(TRUE), h0, h3 - 49: addh_d2 h3(TRUE), h0, h2 - 50: movh h0(TRUE), h3 - 51: slth h3.x(TRUE), h3.w, h5.w - 52: sgth h3.w(TRUE), h3, h5.x - 53: addx.c0 rc(TRUE), h3.x, h3 - 54: slth.c0 rc(TRUE), h5.z, h5 - 55: movh h0(c0.NE.w), h2 - 56: movh h0(c0.NE.x), h1 - -IPU0 ------ Simplified schedule: -------- -Pass | Unit | uOp | PC: Op ------+--------+------+------------------------- - 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0; - | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--; - | | | - 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; - | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0; - | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---; - | | | - 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0; - | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---; - | SCB1 | min | 9: MINh h4.w, h2.---y, h2; - | | | - 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; - | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0; - | SCB0 | add | 14: ADDh h0.x, h0.w---, h0; - | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x; - | | | - 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---; - | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-; - | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--; - | | | - 6 | SCT1 | mov | 18: NRMh h2.xz, h0; - | SRB | nrm | 18: NRMh h2.xz, h0; - | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|; - | | | - 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--; - | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy; - | SCB1 | max | 22: MAXh h2.w, h0, h1; - | | | - 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--; - | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0; - | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0; - | SCB0 | max | 28: MAXh h5.x, h2.w---, h5; - | SCB1 | min | 29: MINh h5.w, h5.---y, h4; - | | | - 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--; - | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0; - | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0; - | SCB0/1 | add | 34: ADDh/2 h2, h0, h2; - | | | - 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; - | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0; - | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--; - | SCB1 | min | 38: MINh h4.w, h1, h5; - | | | - 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--; - | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0; - | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0; - | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--; - | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-; - | | | - 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0; - | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0; - | SCB0/1 | add | 48: ADDh/2 h0, h0, h3; - | | | - 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2; - | SCB0/1 | mul | 50: MOVh h0, h3; - | | | - 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---; - | SCT1 | set | 52: SGTh h3.w, h3, h5.---x; - | SCB0 | set | 54: SLThc0 rc, h5.z---, h5; - | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3; - | | | - 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2; - | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1; - -Pass SCT TEX SCB - 1: 0% 100% 25% - 2: 0% 100% 25% - 3: 0% 100% 50% - 4: 0% 100% 50% - 5: 50% 0% 25% - 6: 0% 0% 25% - 7: 100% 0% 25% - 8: 0% 100% 50% - 9: 0% 100% 100% - 10: 0% 100% 50% - 11: 0% 100% 75% - 12: 0% 100% 100% - 13: 100% 0% 100% - 14: 50% 0% 50% - 15: 100% 0% 100% - -MEAN: 26% 60% 56% - -Pass SCT0 SCT1 TEX SCB0 SCB1 - 1: 0% 0% 100% 100% 0% - 2: 0% 0% 100% 100% 0% - 3: 0% 0% 100% 100% 100% - 4: 0% 0% 100% 100% 100% - 5: 100% 100% 0% 100% 0% - 6: 0% 0% 0% 0% 100% - 7: 100% 100% 0% 0% 100% - 8: 0% 0% 100% 100% 100% - 9: 0% 0% 100% 100% 100% - 10: 0% 0% 100% 100% 100% - 11: 0% 0% 100% 100% 100% - 12: 0% 0% 100% 100% 100% - 13: 100% 100% 0% 100% 100% - 14: 100% 100% 0% 100% 100% - 15: 100% 100% 0% 100% 100% - -MEAN: 33% 33% 60% 86% 80% -Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5 -Results 15 cycles, 3 r regs, 800,000,000 pixels/s -============================================================================*/ -#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1) -/*--------------------------------------------------------------------------*/ -#pragma regcount 7 -#pragma disablepc all -#pragma option O2 -#pragma option OutColorPrec=fp16 -#pragma texformat default RGBA8 -/*==========================================================================*/ -half4 FxaaPixelShader( - // See FXAA Quality FxaaPixelShader() source for docs on Inputs! - FxaaFloat2 pos, - FxaaFloat4 fxaaConsolePosPos, - FxaaTex tex, - FxaaTex fxaaConsole360TexExpBiasNegOne, - FxaaTex fxaaConsole360TexExpBiasNegTwo, - FxaaFloat2 fxaaQualityRcpFrame, - FxaaFloat4 fxaaConsoleRcpFrameOpt, - FxaaFloat4 fxaaConsoleRcpFrameOpt2, - FxaaFloat4 fxaaConsole360RcpFrameOpt2, - FxaaFloat fxaaQualitySubpix, - FxaaFloat fxaaQualityEdgeThreshold, - FxaaFloat fxaaQualityEdgeThresholdMin, - FxaaFloat fxaaConsoleEdgeSharpness, - FxaaFloat fxaaConsoleEdgeThreshold, - FxaaFloat fxaaConsoleEdgeThresholdMin, - FxaaFloat4 fxaaConsole360ConstDir -) { -/*--------------------------------------------------------------------------*/ -// (1) - half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaNe = rgbyNe.w + half(1.0/512.0); - #else - half lumaNe = rgbyNe.y + half(1.0/512.0); - #endif -/*--------------------------------------------------------------------------*/ -// (2) - half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaSwNegNe = lumaSw.w - lumaNe; - #else - half lumaSwNegNe = lumaSw.y - lumaNe; - #endif -/*--------------------------------------------------------------------------*/ -// (3) - half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMaxNwSw = max(lumaNw.w, lumaSw.w); - half lumaMinNwSw = min(lumaNw.w, lumaSw.w); - #else - half lumaMaxNwSw = max(lumaNw.y, lumaSw.y); - half lumaMinNwSw = min(lumaNw.y, lumaSw.y); - #endif -/*--------------------------------------------------------------------------*/ -// (4) - half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half dirZ = lumaNw.w + lumaSwNegNe; - half dirX = -lumaNw.w + lumaSwNegNe; - #else - half dirZ = lumaNw.y + lumaSwNegNe; - half dirX = -lumaNw.y + lumaSwNegNe; - #endif -/*--------------------------------------------------------------------------*/ -// (5) - half3 dir; - dir.y = 0.0; - #if (FXAA_GREEN_AS_LUMA == 0) - dir.x = lumaSe.w + dirX; - dir.z = -lumaSe.w + dirZ; - half lumaMinNeSe = min(lumaNe, lumaSe.w); - #else - dir.x = lumaSe.y + dirX; - dir.z = -lumaSe.y + dirZ; - half lumaMinNeSe = min(lumaNe, lumaSe.y); - #endif -/*--------------------------------------------------------------------------*/ -// (6) - half4 dir1_pos; - dir1_pos.xy = normalize(dir).xz; - half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS); -/*--------------------------------------------------------------------------*/ -// (7) - half4 dir2_pos; - dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0)); - dir1_pos.zw = pos.xy; - dir2_pos.zw = pos.xy; - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMaxNeSe = max(lumaNe, lumaSe.w); - #else - half lumaMaxNeSe = max(lumaNe, lumaSe.y); - #endif -/*--------------------------------------------------------------------------*/ -// (8) - half4 temp1N; - temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; - temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0)); - half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe); - half lumaMin = min(lumaMinNwSw, lumaMinNeSe); -/*--------------------------------------------------------------------------*/ -// (9) - half4 rgby1; - rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw; - rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0)); - rgby1 = (temp1N + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (10) - half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0)); - #if (FXAA_GREEN_AS_LUMA == 0) - half lumaMaxM = max(lumaMax, rgbyM.w); - half lumaMinM = min(lumaMin, rgbyM.w); - #else - half lumaMaxM = max(lumaMax, rgbyM.y); - half lumaMinM = min(lumaMin, rgbyM.y); - #endif -/*--------------------------------------------------------------------------*/ -// (11) - half4 temp2N; - temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0)); - half4 rgby2; - rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw; - half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD; -/*--------------------------------------------------------------------------*/ -// (12) - rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0)); - rgby2 = (temp2N + rgby2) * 0.5; -/*--------------------------------------------------------------------------*/ -// (13) - rgby2 = (rgby2 + rgby1) * 0.5; -/*--------------------------------------------------------------------------*/ -// (14) - #if (FXAA_GREEN_AS_LUMA == 0) - bool twoTapLt = rgby2.w < lumaMin; - bool twoTapGt = rgby2.w > lumaMax; - #else - bool twoTapLt = rgby2.y < lumaMin; - bool twoTapGt = rgby2.y > lumaMax; - #endif - bool earlyExit = lumaRangeM < lumaMax; - bool twoTap = twoTapLt || twoTapGt; -/*--------------------------------------------------------------------------*/ -// (15) - if(twoTap) rgby2 = rgby1; - if(earlyExit) rgby2 = rgbyM; -/*--------------------------------------------------------------------------*/ - return rgby2; } -/*==========================================================================*/ -#endif \ No newline at end of file diff --git a/qad/utils/CMakeLists.txt b/utils/CMakeLists.txt similarity index 100% rename from qad/utils/CMakeLists.txt rename to utils/CMakeLists.txt diff --git a/qad/utils/blockeditor/CMakeLists.txt b/utils/blockeditor/CMakeLists.txt similarity index 100% rename from qad/utils/blockeditor/CMakeLists.txt rename to utils/blockeditor/CMakeLists.txt diff --git a/qad/utils/blockeditor/blockeditor_main.cpp b/utils/blockeditor/blockeditor_main.cpp similarity index 100% rename from qad/utils/blockeditor/blockeditor_main.cpp rename to utils/blockeditor/blockeditor_main.cpp diff --git a/qad/utils/blockeditor/icons/blockview.ico b/utils/blockeditor/icons/blockview.ico similarity index 100% rename from qad/utils/blockeditor/icons/blockview.ico rename to utils/blockeditor/icons/blockview.ico diff --git a/qad/utils/blockeditor/icons/blockview.png b/utils/blockeditor/icons/blockview.png similarity index 100% rename from qad/utils/blockeditor/icons/blockview.png rename to utils/blockeditor/icons/blockview.png diff --git a/piqt/utils/cd_pult/CMakeLists.txt b/utils/cd_pult/CMakeLists.txt similarity index 100% rename from piqt/utils/cd_pult/CMakeLists.txt rename to utils/cd_pult/CMakeLists.txt diff --git a/piqt/utils/cd_pult/cddirectk.cpp b/utils/cd_pult/cddirectk.cpp similarity index 100% rename from piqt/utils/cd_pult/cddirectk.cpp rename to utils/cd_pult/cddirectk.cpp diff --git a/piqt/utils/cd_pult/cddirectk.h b/utils/cd_pult/cddirectk.h similarity index 100% rename from piqt/utils/cd_pult/cddirectk.h rename to utils/cd_pult/cddirectk.h diff --git a/piqt/utils/cd_pult/cddirectk.ui b/utils/cd_pult/cddirectk.ui similarity index 100% rename from piqt/utils/cd_pult/cddirectk.ui rename to utils/cd_pult/cddirectk.ui diff --git a/piqt/utils/cd_pult/cddirectk_type_dialog.cpp b/utils/cd_pult/cddirectk_type_dialog.cpp similarity index 100% rename from piqt/utils/cd_pult/cddirectk_type_dialog.cpp rename to utils/cd_pult/cddirectk_type_dialog.cpp diff --git a/piqt/utils/cd_pult/cddirectk_type_dialog.h b/utils/cd_pult/cddirectk_type_dialog.h similarity index 100% rename from piqt/utils/cd_pult/cddirectk_type_dialog.h rename to utils/cd_pult/cddirectk_type_dialog.h diff --git a/piqt/utils/cd_pult/cddirectk_type_dialog.ui b/utils/cd_pult/cddirectk_type_dialog.ui similarity index 100% rename from piqt/utils/cd_pult/cddirectk_type_dialog.ui rename to utils/cd_pult/cddirectk_type_dialog.ui diff --git a/piqt/utils/cd_pult/cdgraphics.cpp b/utils/cd_pult/cdgraphics.cpp similarity index 100% rename from piqt/utils/cd_pult/cdgraphics.cpp rename to utils/cd_pult/cdgraphics.cpp diff --git a/piqt/utils/cd_pult/cdgraphics.h b/utils/cd_pult/cdgraphics.h similarity index 100% rename from piqt/utils/cd_pult/cdgraphics.h rename to utils/cd_pult/cdgraphics.h diff --git a/piqt/utils/cd_pult/cdgraphics.ui b/utils/cd_pult/cdgraphics.ui similarity index 100% rename from piqt/utils/cd_pult/cdgraphics.ui rename to utils/cd_pult/cdgraphics.ui diff --git a/piqt/utils/cd_pult/cdpult.qrc b/utils/cd_pult/cdpult.qrc similarity index 100% rename from piqt/utils/cd_pult/cdpult.qrc rename to utils/cd_pult/cdpult.qrc diff --git a/piqt/utils/cd_pult/cdpultwindow.cpp b/utils/cd_pult/cdpultwindow.cpp similarity index 100% rename from piqt/utils/cd_pult/cdpultwindow.cpp rename to utils/cd_pult/cdpultwindow.cpp diff --git a/piqt/utils/cd_pult/cdpultwindow.h b/utils/cd_pult/cdpultwindow.h similarity index 100% rename from piqt/utils/cd_pult/cdpultwindow.h rename to utils/cd_pult/cdpultwindow.h diff --git a/piqt/utils/cd_pult/cdpultwindow.ui b/utils/cd_pult/cdpultwindow.ui similarity index 100% rename from piqt/utils/cd_pult/cdpultwindow.ui rename to utils/cd_pult/cdpultwindow.ui diff --git a/piqt/utils/cd_pult/cdviewwidget.cpp b/utils/cd_pult/cdviewwidget.cpp similarity index 100% rename from piqt/utils/cd_pult/cdviewwidget.cpp rename to utils/cd_pult/cdviewwidget.cpp diff --git a/piqt/utils/cd_pult/cdviewwidget.h b/utils/cd_pult/cdviewwidget.h similarity index 100% rename from piqt/utils/cd_pult/cdviewwidget.h rename to utils/cd_pult/cdviewwidget.h diff --git a/piqt/utils/cd_pult/cdviewwidget.ui b/utils/cd_pult/cdviewwidget.ui similarity index 100% rename from piqt/utils/cd_pult/cdviewwidget.ui rename to utils/cd_pult/cdviewwidget.ui diff --git a/piqt/utils/cd_pult/icons/Apps-accessories-calculator-icon.png b/utils/cd_pult/icons/Apps-accessories-calculator-icon.png similarity index 100% rename from piqt/utils/cd_pult/icons/Apps-accessories-calculator-icon.png rename to utils/cd_pult/icons/Apps-accessories-calculator-icon.png diff --git a/piqt/utils/cd_pult/icons/accessories-text-editor.png b/utils/cd_pult/icons/accessories-text-editor.png similarity index 100% rename from piqt/utils/cd_pult/icons/accessories-text-editor.png rename to utils/cd_pult/icons/accessories-text-editor.png diff --git a/piqt/utils/cd_pult/icons/db-export.png b/utils/cd_pult/icons/db-export.png similarity index 100% rename from piqt/utils/cd_pult/icons/db-export.png rename to utils/cd_pult/icons/db-export.png diff --git a/piqt/utils/cd_pult/icons/db-import.png b/utils/cd_pult/icons/db-import.png similarity index 100% rename from piqt/utils/cd_pult/icons/db-import.png rename to utils/cd_pult/icons/db-import.png diff --git a/piqt/utils/cd_pult/icons/flame.png b/utils/cd_pult/icons/flame.png similarity index 100% rename from piqt/utils/cd_pult/icons/flame.png rename to utils/cd_pult/icons/flame.png diff --git a/piqt/utils/cd_pult/icons/timer.png b/utils/cd_pult/icons/timer.png similarity index 100% rename from piqt/utils/cd_pult/icons/timer.png rename to utils/cd_pult/icons/timer.png diff --git a/piqt/utils/cd_pult/main.cpp b/utils/cd_pult/main.cpp similarity index 100% rename from piqt/utils/cd_pult/main.cpp rename to utils/cd_pult/main.cpp diff --git a/piqt/utils/piconnedit/CMakeLists.txt b/utils/piconnedit/CMakeLists.txt similarity index 100% rename from piqt/utils/piconnedit/CMakeLists.txt rename to utils/piconnedit/CMakeLists.txt diff --git a/piqt/utils/piconnedit/piconnedit.qrc b/utils/piconnedit/piconnedit.qrc similarity index 100% rename from piqt/utils/piconnedit/piconnedit.qrc rename to utils/piconnedit/piconnedit.qrc diff --git a/piqt/utils/piconnedit/piconnedit_main.cpp b/utils/piconnedit/piconnedit_main.cpp similarity index 100% rename from piqt/utils/piconnedit/piconnedit_main.cpp rename to utils/piconnedit/piconnedit_main.cpp diff --git a/piqt/utils/pidumper/CMakeLists.txt b/utils/pidumper/CMakeLists.txt similarity index 100% rename from piqt/utils/pidumper/CMakeLists.txt rename to utils/pidumper/CMakeLists.txt diff --git a/piqt/utils/pidumper/pidumper.cpp b/utils/pidumper/pidumper.cpp similarity index 100% rename from piqt/utils/pidumper/pidumper.cpp rename to utils/pidumper/pidumper.cpp diff --git a/piqt/utils/pidumper/pidumper.h b/utils/pidumper/pidumper.h similarity index 100% rename from piqt/utils/pidumper/pidumper.h rename to utils/pidumper/pidumper.h diff --git a/piqt/utils/pidumper/pidumper.ui b/utils/pidumper/pidumper.ui similarity index 100% rename from piqt/utils/pidumper/pidumper.ui rename to utils/pidumper/pidumper.ui diff --git a/piqt/utils/pidumper/pidumper_main.cpp b/utils/pidumper/pidumper_main.cpp similarity index 100% rename from piqt/utils/pidumper/pidumper_main.cpp rename to utils/pidumper/pidumper_main.cpp diff --git a/piqt/utils/piintrospector/CMakeLists.txt b/utils/piintrospector/CMakeLists.txt similarity index 100% rename from piqt/utils/piintrospector/CMakeLists.txt rename to utils/piintrospector/CMakeLists.txt diff --git a/piqt/utils/piintrospector/containers_view.cpp b/utils/piintrospector/containers_view.cpp similarity index 100% rename from piqt/utils/piintrospector/containers_view.cpp rename to utils/piintrospector/containers_view.cpp diff --git a/piqt/utils/piintrospector/containers_view.h b/utils/piintrospector/containers_view.h similarity index 100% rename from piqt/utils/piintrospector/containers_view.h rename to utils/piintrospector/containers_view.h diff --git a/piqt/utils/piintrospector/containers_view.ui b/utils/piintrospector/containers_view.ui similarity index 100% rename from piqt/utils/piintrospector/containers_view.ui rename to utils/piintrospector/containers_view.ui diff --git a/piqt/utils/piintrospector/objects_view.cpp b/utils/piintrospector/objects_view.cpp similarity index 100% rename from piqt/utils/piintrospector/objects_view.cpp rename to utils/piintrospector/objects_view.cpp diff --git a/piqt/utils/piintrospector/objects_view.h b/utils/piintrospector/objects_view.h similarity index 100% rename from piqt/utils/piintrospector/objects_view.h rename to utils/piintrospector/objects_view.h diff --git a/piqt/utils/piintrospector/objects_view.ui b/utils/piintrospector/objects_view.ui similarity index 100% rename from piqt/utils/piintrospector/objects_view.ui rename to utils/piintrospector/objects_view.ui diff --git a/piqt/utils/piintrospector/piintrospector.cpp b/utils/piintrospector/piintrospector.cpp similarity index 100% rename from piqt/utils/piintrospector/piintrospector.cpp rename to utils/piintrospector/piintrospector.cpp diff --git a/piqt/utils/piintrospector/piintrospector.h b/utils/piintrospector/piintrospector.h similarity index 100% rename from piqt/utils/piintrospector/piintrospector.h rename to utils/piintrospector/piintrospector.h diff --git a/piqt/utils/piintrospector/piintrospector.ui b/utils/piintrospector/piintrospector.ui similarity index 100% rename from piqt/utils/piintrospector/piintrospector.ui rename to utils/piintrospector/piintrospector.ui diff --git a/piqt/utils/piintrospector/piintrospector_main.cpp b/utils/piintrospector/piintrospector_main.cpp similarity index 100% rename from piqt/utils/piintrospector/piintrospector_main.cpp rename to utils/piintrospector/piintrospector_main.cpp diff --git a/piqt/utils/piintrospector/threads_view.cpp b/utils/piintrospector/threads_view.cpp similarity index 100% rename from piqt/utils/piintrospector/threads_view.cpp rename to utils/piintrospector/threads_view.cpp diff --git a/piqt/utils/piintrospector/threads_view.h b/utils/piintrospector/threads_view.h similarity index 100% rename from piqt/utils/piintrospector/threads_view.h rename to utils/piintrospector/threads_view.h diff --git a/piqt/utils/piintrospector/threads_view.ui b/utils/piintrospector/threads_view.ui similarity index 100% rename from piqt/utils/piintrospector/threads_view.ui rename to utils/piintrospector/threads_view.ui diff --git a/qad/utils/qpicalculator/CMakeLists.txt b/utils/qpicalculator/CMakeLists.txt similarity index 100% rename from qad/utils/qpicalculator/CMakeLists.txt rename to utils/qpicalculator/CMakeLists.txt diff --git a/qad/utils/qpicalculator/icons/qpicalculator.ico b/utils/qpicalculator/icons/qpicalculator.ico similarity index 100% rename from qad/utils/qpicalculator/icons/qpicalculator.ico rename to utils/qpicalculator/icons/qpicalculator.ico diff --git a/qad/utils/qpicalculator/icons/qpicalculator.png b/utils/qpicalculator/icons/qpicalculator.png similarity index 100% rename from qad/utils/qpicalculator/icons/qpicalculator.png rename to utils/qpicalculator/icons/qpicalculator.png diff --git a/qad/utils/qpicalculator/main.cpp b/utils/qpicalculator/main.cpp similarity index 100% rename from qad/utils/qpicalculator/main.cpp rename to utils/qpicalculator/main.cpp diff --git a/qad/utils/qpicalculator/mainwindow.cpp b/utils/qpicalculator/mainwindow.cpp similarity index 100% rename from qad/utils/qpicalculator/mainwindow.cpp rename to utils/qpicalculator/mainwindow.cpp diff --git a/qad/utils/qpicalculator/mainwindow.h b/utils/qpicalculator/mainwindow.h similarity index 100% rename from qad/utils/qpicalculator/mainwindow.h rename to utils/qpicalculator/mainwindow.h diff --git a/qad/utils/qpicalculator/mainwindow.ui b/utils/qpicalculator/mainwindow.ui similarity index 100% rename from qad/utils/qpicalculator/mainwindow.ui rename to utils/qpicalculator/mainwindow.ui diff --git a/qad/utils/qpicalculator/qpicalculator.qrc b/utils/qpicalculator/qpicalculator.qrc similarity index 100% rename from qad/utils/qpicalculator/qpicalculator.qrc rename to utils/qpicalculator/qpicalculator.qrc