source-tree refactoring

This commit is contained in:
2023-02-03 21:22:25 +03:00
parent b20068165f
commit 7d30802cbd
153 changed files with 606 additions and 278 deletions

View File

@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.0)
project(qglengine_widgets)
if (POLICY CMP0017)
cmake_policy(SET CMP0017 NEW)
endif()
qad_find_qt(Qt5 Qt6 Core Gui Widgets)
qad_sources(SRC)
qad_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} ${QGLEngine_LIB_TYPE}
LABEL "QGLEngine widgets library"
FULLNAME "${QGLEngine_DOMAIN}.${PROJECT_NAME}"
COMPANY "${QGLEngine_COMPANY}"
INFO "QGLEngine widgets library")
make_rc(${PROJECT_NAME} _RC)
qad_add_library(${PROJECT_NAME} ${QGLEngine_LIB_TYPE} out_CPP ${_RC})
qad_generate_export_header(${PROJECT_NAME})
list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h")
qad_target_link_libraries(${PROJECT_NAME} QAD::Widgets qglengine_core)
qad_target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${_qglengine_root_build}")
list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME})
shstk_copy_to_parent()
#message(STATUS "Building ${PROJECT_NAME}")
shstk_qad_install("qglengine" FALSE "${PROJECT_NAME}" "${out_HDR}" "out_QM")

View File

@@ -0,0 +1,257 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "material_editor.h"
#include "glmaterial.h"
#include "ui_material_editor.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();
}

View File

@@ -0,0 +1,67 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef MATERIAL_EDITOR_H
#define MATERIAL_EDITOR_H
#include "gltypes.h"
#include <QFileDialog>
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

View File

@@ -0,0 +1,637 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaterialEditor</class>
<widget class="QWidget" name="MaterialEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>435</width>
<height>535</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="MaterialMapEditor" name="mapDiffuse" native="true">
<property name="styleSheet">
<string notr="true">font:normal;</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="MaterialMapEditor" name="mapNormal" native="true">
<property name="styleSheet">
<string notr="true">font:normal;</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="MaterialMapEditor" name="mapMetalness" native="true">
<property name="styleSheet">
<string notr="true">font:normal;</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="MaterialMapEditor" name="mapRoughness" native="true">
<property name="styleSheet">
<string notr="true">font:normal;</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="MaterialMapEditor" name="mapEmission" native="true">
<property name="styleSheet">
<string notr="true">font:normal;</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="MaterialMapEditor" name="mapRelief" native="true">
<property name="styleSheet">
<string notr="true">font:normal;</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="1">
<widget class="QCheckBox" name="checkGlass">
<property name="text">
<string>Glass</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Transparency</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SpinSlider" name="spinTransparent">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Reflectivity</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SpinSlider" name="spinReflect">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>IOF</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="SpinSlider" name="spinIOF">
<property name="maximum">
<double>2.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Dispersion</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="SpinSlider" name="spinDispersion">
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Reflection map</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QFrame" name="frameReflection">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="1" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Front:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Back:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Left:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Right:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>Top:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Bottom:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="lineReflLeft"/>
</item>
<item>
<widget class="QToolButton" name="buttonReflLeftClear">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonReflLeftSelect">
<property name="text">
<string>^</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="lineReflFront"/>
</item>
<item>
<widget class="QToolButton" name="buttonReflFrontClear">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonReflFrontSelect">
<property name="text">
<string>^</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="lineReflBack"/>
</item>
<item>
<widget class="QToolButton" name="buttonReflBackClear">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonReflBackSelect">
<property name="text">
<string>^</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_11">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="lineReflRight"/>
</item>
<item>
<widget class="QToolButton" name="buttonReflRightClear">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonReflRightSelect">
<property name="text">
<string>^</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_12">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="lineReflTop"/>
</item>
<item>
<widget class="QToolButton" name="buttonReflTopClear">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonReflTopSelect">
<property name="text">
<string>^</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_13">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="lineReflBottom"/>
</item>
<item>
<widget class="QToolButton" name="buttonReflBottomClear">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonReflBottomSelect">
<property name="text">
<string>^</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0" colspan="2">
<widget class="QPushButton" name="buttonLoadCubeDir">
<property name="text">
<string>load from directory</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpinSlider</class>
<extends>QWidget</extends>
<header>spinslider.h</header>
</customwidget>
<customwidget>
<class>MaterialMapEditor</class>
<extends>QWidget</extends>
<header>material_map_editor.h</header>
<container>1</container>
<slots>
<signal>changed()</signal>
</slots>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>spinTransparent</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>433</x>
<y>468</y>
</hint>
<hint type="destinationlabel">
<x>283</x>
<y>149</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinReflect</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>433</x>
<y>497</y>
</hint>
<hint type="destinationlabel">
<x>284</x>
<y>174</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinIOF</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>433</x>
<y>526</y>
</hint>
<hint type="destinationlabel">
<x>284</x>
<y>236</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkGlass</sender>
<signal>toggled(bool)</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>433</x>
<y>439</y>
</hint>
<hint type="destinationlabel">
<x>284</x>
<y>84</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinDispersion</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>433</x>
<y>555</y>
</hint>
<hint type="destinationlabel">
<x>326</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>mapDiffuse</sender>
<signal>changed()</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>421</x>
<y>69</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
<y>63</y>
</hint>
</hints>
</connection>
<connection>
<sender>mapMetalness</sender>
<signal>changed()</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>421</x>
<y>189</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
<y>143</y>
</hint>
</hints>
</connection>
<connection>
<sender>mapEmission</sender>
<signal>changed()</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>421</x>
<y>338</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
<y>216</y>
</hint>
</hints>
</connection>
<connection>
<sender>mapNormal</sender>
<signal>changed()</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>421</x>
<y>129</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
<y>260</y>
</hint>
</hints>
</connection>
<connection>
<sender>mapRelief</sender>
<signal>changed()</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>421</x>
<y>398</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
<y>304</y>
</hint>
</hints>
</connection>
<connection>
<sender>mapRoughness</sender>
<signal>changed()</signal>
<receiver>MaterialEditor</receiver>
<slot>materialChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>421</x>
<y>249</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
<y>250</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>materialChanged()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,154 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "material_map_editor.h"
#include "glmaterial.h"
#include "gltexture_manager.h"
#include "ui_material_map_editor.h"
#include <qad_types.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();
}

View File

@@ -0,0 +1,60 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef MATERIAL_MAP_EDITOR_H
#define MATERIAL_MAP_EDITOR_H
#include "gltypes.h"
#include <QFileDialog>
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

View File

@@ -0,0 +1,506 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaterialMapEditor</class>
<widget class="QWidget" name="MaterialMapEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>725</width>
<height>218</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="labelTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">font: bold;</string>
</property>
<property name="text">
<string>title:</string>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="page">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="SpinSlider" name="sliderValue">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="pageStep">
<double>0.200000000000000</double>
</property>
<property name="spinMinimum">
<double>0.000000000000000</double>
</property>
<property name="spinMaximum">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2"/>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkMap">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Map</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="widgetMap" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="IconedLabel" name="iconedLabel">
<property name="direction">
<enum>IconedLabel::RightToLeft</enum>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="linePath"/>
</item>
<item>
<widget class="QToolButton" name="buttonClear">
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonSelect">
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Amount:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SpinSlider" name="sliderAmount">
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="pageStep">
<double>0.200000000000000</double>
</property>
<property name="spinMinimum">
<double>-99.000000000000000</double>
</property>
<property name="spinMaximum">
<double>99.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Offset:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SpinSlider" name="sliderOffset">
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="pageStep">
<double>0.200000000000000</double>
</property>
<property name="spinMinimum">
<double>-99.000000000000000</double>
</property>
<property name="spinMaximum">
<double>99.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Scale X:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinScaleX">
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Scale Y:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinScaleY">
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpinSlider</class>
<extends>QWidget</extends>
<header>spinslider.h</header>
</customwidget>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
<customwidget>
<class>IconedLabel</class>
<extends>QFrame</extends>
<header>iconedlabel.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/utils/qad_utils.qrc"/>
<include location="../../qad/application/qad_application.qrc"/>
</resources>
<connections>
<connection>
<sender>linePath</sender>
<signal>textChanged(QString)</signal>
<receiver>MaterialMapEditor</receiver>
<slot>mapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>598</x>
<y>55</y>
</hint>
<hint type="destinationlabel">
<x>99</x>
<y>73</y>
</hint>
</hints>
</connection>
<connection>
<sender>sliderAmount</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialMapEditor</receiver>
<slot>mapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>655</x>
<y>87</y>
</hint>
<hint type="destinationlabel">
<x>512</x>
<y>37</y>
</hint>
</hints>
</connection>
<connection>
<sender>sliderOffset</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialMapEditor</receiver>
<slot>mapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>655</x>
<y>116</y>
</hint>
<hint type="destinationlabel">
<x>511</x>
<y>65</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinScaleX</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialMapEditor</receiver>
<slot>mapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>491</x>
<y>146</y>
</hint>
<hint type="destinationlabel">
<x>332</x>
<y>164</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinScaleY</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialMapEditor</receiver>
<slot>mapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>647</x>
<y>146</y>
</hint>
<hint type="destinationlabel">
<x>493</x>
<y>164</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkMap</sender>
<signal>toggled(bool)</signal>
<receiver>sliderValue</receiver>
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>693</x>
<y>15</y>
</hint>
<hint type="destinationlabel">
<x>626</x>
<y>14</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkMap</sender>
<signal>toggled(bool)</signal>
<receiver>widgetMap</receiver>
<slot>setVisible(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>686</x>
<y>9</y>
</hint>
<hint type="destinationlabel">
<x>695</x>
<y>62</y>
</hint>
</hints>
</connection>
<connection>
<sender>sliderValue</sender>
<signal>valueChanged(double)</signal>
<receiver>MaterialMapEditor</receiver>
<slot>mapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>99</x>
<y>15</y>
</hint>
<hint type="destinationlabel">
<x>130</x>
<y>28</y>
</hint>
</hints>
</connection>
<connection>
<sender>colorButton</sender>
<signal>colorChanged(QColor)</signal>
<receiver>MaterialMapEditor</receiver>
<slot>mapChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>60</x>
<y>11</y>
</hint>
<hint type="destinationlabel">
<x>75</x>
<y>27</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>mapChanged()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,204 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "materials_editor.h"
#include "glmaterial.h"
#include "material_editor.h"
#include "qglview.h"
#include "ui_materials_editor.h"
#include <QInputDialog>
#include <ecombobox.h>
#include <qad_types.h>
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<Material *> 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<quintptr>()) == 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<quintptr>()) == 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<Material *> 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);
}

View File

@@ -0,0 +1,66 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef MATERIALS_EDITOR_H
#define MATERIALS_EDITOR_H
#include "gltypes.h"
#include <QFileDialog>
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

View File

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaterialsEditor</class>
<widget class="QWidget" name="MaterialsEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>520</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="EComboBox" name="comboMaterial">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="2" rowspan="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QToolButton" name="buttonUnset">
<property name="toolTip">
<string>Unset</string>
</property>
<property name="icon">
<iconset resource="../../qcd_utils/pult/cdpult.qrc">
<normaloff>:/icons/dialog-cancel.png</normaloff>:/icons/dialog-cancel.png</iconset>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QToolButton" name="buttonAssign">
<property name="toolTip">
<string>Assign</string>
</property>
<property name="icon">
<iconset resource="widgets.qrc">
<normaloff>:/icons/go-jump.png</normaloff>:/icons/go-jump.png</iconset>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QToolButton" name="buttonAdd">
<property name="toolTip">
<string>Add</string>
</property>
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="buttonDelete">
<property name="toolTip">
<string>Delete</string>
</property>
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="buttonRename">
<property name="toolTip">
<string>Rename ...</string>
</property>
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/edit-rename.png</normaloff>:/icons/edit-rename.png</iconset>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QToolButton" name="buttonClone">
<property name="toolTip">
<string>Clone</string>
</property>
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/edit-copy.png</normaloff>:/icons/edit-copy.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>440</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="MaterialEditor" name="widgetMaterial" native="true"/>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>421</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>EComboBox</class>
<extends>QComboBox</extends>
<header>ecombobox.h</header>
</customwidget>
<customwidget>
<class>MaterialEditor</class>
<extends>QWidget</extends>
<header>material_editor.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/utils/qad_utils.qrc"/>
<include location="../../qcd_utils/pult/cdpult.qrc"/>
<include location="widgets.qrc"/>
<include location="../qglview.qrc"/>
</resources>
<connections/>
<slots>
<slot>materialChanged()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,261 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "object_editor.h"
#include "qglview.h"
#include "ui_object_editor.h"
#include <scroll_spin_box.h>
#include <spinslider.h>
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<Light *>(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<Camera *>(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<Light *> 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<Light *> 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<Light *> 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<Camera *> 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<Camera *> 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);
}
}

View File

@@ -0,0 +1,62 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef OBJECT_EDITOR_H
#define OBJECT_EDITOR_H
#include "globject.h"
#include <QWidget>
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

View File

@@ -0,0 +1,782 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ObjectEditor</class>
<widget class="QWidget" name="ObjectEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>466</width>
<height>778</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">font: bold;</string>
</property>
<property name="text">
<string>[No selected]</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetMain" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Position</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinPosX"/>
</item>
<item>
<widget class="QLabel" name="label_23">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinPosY"/>
</item>
<item>
<widget class="QLabel" name="label_24">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Z:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinPosZ"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Rotation</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="SpinSlider" name="spinRotationX">
<property name="minimum">
<double>-360.000000000000000</double>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="singleStep">
<double>4.500000000000000</double>
</property>
<property name="pageStep">
<double>90.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>90</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SpinSlider" name="spinRotationY">
<property name="minimum">
<double>-360.000000000000000</double>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>4.500000000000000</double>
</property>
<property name="pageStep">
<double>90.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>90</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Z:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SpinSlider" name="spinRotationZ">
<property name="minimum">
<double>-360.000000000000000</double>
</property>
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>4.500000000000000</double>
</property>
<property name="pageStep">
<double>90.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>90</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Scale</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_25">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>X:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinScaleX"/>
</item>
<item>
<widget class="QLabel" name="label_26">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Y:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinScaleY"/>
</item>
<item>
<widget class="QLabel" name="label_27">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Z:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinScaleZ"/>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="2">
<widget class="QCheckBox" name="checkAcceptFog">
<property name="text">
<string>Accept fog</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="checkAcceptLight">
<property name="text">
<string>Accept light</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkVisible">
<property name="text">
<string>Visible</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkCastShadows">
<property name="text">
<string>Cast shadows</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkReceiveShadows">
<property name="text">
<string>Receive shadows</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="ColorButton" name="buttonColor"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelAimDist">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Aim distance:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="ScrollSpinBox" name="spinAimDist"/>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupLight">
<property name="title">
<string>Light</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboLightType">
<item>
<property name="text">
<string>Omni</string>
</property>
</item>
<item>
<property name="text">
<string>Cone</string>
</property>
</item>
<item>
<property name="text">
<string>Directional</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>Intensity:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SpinSlider" name="spinLightIntensity">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="pageStep">
<double>1.000000000000000</double>
</property>
<property name="squareScale">
<bool>true</bool>
</property>
<property name="spinMaximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>Decay ^0:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SpinSlider" name="spinLightDecayConst">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="pageStep">
<double>1.000000000000000</double>
</property>
<property name="squareScale">
<bool>true</bool>
</property>
<property name="spinMaximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Decay ^1:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="SpinSlider" name="spinLightDecayLinear">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="pageStep">
<double>1.000000000000000</double>
</property>
<property name="squareScale">
<bool>true</bool>
</property>
<property name="spinMaximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Decay ^2:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="SpinSlider" name="spinLightDecayQuadratic">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="pageStep">
<double>1.000000000000000</double>
</property>
<property name="squareScale">
<bool>true</bool>
</property>
<property name="spinMaximum">
<double>999.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelLightAngle">
<property name="text">
<string>Angle:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="SpinSlider" name="spinLightAngleStart">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>180.000000000000000</double>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="singleStep">
<double>5.000000000000000</double>
</property>
<property name="pageStep">
<double>30.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelLightAngleDash">
<property name="text">
<string> - </string>
</property>
</widget>
</item>
<item>
<widget class="SpinSlider" name="spinLightAngleEnd">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>180.000000000000000</double>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="singleStep">
<double>5.000000000000000</double>
</property>
<property name="pageStep">
<double>30.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupCamera">
<property name="title">
<string>Camera</string>
</property>
<layout class="QFormLayout" name="formLayout_5">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_46">
<property name="text">
<string>Depth start:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_45">
<property name="text">
<string>FOV:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SpinSlider" name="spinCameraFOV">
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>179.900000000000006</double>
</property>
<property name="value">
<double>60.000000000000000</double>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="singleStep">
<double>5.000000000000000</double>
</property>
<property name="pageStep">
<double>30.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="checkCameraMirrorY">
<property name="text">
<string>Mirror Y</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkCameraMirrorX">
<property name="text">
<string>Mirror X</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="spinCameraDepthStart">
<property name="decimals">
<number>5</number>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SpinSlider" name="spinCameraRoll">
<property name="minimum">
<double>-180.000000000000000</double>
</property>
<property name="maximum">
<double>180.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="singleStep">
<double>5.000000000000000</double>
</property>
<property name="pageStep">
<double>30.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_47">
<property name="text">
<string>Roll:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpinSlider</class>
<extends>QWidget</extends>
<header>spinslider.h</header>
</customwidget>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
<customwidget>
<class>ScrollSpinBox</class>
<extends>QWidget</extends>
<header>scroll_spin_box.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
<slots>
<slot>objectChanged()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,234 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "primitiveeditor.h"
#include "glmesh.h"
#include "glprimitives.h"
#include "ui_primitiveeditor.h"
#include <QMetaEnum>
#include <qad_types.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<QWidget *> all;
QMetaEnum me = metaObject()->enumerator(0);
for (int i = 0; i < me.keyCount(); ++i) {
ui->comboPrimitives->addItem(me.key(i));
all.unite(QList2QSet(editors[(PrimitiveType)me.value(i)]));
}
all_editors = all.values();
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<QWidget *> 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<QColor>());
}
}
}
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();
}

View File

@@ -0,0 +1,70 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef PRIMITIVEEDITOR_H
#define PRIMITIVEEDITOR_H
#include "qglview.h"
#include <QWidget>
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<PrimitiveType, QList<QWidget *>> editors;
QList<QWidget *> all_editors;
bool can_replace;
private slots:
void selectionChanged();
void replaceMesh();
void on_buttonAdd_clicked();
void on_comboPrimitives_currentIndexChanged(int index);
};
#endif // PRIMITIVEEDITOR_H

View File

@@ -0,0 +1,597 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrimitiveEditor</class>
<widget class="QWidget" name="PrimitiveEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>536</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="EComboBox" name="comboPrimitives"/>
</item>
<item>
<widget class="QWidget" name="widgetRows" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widgetWidth" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Width:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinWidth">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetLength" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Length:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinLength">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetHeight" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinHeight">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRadius1" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Radius 1:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinRadius">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRadius2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Radius 2:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinRadius2">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetAngle" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Angle:</string>
</property>
</widget>
</item>
<item>
<widget class="SpinSlider" name="spinAngle">
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="value">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>4.500000000000000</double>
</property>
<property name="pageStep">
<double>90.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>90</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetSegments" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Segments:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinSegments">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetSegments2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Segments 2:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinSegments2">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetColor" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorButton">
<property name="color">
<color>
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="flipNormals">
<property name="text">
<string>Flip normals</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>176</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="buttonAdd">
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpinSlider</class>
<extends>QWidget</extends>
<header>spinslider.h</header>
</customwidget>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
<customwidget>
<class>EComboBox</class>
<extends>QComboBox</extends>
<header>ecombobox.h</header>
</customwidget>
<customwidget>
<class>ScrollSpinBox</class>
<extends>QWidget</extends>
<header>scroll_spin_box.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/utils/qad_utils.qrc"/>
</resources>
<connections>
<connection>
<sender>spinWidth</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>331</x>
<y>51</y>
</hint>
<hint type="destinationlabel">
<x>368</x>
<y>45</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinLength</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>330</x>
<y>84</y>
</hint>
<hint type="destinationlabel">
<x>369</x>
<y>82</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinHeight</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>334</x>
<y>116</y>
</hint>
<hint type="destinationlabel">
<x>366</x>
<y>114</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinRadius</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>332</x>
<y>144</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>145</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinRadius2</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>334</x>
<y>186</y>
</hint>
<hint type="destinationlabel">
<x>371</x>
<y>181</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinAngle</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>335</x>
<y>210</y>
</hint>
<hint type="destinationlabel">
<x>372</x>
<y>213</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinSegments</sender>
<signal>valueChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>246</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>247</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinSegments2</sender>
<signal>valueChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>336</x>
<y>284</y>
</hint>
<hint type="destinationlabel">
<x>372</x>
<y>279</y>
</hint>
</hints>
</connection>
<connection>
<sender>flipNormals</sender>
<signal>toggled(bool)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>70</x>
<y>344</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>341</y>
</hint>
</hints>
</connection>
<connection>
<sender>comboPrimitives</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>348</x>
<y>9</y>
</hint>
<hint type="destinationlabel">
<x>367</x>
<y>9</y>
</hint>
</hints>
</connection>
<connection>
<sender>colorButton</sender>
<signal>colorChanged(QColor)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>271</x>
<y>285</y>
</hint>
<hint type="destinationlabel">
<x>179</x>
<y>267</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>replaceMesh()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,674 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "propertyeditor.h"
#include "clineedit.h"
#include "colorbutton.h"
#include "qpointedit.h"
#include "qrectedit.h"
#include <QApplication>
#include <QCheckBox>
#include <QPainter>
QWidget * Delegate::widgetForProperty(QWidget * parent, const QModelIndex & index) const {
QWidget * w = nullptr;
int type = 0;
QVariant value = index.data(Qt::UserRole);
if (index.data(Qt::UserRole + 2).toString() == "__flags") return nullptr;
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<QMetaProperty>();
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>()) {
PropertyValuePair prop = value.value<PropertyValuePair>();
if (prop.first.isEnumType()) {
w = new QComboBox(parent);
type = 13;
((QComboBox *)w)->setCurrentIndex(value.toInt());
w->setProperty("__prop", QVariant::fromValue<QMetaProperty>(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 {
#if QT_VERSION_MAJOR <= 5
switch (value.type()) {
#else
switch (value.metaType().id()) {
#endif
#if QT_VERSION_MAJOR <= 5
case QVariant::Int:
#else
case QMetaType::Int:
#endif
w = new QSpinBox(parent);
type = 2;
((QSpinBox *)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF);
connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::UInt:
#else
case QMetaType::UInt:
#endif
w = new QSpinBox(parent);
type = 3;
((QSpinBox *)w)->setRange(0, 0xFFFFFFFF);
connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::LongLong:
#else
case QMetaType::LongLong:
#endif
w = new QSpinBox(parent);
type = 4;
((QSpinBox *)w)->setRange(-0x7FFFFFFF, 0x7FFFFFFF);
connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::ULongLong:
#else
case QMetaType::ULongLong:
#endif
w = new QSpinBox(parent);
type = 5;
((QSpinBox *)w)->setRange(0, 0xFFFFFFFF);
connect((QSpinBox *)w, SIGNAL(valueChanged(int)), this, SLOT(changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Double:
#else
case QMetaType::Double:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::Bool:
#else
case QMetaType::Bool:
#endif
w = new QCheckBox(parent);
type = 7;
((QCheckBox *)w)->setChecked(value.toBool());
connect((QCheckBox *)w, SIGNAL(toggled(bool)), this, SLOT(changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Color:
#else
case QMetaType::QColor:
#endif
w = new ColorButton(parent);
type = 8;
((ColorButton *)w)->setUseAlphaChannel(true);
((ColorButton *)w)->setColor(value.value<QColor>());
connect((ColorButton *)w, SIGNAL(colorChanged(QColor)), this, SLOT(changed()));
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Point:
#else
case QMetaType::QPoint:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::PointF:
#else
case QMetaType::QPointF:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::Rect:
#else
case QMetaType::QRect:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::RectF:
#else
case QMetaType::QRectF:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::String:
default:
#else
case QMetaType::QString:
default:
#endif
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<QColor>()); break;
case 9: ((QPointEdit *)w)->setValue(value.value<QPoint>()); break;
case 10: ((QPointEdit *)w)->setValue(value.value<QPointF>()); break;
case 11: ((QRectEdit *)w)->setValue(value.value<QRect>()); break;
case 12: ((QRectEdit *)w)->setValue(value.value<QRectF>()); break;
}
}
const QVariant Delegate::widgetProperty(QWidget * w) const {
if (w == 0) return QVariant();
switch (w->property("__type").toInt()) {
case 1: return QVariant::fromValue<QString>(((CLineEdit *)w)->text()); break;
case 2: return QVariant::fromValue<int>(((QSpinBox *)w)->value()); break;
case 3: return QVariant::fromValue<uint>(((QSpinBox *)w)->value()); break;
case 4: return QVariant::fromValue<qlonglong>(((QSpinBox *)w)->value()); break;
case 5: return QVariant::fromValue<qulonglong>(((QSpinBox *)w)->value()); break;
case 6: return QVariant::fromValue<double>(((QDoubleSpinBox *)w)->value()); break;
case 7: return QVariant::fromValue<bool>(((QCheckBox *)w)->isChecked()); break;
case 8: return QVariant::fromValue<QColor>(((ColorButton *)w)->color()); break;
case 9: return QVariant::fromValue<QPoint>(((QPointEdit *)w)->value().toPoint()); break;
case 10: return QVariant::fromValue<QPointF>(((QPointEdit *)w)->value()); break;
case 11: return QVariant::fromValue<QRect>(((QRectEdit *)w)->value().toRect()); break;
case 12: return QVariant::fromValue<QRectF>(((QRectEdit *)w)->value()); break;
case 13:
return QVariant::fromValue<PropertyValuePair>(
PropertyValuePair(w->property("__prop").value<QMetaProperty>(), ((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>()) {
PropertyValuePair prop = value.value<PropertyValuePair>();
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 {
#if QT_VERSION_MAJOR <= 5
switch (value.type()) {
#else
switch (value.metaType().id()) {
#endif
#if QT_VERSION_MAJOR <= 5
case QVariant::Int:
#else
case QMetaType::Int:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::UInt:
#else
case QMetaType::UInt:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::LongLong:
#else
case QMetaType::LongLong:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::ULongLong:
#else
case QMetaType::ULongLong:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::Double:
#else
case QMetaType::Double:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::Bool:
#else
case QMetaType::Bool:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::Color:
#else
case QMetaType::QColor:
#endif
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<QColor>());
break;
#if QT_VERSION_MAJOR <= 5
case QVariant::Point:
#else
case QMetaType::QPoint:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::PointF:
#else
case QMetaType::QPointF:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::Rect:
#else
case QMetaType::QRect:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::RectF:
#else
case QMetaType::QRectF:
#endif
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;
#if QT_VERSION_MAJOR <= 5
case QVariant::String:
default:
#else
case QMetaType::QString:
default:
#endif
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<QAbstractItemModel *>(cmi.model());
model->setData(cmi, qobject_cast<QCheckBox *>(sender())->isChecked(), Qt::UserRole + 3);
QModelIndex p = cmi.parent(), mi;
int row = 0;
qulonglong val = 0;
QList<QModelIndex> chldr;
mi = model->index(row, 1, p);
while (mi.isValid()) {
chldr << mi;
model->setData(mi, !mi.data(Qt::UserRole + 4).toBool(), Qt::UserRole + 4);
mi = model->index(++row, 1, p);
}
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<PropertyValuePair>()) {
value = value.value<PropertyValuePair>().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<const QMetaObject *> 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);
tli->setFirstColumnSpanned(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<QMetaProperty>(props.back()));
} else if (props.back().isEnumType())
value.setValue<PropertyValuePair>(PropertyValuePair(props.back(), value));
// ti->setText(1, value.toString());
ti->setData(1, Qt::UserRole, value);
tli->addChild(ti);
// const_cast<QModelIndex & >(indexFromItem(ti, 1)).;
// if (pw != 0) setItemWidget(ti, 1, pw);
}
chue += 60;
chue %= 360;
}
active_ = true;
}
void PropertyEditor::refresh() {}

View File

@@ -0,0 +1,115 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef PROPERTYEDITOR_H
#define PROPERTYEDITOR_H
#include <QDebug>
#include <QEvent>
#include <QHeaderView>
#include <QMetaProperty>
#include <QStyledItemDelegate>
#include <QTreeWidget>
#include <qpiconfigwidget.h>
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<QModelIndex &>(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<QAbstractItemModel *>(cmi.model()), cmi); }
void changedFlag();
};
typedef QPair<QMetaProperty, QVariant> PropertyValuePair;
Q_DECLARE_METATYPE(PropertyValuePair)
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
Q_DECLARE_METATYPE(QMetaProperty)
#endif
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->setBackground(0, c);
i->setBackground(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<QMetaProperty> props;
bool active_;
private slots:
void itemClicked(QTreeWidgetItem * item, int column);
void itemChanged(QTreeWidgetItem * item, int column);
};
#endif // PROPERTYEDITOR_H

521
src/widgets/scene_tree.cpp Normal file
View File

@@ -0,0 +1,521 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "scene_tree.h"
#include "glcamera.h"
#include "qglview.h"
#include "ui_scene_tree.h"
#include <QAction>
#include <QEvent>
#include <QScrollBar>
#include <QTreeWidget>
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);
ui->treeObjects->setItemDelegateForColumn(1, new NoEditDelegate(this));
ui->treeObjects->setItemDelegateForColumn(2, new NoEditDelegate(this));
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<QAction *>()
<< 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<QAction *> SceneTree::actionsAdd() {
QList<QAction *> ret;
ret << ui->actionAdd_node << ui->actionAdd_light << ui->actionAdd_camera;
return ret;
}
QList<QAction *> SceneTree::actionsSelection() {
QList<QAction *> 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::expandItems() {
ui->treeObjects->expandAll();
}
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<QTreeWidgetItem *> 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;
bool has_cam = false;
bool has_mesh = false;
bool is_def_cam = false;
if (view) {
is_def_cam = view->isDefaultCamera();
ObjectBaseList slo = view->selectedObjects();
has_1 = !slo.isEmpty();
has_m = slo.size() > 1;
for (ObjectBase * o: slo) {
if (o->type() == ObjectBase::glCamera) has_cam = (slo.size() == 1);
if (o->type() == ObjectBase::glMesh) has_mesh = true;
}
}
ui->actionFocus->setEnabled(has_mesh);
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_mesh);
ui->actionSelect_by_material->setEnabled(has_mesh);
ui->actionActive_camera->setEnabled(has_cam);
ui->actionDefault_camera->setEnabled(!is_def_cam);
}
void SceneTree::treeObjects_selectionCnahged() {
if (block_tree || !view) return;
block_tree = true;
view->scene()->clearSelection();
ObjectBaseList sol;
QList<QTreeWidgetItem *> 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<QTreeWidgetItem *> 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<QTreeWidgetItem *> 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<ObjectBase *> nsl;
foreach(ObjectBase * o, sol) {
ObjectBase * po = o->parent();
if (po != view->scene()->rootObject()) o = po;
nsl << o;
}
view->scene()->selectObjects(nsl.values());
}
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<QTreeWidgetItem *> sil = ui->treeObjects->selectedItems();
foreach(QTreeWidgetItem * i, sil) {
ObjectBase * o = itemObject(i);
if (o->isSelected(true)) view->scene()->clearSelection();
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);
}

101
src/widgets/scene_tree.h Normal file
View File

@@ -0,0 +1,101 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef SCENE_TREE_H
#define SCENE_TREE_H
#include "glscene.h"
#include <QIcon>
#include <QWidget>
class QTreeWidgetItem;
namespace Ui {
class SceneTree;
}
class SceneTree: public QWidget {
Q_OBJECT
public:
SceneTree(QWidget * parent = 0);
~SceneTree();
void assignQGLView(QGLView * v);
QList<QAction *> actionsAdd();
QList<QAction *> actionsSelection();
void expandItems();
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<ObjectBase *> expanded_;
QList<QTreeWidgetItem *> 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

433
src/widgets/scene_tree.ui Normal file
View File

@@ -0,0 +1,433 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SceneTree</class>
<widget class="QWidget" name="SceneTree">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>442</width>
<height>606</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Filter:</string>
</property>
</widget>
</item>
<item>
<widget class="CLineEdit" name="lineFilter"/>
</item>
<item>
<widget class="QToolButton" name="buttonFilter">
<property name="icon">
<iconset resource="../../qad/libs/application/qad_application.qrc">
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonExpand">
<property name="toolTip">
<string>Expand tree</string>
</property>
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/expand.png</normaloff>:/icons/expand.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonCollapse">
<property name="toolTip">
<string>Collapse tree</string>
</property>
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/collapse.png</normaloff>:/icons/collapse.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="labelCounts">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="InternalMoveTreeWidget" name="treeObjects">
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="autoExpandDelay">
<number>2</number>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Vis</string>
</property>
</column>
<column>
<property name="text">
<string>Material</string>
</property>
</column>
</widget>
</item>
</layout>
<action name="actionFocus">
<property name="icon">
<iconset resource="../../qad/libs/qglview/qglview.qrc">
<normaloff>:/icons/type-camera.png</normaloff>:/icons/type-camera.png</iconset>
</property>
<property name="text">
<string>Focus</string>
</property>
</action>
<action name="actionRemove">
<property name="icon">
<iconset resource="../../qad/libs/blockview/qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
<property name="text">
<string>Remove</string>
</property>
</action>
<action name="actionClone">
<property name="icon">
<iconset resource="../../qad/libs/application/qad_application.qrc">
<normaloff>:/icons/edit-copy.png</normaloff>:/icons/edit-copy.png</iconset>
</property>
<property name="text">
<string>Clone</string>
</property>
</action>
<action name="actionGroup">
<property name="icon">
<iconset resource="widgets.qrc">
<normaloff>:/icons/group.png</normaloff>:/icons/group.png</iconset>
</property>
<property name="text">
<string>Group</string>
</property>
</action>
<action name="actionSelect_parent">
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/go-top.png</normaloff>:/icons/go-top.png</iconset>
</property>
<property name="text">
<string>Select parent</string>
</property>
</action>
<action name="actionSelect_by_mesh">
<property name="icon">
<iconset resource="../../qad/libs/qglview/qglview.qrc">
<normaloff>:/icons/type-geo.png</normaloff>:/icons/type-geo.png</iconset>
</property>
<property name="text">
<string>Select by mesh</string>
</property>
</action>
<action name="actionSelect_by_material">
<property name="icon">
<iconset resource="../../qad/libs/blockview/qad_blockview.qrc">
<normaloff>:/icons/format-fill-color.png</normaloff>:/icons/format-fill-color.png</iconset>
</property>
<property name="text">
<string>Select by material</string>
</property>
</action>
<action name="actionAdd_node">
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/add-type-empty.png</normaloff>:/icons/add-type-empty.png</iconset>
</property>
<property name="text">
<string>Add node</string>
</property>
</action>
<action name="actionAdd_light">
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/add-type-light.png</normaloff>:/icons/add-type-light.png</iconset>
</property>
<property name="text">
<string>Add light</string>
</property>
</action>
<action name="actionAdd_camera">
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/add-type-camera.png</normaloff>:/icons/add-type-camera.png</iconset>
</property>
<property name="text">
<string>Add camera</string>
</property>
</action>
<action name="actionFilter_node">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../qglview.qrc">
<normaloff>:/icons/type-empty.png</normaloff>:/icons/type-empty.png</iconset>
</property>
<property name="text">
<string>Nodes</string>
</property>
</action>
<action name="actionFilter_mesh">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../qad/libs/qglview/qglview.qrc">
<normaloff>:/icons/type-geo.png</normaloff>:/icons/type-geo.png</iconset>
</property>
<property name="text">
<string>Meshes</string>
</property>
</action>
<action name="actionFilter_light">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../qad/libs/qglview/qglview.qrc">
<normaloff>:/icons/type-light.png</normaloff>:/icons/type-light.png</iconset>
</property>
<property name="text">
<string>Lights</string>
</property>
</action>
<action name="actionFilter_camera">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="../../qad/libs/qglview/qglview.qrc">
<normaloff>:/icons/type-camera.png</normaloff>:/icons/type-camera.png</iconset>
</property>
<property name="text">
<string>Cameras</string>
</property>
</action>
<action name="actionTransfer_transform_to_children">
<property name="text">
<string>Transfer transform to children</string>
</property>
</action>
<action name="actionActive_camera">
<property name="icon">
<iconset resource="../../qad/libs/qglview/qglview.qrc">
<normaloff>:/icons/type-camera.png</normaloff>:/icons/type-camera.png</iconset>
</property>
<property name="text">
<string>Active camera</string>
</property>
</action>
<action name="actionDefault_camera">
<property name="icon">
<iconset resource="../../qad/libs/qglview/qglview.qrc">
<normaloff>:/icons/type-camera.png</normaloff>:/icons/type-camera.png</iconset>
</property>
<property name="text">
<string>Default camera</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>CLineEdit</class>
<extends>QLineEdit</extends>
<header>clineedit.h</header>
</customwidget>
<customwidget>
<class>InternalMoveTreeWidget</class>
<extends>QTreeWidget</extends>
<header>treewidget_p.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/libs/application/qad_application.qrc"/>
<include location="../../qad/libs/blockview/qad_blockview.qrc"/>
<include location="../../qad/libs/qglview/qglview.qrc"/>
<include location="widgets.qrc"/>
<include location="../qglview.qrc"/>
<include location="../../qad/libs/application/qad_application.qrc"/>
<include location="../../qad/libs/blockview/qad_blockview.qrc"/>
<include location="../../qad/libs/qglview/qglview.qrc"/>
<include location="../qglview.qrc"/>
<include location="widgets.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonExpand</sender>
<signal>clicked()</signal>
<receiver>treeObjects</receiver>
<slot>expandAll()</slot>
<hints>
<hint type="sourcelabel">
<x>395</x>
<y>164</y>
</hint>
<hint type="destinationlabel">
<x>299</x>
<y>359</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonCollapse</sender>
<signal>clicked()</signal>
<receiver>treeObjects</receiver>
<slot>collapseAll()</slot>
<hints>
<hint type="sourcelabel">
<x>427</x>
<y>164</y>
</hint>
<hint type="destinationlabel">
<x>332</x>
<y>369</y>
</hint>
</hints>
</connection>
<connection>
<sender>lineFilter</sender>
<signal>textChanged(QString)</signal>
<receiver>SceneTree</receiver>
<slot>filter()</slot>
<hints>
<hint type="sourcelabel">
<x>273</x>
<y>130</y>
</hint>
<hint type="destinationlabel">
<x>355</x>
<y>37</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFilter_camera</sender>
<signal>toggled(bool)</signal>
<receiver>SceneTree</receiver>
<slot>filter()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>414</x>
<y>302</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFilter_mesh</sender>
<signal>toggled(bool)</signal>
<receiver>SceneTree</receiver>
<slot>filter()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>414</x>
<y>302</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFilter_light</sender>
<signal>toggled(bool)</signal>
<receiver>SceneTree</receiver>
<slot>filter()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>414</x>
<y>302</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFilter_node</sender>
<signal>toggled(bool)</signal>
<receiver>SceneTree</receiver>
<slot>filter()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>414</x>
<y>302</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>removeObjects()</slot>
<slot>focusObjects()</slot>
<slot>filter()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,60 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef TREEWIDGET_H
#define TREEWIDGET_H
#include <QDebug>
#include <QDropEvent>
#include <QStyledItemDelegate>
#include <QTimer>
#include <QTreeWidget>
class InternalMoveTreeWidget: public QTreeWidget {
Q_OBJECT
public:
InternalMoveTreeWidget(QWidget * parent = 0): QTreeWidget(parent) {}
protected:
virtual void dropEvent(QDropEvent * e) {
QList<QTreeWidgetItem *> 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);
};
class NoEditDelegate: public QStyledItemDelegate {
public:
NoEditDelegate(QObject * parent = 0): QStyledItemDelegate(parent) {}
virtual QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {
return nullptr;
}
};
#endif // TREEWIDGET_H

205
src/widgets/view_editor.cpp Normal file
View File

@@ -0,0 +1,205 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include "view_editor.h"
#include "ui_view_editor.h"
#include <QFileDialog>
#include <colorbutton.h>
#include <spinslider.h>
ViewEditor::ViewEditor(QWidget * parent): QWidget(parent) {
ui = new Ui::ViewEditor();
ui->setupUi(this);
view = nullptr;
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());
ui->checkVSync->setChecked(view->getVSync());
ui->colorFogBack->setColor(view->fogColor());
ui->spinFogDecay->setValue(view->fogDecay());
ui->spinFogDensity->setValue(view->fogDensity());
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);
}
void ViewEditor::on_colorFogBack_colorChanged(const QColor & color) {
if (!view || !active) return;
view->setFogColor(color);
}
void ViewEditor::on_spinFogDensity_valueChanged(double arg1) {
if (!view || !active) return;
view->setFogDensity(arg1);
}
void ViewEditor::on_spinFogDecay_valueChanged(double arg1) {
if (!view || !active) return;
view->setFogDecay(arg1);
}
void ViewEditor::on_checkVSync_clicked(bool val) {
if (!view || !active) return;
view->setVSync(val);
}

69
src/widgets/view_editor.h Normal file
View File

@@ -0,0 +1,69 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef VIEW_EDITOR_H
#define VIEW_EDITOR_H
#include "qglview.h"
#include <QWidget>
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_checkVSync_clicked(bool val);
void on_buttonHDRClear_clicked();
void on_buttonHDRSelect_clicked();
void on_colorFogBack_colorChanged(const QColor & color);
void on_spinFogDensity_valueChanged(double arg1);
void on_spinFogDecay_valueChanged(double arg1);
};
#endif // VIEW_EDITOR_H

512
src/widgets/view_editor.ui Normal file
View File

@@ -0,0 +1,512 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ViewEditor</class>
<widget class="QWidget" name="ViewEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>328</width>
<height>538</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QFormLayout" name="formLayout_9">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Draw mode:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboViewRenderMode">
<property name="currentIndex">
<number>2</number>
</property>
<item>
<property name="text">
<string>Point</string>
</property>
</item>
<item>
<property name="text">
<string>Wireframe</string>
</property>
</item>
<item>
<property name="text">
<string>Solid</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Gamma:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SpinSlider" name="spinViewGamma">
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>5.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Env HDR:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QLineEdit" name="lineHDR"/>
</item>
<item>
<widget class="QToolButton" name="buttonHDRClear">
<property name="icon">
<iconset resource="../../qad/libs/blockview/qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonHDRSelect">
<property name="icon">
<iconset resource="../../qad/libs/blockview/qad_blockview.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QCheckBox" name="checkCameraLight">
<property name="text">
<string>Camera light</string>
</property>
<property name="tristate">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkService">
<property name="text">
<string>Service mode</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkFXAA">
<property name="text">
<string>FXAA</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkAutoExposure">
<property name="text">
<string>Auto exposure</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="checkVSync">
<property name="text">
<string>VSync</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupCamera">
<property name="title">
<string>Camera</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QCheckBox" name="checkCameraOrbit">
<property name="text">
<string>Orbit</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>FOV:</string>
</property>
</widget>
</item>
<item>
<widget class="SpinSlider" name="spinFOV">
<property name="minimum">
<double>0.100000000000000</double>
</property>
<property name="maximum">
<double>179.900000000000006</double>
</property>
<property name="value">
<double>60.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Depth start:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinDepthStart">
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupHoverHalo">
<property name="title">
<string>Hover halo</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_11">
<property name="text">
<string>Fill:</string>
</property>
</widget>
</item>
<item>
<widget class="SpinSlider" name="spinHoverHaloFill">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.300000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorHoverHalo">
<property name="color">
<color>
<red>255</red>
<green>0</green>
<blue>251</blue>
</color>
</property>
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupSelectionHalo">
<property name="title">
<string>Selection halo</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_20">
<property name="text">
<string>Fill:</string>
</property>
</widget>
</item>
<item>
<widget class="SpinSlider" name="spinSelectionHaloFill">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="value">
<double>0.300000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorSelectionHalo">
<property name="color">
<color>
<red>0</red>
<green>143</green>
<blue>239</blue>
</color>
</property>
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Fog</string>
</property>
<layout class="QFormLayout" name="formLayout_10">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Density:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="SpinSlider" name="spinFogDensity">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Decay:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SpinSlider" name="spinFogDecay">
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="value">
<double>10.000000000000000</double>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="pageStep">
<double>0.100000000000000</double>
</property>
<property name="squareScale">
<bool>true</bool>
</property>
<property name="spinMaximum">
<double>9999.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="ColorButton" name="colorFogBack">
<property name="color">
<color>
<red>128</red>
<green>128</green>
<blue>128</blue>
</color>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpinSlider</class>
<extends>QWidget</extends>
<header>spinslider.h</header>
</customwidget>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/libs/blockview/qad_blockview.qrc"/>
</resources>
<connections/>
</ui>

18
src/widgets/widgets.qrc Normal file
View File

@@ -0,0 +1,18 @@
<RCC>
<qresource prefix="/">
<file>../icons/go-jump.png</file>
<file>../icons/dialog-close.png</file>
<file>../icons/dialog-cancel.png</file>
<file>../icons/edit-clear.png</file>
<file>../icons/configure.png</file>
<file>../icons/document-save.png</file>
<file>../icons/edit-find.png</file>
<file>../icons/list-add.png</file>
<file>../icons/edit-delete.png</file>
<file>../icons/edit-copy.png</file>
<file>../icons/edit-paste.png</file>
<file>../icons/document-edit.png</file>
<file>../icons/group.png</file>
<file>../icons/format-fill-color.png</file>
</qresource>
</RCC>