Merge pull request #1751 from openscad/gsoc2016-refactored

GSoC2016 refactored
This commit is contained in:
Marius Kintel 2016-11-07 21:30:14 -05:00 committed by GitHub
commit d06c290cec
74 changed files with 4300 additions and 52 deletions

View file

@ -0,0 +1,61 @@
{
"parameterSets": {
"Medium Size": {
"CenterCandleWidth": "6",
"candleSize": "9",
"centerCandle": "true",
"count": "7",
"heightOfRing": "4",
"heightOfSupport": "3",
"holeSize": "3",
"length": "50",
"radius": "25",
"width": "5",
"widthOfRing": "23",
"widthOfSupport": "3"
},
"small": {
"CenterCandleWidth": "4",
"candleSize": "6",
"centerCandle": "true",
"count": "7",
"heightOfRing": "2",
"heightOfSupport": "2",
"holeSize": "2",
"length": "30",
"radius": "16",
"width": "4",
"widthOfRing": "13",
"widthOfSupport": "2"
},
"With Ball": {
"CenterCandleWidth": "7",
"candleSize": "6",
"centerCandle": "false",
"count": "5",
"heightOfRing": "2",
"heightOfSupport": "2",
"holeSize": "2",
"length": "30",
"radius": "16",
"width": "4",
"widthOfRing": "13",
"widthOfSupport": "2"
},
"Large": {
"CenterCandleWidth": "10",
"candleSize": "9",
"centerCandle": "false",
"count": "7",
"heightOfRing": "4",
"heightOfSupport": "3",
"holeSize": "3",
"length": "70",
"radius": "25",
"width": "5",
"widthOfRing": "23",
"widthOfSupport": "3"
}
},
"fileFormatVersion": "1"
}

View file

@ -0,0 +1,125 @@
/*[ Candle Stand ]*/
//Lenght of candle stand
length=50; // [70:large,50:medium,30:small]
// Center stand
cylinder(length,width-2);
//Radius of ring of stand
radius=25;
/* [ Number of candle holders ]*/
// Number of candle holders
count=7; //[3:14]
//Do you want center Candle
centerCandle=true;
/* [ Candle Holder ]*/
//Lenght of candle holder
candleSize=7;
//Width of candle holder
width=4;
//Size of hole for candle holder
holeSize=3;
CenterCandleWidth=4;
/*[Properties of support]*/
heightOfSupport=3;
widthOfSupport=3;
/*[Properties of Ring]*/
heightOfRing=4;
widthOfRing=23;
//Create center candle
translate([0,0,length-candleSize/2])
if(centerCandle){
difference(){
$fn=360;
cylinder(candleSize,r=CenterCandleWidth);
cylinder(candleSize+1,r=CenterCandleWidth-2);
}
}else{
sphere(CenterCandleWidth);
}
//make ring
translate([0,0,length-candleSize/2]){
make(radius, count,candleSize,length);
//make bottom cover for candle holders
make_ring_of(radius, count){
cylinder(1,r=width);
}
}
//Base of candle stand
for (a = [0 : count - 1]) {
rotate(a*360/count) {
translate([0, -width/2, 0])
cube([radius, widthOfSupport, heightOfSupport]);
}
}
//make ring with candle holders
module make(radius, count,candleSize,length){
$fa = 0.5;
$fs = 0.5;
difference(){
union(){
//making holders
make_ring_of(radius, count){
cylinder(candleSize,r=width);
}
//Attaching holders to stand
for (a = [0 : count - 1]) {
rotate(a*360/count) {
translate([0, -width/2, 0])
cube([radius, widthOfSupport, heightOfSupport]);
}
}
//make ring
linear_extrude(heightOfRing)
difference(){
circle(radius);
circle(widthOfRing);
}
}
//Making holes in candle holder
make_ring_of(radius, count){
cylinder(candleSize+1,r=holeSize);
}
}
}
module make_ring_of(radius, count){
for (a = [0 : count - 1]) {
angle = a * 360 / count;
translate(radius * [cos(angle), -sin(angle), 0])
children();
}
}
// Written by Amarjeet Singh Kapoor <amarjeet.kapoor1@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to the
// public domain worldwide. This software is distributed without any
// warranty.
//
// You should have received a copy of the CC0 Public Domain
// Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

View file

@ -0,0 +1,26 @@
{
"parameterSets": {
"Welcome sign": {
"Message": "Welcome to...",
"To": "Parametric Designs",
"height": "2",
"radius": "80",
"resolution": "30"
},
"Congo Sign": {
"Message": "Congratulations",
"To": "openSCAD",
"height": "2",
"radius": "67",
"resolution": "20"
},
"Happy birthday sign": {
"Message": "Happy Birthday!",
"To": "To Me",
"height": "2",
"radius": "67",
"resolution": "10"
}
},
"fileFormatVersion": "1"
}

View file

@ -0,0 +1,55 @@
// First example of parameteric model
//
// syntax:
// //Description
// variable=value; //Parameter
//
// This type of comment tells the name of group to which parameters below
// this comment will belong
//
// /*[ group name ]*/
//
//Below comment tells the group to which a varaible will belong
/*[ properties of Sign]*/
//The resolution of the curves. Higher values give smoother curves but may increase the model render time.
resolution = 10; //[10, 20, 30, 50, 100]
//The horizontal radius of the outer ellipse of the sign.
radius = 80;//[60 : 200]
//Total height of the sign
height = 2;//[1 : 10]
/*[ Content To be written ] */
//Message to be write
Message = "Welcome to..."; //["Welcome to...", "Happy Birthday!", "Happy Anniversary", "Congratulations", "Thank You"]
//Name of Person, company etc.
To = "Parametric Designs";
$fn = resolution;
scale([1, 0.5]) difference() {
cylinder(r = radius, h = 2 * height, center = true);
translate([0, 0, height])
cylinder(r = radius - 10, h = height + 1, center = true);
}
linear_extrude(height = height) {
translate([0, --4]) text(Message, halign = "center");
translate([0, -16]) text(To, halign = "center");
}
// Written by Amarjeet Singh Kapoor <amarjeet.kapoor1@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to the
// public domain worldwide. This software is distributed without any
// warranty.
//
// You should have received a copy of the CC0 Public Domain
// Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

View file

@ -25,6 +25,10 @@
"animation.scad",
"module_recursion.scad"
],
"Parametric": [
"sign.scad",
"candleStand.scad"
],
"Old": [
"example001.scad",
"example002.scad",

View file

@ -225,7 +225,9 @@ FORMS += src/MainWindow.ui \
src/FontListDialog.ui \
src/ProgressWidget.ui \
src/launchingscreen.ui \
src/LibraryInfoDialog.ui
src/LibraryInfoDialog.ui \
src/parameter/ParameterWidget.ui \
src/parameter/ParameterEntryWidget.ui
# AST nodes
win* {
@ -243,14 +245,47 @@ HEADERS += src/AST.h \
src/expression.h \
src/function.h \
src/module.h \
src/UserModule.h
src/UserModule.h \
SOURCES += src/AST.cc \
src/ModuleInstantiation.cc \
src/expr.cc \
src/function.cc \
src/module.cc \
src/UserModule.cc
src/UserModule.cc \
src/annotation.cc \
src/assignment.cc
# Comment parser
FLEX = src/comment_lexer.l
BISON = src/comment_parser.y
flexs.name = Flex ${QMAKE_FILE_IN}
flexs.input = FLEX
flexs.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.cpp
flexs.commands = flex -o${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_IN}
flexs.CONFIG += target_predeps
flexs.variable_out = GENERATED_SOURCES
silent:flexs.commands = @echo Lex ${QMAKE_FILE_IN} && $$flexs.commands
QMAKE_EXTRA_COMPILERS += flexs
bison.name = Bison ${QMAKE_FILE_IN}
biso.input = BISON
biso.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.cpp
biso.commands = bison -d -o ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_IN}
biso.commands += && if [[ -e ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}_yacc.hpp ]] ; then mv ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.hpp ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.h ; fi
biso.CONFIG += target_predeps
biso.variable_out = GENERATED_SOURCES
silent:biso.commands = @echo Bison ${QMAKE_FILE_IN} && $$biso.commands
QMAKE_EXTRA_COMPILERS += biso
biso_header.input = BISON
biso_header.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.h
biso_header.commands = bison -d -o ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_IN}
biso_header.commands += && if [ -e ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.hpp ]; then mv ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.hpp ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}.h ; fi
biso_header.CONFIG += target_predeps no_link
silent:biso_header.commands = @echo Bison ${QMAKE_FILE_IN} && $$biso.commands
QMAKE_EXTRA_COMPILERS += biso_header
HEADERS += src/version_check.h \
src/ProgressWidget.h \
@ -351,7 +386,22 @@ HEADERS += src/version_check.h \
src/AutoUpdater.h \
src/launchingscreen.h \
src/legacyeditor.h \
src/LibraryInfoDialog.h
src/LibraryInfoDialog.h \
\
src/comment.h\
\
src/parameter/ParameterWidget.h \
src/parameter/parameterobject.h \
src/parameter/parameterextractor.h \
src/parameter/parametervirtualwidget.h \
src/parameter/parameterspinbox.h \
src/parameter/parametercombobox.h \
src/parameter/parameterslider.h \
src/parameter/parametercheckbox.h \
src/parameter/parametertext.h \
src/parameter/parametervector.h \
src/parameter/groupwidget.h \
src/parameter/parameterset.h
SOURCES += \
src/libsvg/libsvg.cc \
@ -475,7 +525,23 @@ SOURCES += \
src/FontListTableView.cc \
src/launchingscreen.cc \
src/legacyeditor.cc \
src/LibraryInfoDialog.cc
src/LibraryInfoDialog.cc\
\
src/comment.cpp \
\
src/parameter/ParameterWidget.cc\
src/parameter/parameterobject.cpp \
src/parameter/parameterextractor.cpp \
src/parameter/parameterspinbox.cpp \
src/parameter/parametercombobox.cpp \
src/parameter/parameterslider.cpp \
src/parameter/parametercheckbox.cpp \
src/parameter/parametertext.cpp \
src/parameter/parametervector.cpp \
src/parameter/groupwidget.cpp \
src/parameter/parameterset.cpp \
src/parameter/parametervirtualwidget.cpp
# ClipperLib
SOURCES += src/polyclipping/clipper.cpp

View file

@ -4,10 +4,12 @@
#include <vector>
#include <utility>
#include "value.h"
#include "AST.h"
#include "memory.h"
#include "annotation.h"
class Assignment : public ASTNode
class Assignment : public ASTNode
{
public:
Assignment(std::string name, const Location &loc)
@ -16,9 +18,17 @@ public:
shared_ptr<class Expression> expr = shared_ptr<class Expression>(),
const Location &loc = Location::NONE)
: ASTNode(loc), name(name), expr(expr) { }
std::string name;
shared_ptr<class Expression> expr;
};
virtual void addAnnotations(AnnotationList *annotations);
virtual bool hasAnnotations() const;
virtual const Annotation *annotation(const std::string &name) const;
protected:
AnnotationMap annotations;
};
typedef std::vector<Assignment> AssignmentList;

View file

@ -64,7 +64,8 @@ public:
QLabel *versionLabel;
QWidget *editorDockTitleWidget;
QWidget *consoleDockTitleWidget;
QWidget *parameterDockTitleWidget;
QString editortype;
bool useScintilla;
@ -112,6 +113,7 @@ private:
static void consoleOutput(const std::string &msg, void *userdata);
void loadViewSettings();
void loadDesignSettings();
void updateWindowSettings(bool console, bool editor, bool customizer, bool toolbar);
void saveBackup();
void writeBackup(class QFile *file);
QString get2dExportFilename(QString format, QString extension);
@ -142,6 +144,7 @@ private slots:
void instantiateRoot();
void compileDone(bool didchange);
void compileEnded();
void changeParameterWidget();
private slots:
void pasteViewportTranslation();
@ -151,6 +154,7 @@ private slots:
void hideEditor();
void hideConsole();
void showConsole();
void hideParameters();
private slots:
void selectFindType(int);
@ -204,9 +208,12 @@ public slots:
void actionReloadRenderPreview();
void on_editorDock_visibilityChanged(bool);
void on_consoleDock_visibilityChanged(bool);
void on_parameterDock_visibilityChanged(bool);
void on_toolButtonCompileResultClose_clicked();
void editorTopLevelChanged(bool);
void consoleTopLevelChanged(bool);
void parameterTopLevelChanged(bool);
#ifdef ENABLE_OPENCSG
void viewModePreview();
#endif

View file

@ -401,6 +401,7 @@
<addaction name="viewActionHideToolBars"/>
<addaction name="viewActionHideEditor"/>
<addaction name="viewActionHideConsole"/>
<addaction name="viewActionHideParameters"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
@ -595,6 +596,36 @@
</layout>
</widget>
</widget>
<widget class="Dock" name="parameterDock">
<property name="windowTitle">
<string>Parameter Widget</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="gridLayout_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>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="ParameterWidget" name="parameterWidget" native="true"/>
</item>
</layout>
</widget>
</widget>
<action name="fileActionNew">
<property name="icon">
<iconset resource="../openscad.qrc">
@ -1331,6 +1362,17 @@
<string>Ctrl+Shift+C</string>
</property>
</action>
<action name="viewActionHideParameters">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Hide Customizer</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
@ -1345,6 +1387,12 @@
<header>Dock.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ParameterWidget</class>
<extends>QWidget</extends>
<header>parameter/ParameterWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../openscad.qrc"/>

View file

@ -271,6 +271,7 @@ void Preferences::featuresCheckBoxToggled(bool state)
feature->enable(state);
QSettings settings;
settings.setValue(QString("feature/%1").arg(QString::fromStdString(feature->get_name())), state);
emit ExperimentalChanged();
}
/**

View file

@ -13,14 +13,14 @@ class Preferences : public QMainWindow, public Ui::Preferences
public:
~Preferences();
static void create(QStringList colorSchemes);
static void create(QStringList colorSchemes);
static Preferences *inst();
QVariant getValue(const QString &key) const;
void init();
void init();
void apply() const;
void fireEditorConfigChanged() const;
void fireEditorConfigChanged() const;
public slots:
void actionTriggered(class QAction *);
@ -84,24 +84,25 @@ signals:
void syntaxHighlightChanged(const QString &s) const;
void editorTypeChanged(const QString &type);
void editorConfigChanged() const;
void ExperimentalChanged() const ;
private:
Preferences(QWidget *parent = NULL);
Preferences(QWidget *parent = NULL);
void keyPressEvent(QKeyEvent *e);
void updateGUI();
void removeDefaultSettings();
void setupFeaturesPage();
void writeSettings();
void writeSettings();
void addPrefPage(QActionGroup *group, QAction *action, QWidget *widget);
/** Initialize combobox list values from the settings range values */
void initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry);
/** Initialize spinbox min/max values from the settings range values */
void initSpinBox(QSpinBox *spinBox, const Settings::SettingsEntry& entry);
/** Update combobox from current settings */
void updateComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry);
/** Set value from combobox to settings */
void applyComboBox(QComboBox *comboBox, int val, Settings::SettingsEntry& entry);
/** Initialize combobox list values from the settings range values */
void initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry);
/** Initialize spinbox min/max values from the settings range values */
void initSpinBox(QSpinBox *spinBox, const Settings::SettingsEntry& entry);
/** Update combobox from current settings */
void updateComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry);
/** Set value from combobox to settings */
void applyComboBox(QComboBox *comboBox, int val, Settings::SettingsEntry& entry);
QSettings::SettingsMap defaultmap;
QHash<const QAction *, QWidget *> prefPages;

56
src/annotation.cc Normal file
View file

@ -0,0 +1,56 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "annotation.h"
#include "expression.h"
#include "context.h"
Annotation::Annotation(const std::string &name, shared_ptr<class Expression> expr)
: name(name), expr(expr)
{
}
Annotation::~Annotation()
{
}
ValuePtr Annotation::evaluate(class Context *ctx) const
{
return this->expr->evaluate(ctx);
}
const std::string & Annotation::getName() const
{
return name;
}
std::string Annotation::dump() const
{
std::stringstream dump;
dump << "//" << name << "(" << *this->expr << ")" << std::endl;
return dump.str();
}

24
src/annotation.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
#include <string>
#include <unordered_map>
#include "memory.h"
#include "value.h"
class Annotation
{
public:
Annotation(const std::string &name, shared_ptr<class Expression> expr);
virtual ~Annotation();
std::string dump() const;
const std::string &getName() const;
virtual ValuePtr evaluate(class Context *ctx) const;
private:
std::string name;
shared_ptr<Expression> expr;
};
typedef std::vector<Annotation> AnnotationList;
typedef std::unordered_map<std::string, Annotation *> AnnotationMap;

46
src/assignment.cc Normal file
View file

@ -0,0 +1,46 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
* This program is distributed in the hope that it will be useful,
*
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "Assignment.h"
#include "annotation.h"
void Assignment::addAnnotations(AnnotationList *annotations)
{
for (auto &annotation : *annotations) {
this->annotations.insert(std::make_pair(annotation.getName(), &annotation));
}
}
bool Assignment::hasAnnotations() const
{
return !annotations.empty();
}
const Annotation * Assignment::annotation(const std::string &name) const
{
auto found = annotations.find(name);
return found == annotations.end() ? nullptr : found->second;
}

306
src/comment.cpp Normal file
View file

@ -0,0 +1,306 @@
#include "comment.h"
#include "expression.h"
#include "annotation.h"
#include <string>
#include <vector>
struct GroupInfo {
std::string commentString;
int lineNo;
};
typedef std::vector <GroupInfo> GroupList;
/*
Finds line to break stop parsing parsing parameters
*/
static int getLineToStop( const std::string &fulltext){
int lineNo=1;
bool inString=false;
for (unsigned int i=0; i<fulltext.length(); i++) {
// increase line number
if (fulltext[i] == '\n') {
lineNo++;
continue;
}
// skip escaped quotes inside strings
if (inString && fulltext.compare(i, 2, "\\\"") == 0) {
i++;
continue;
}
//start or end of string negate the checkpoint
if (fulltext[i] == '"') {
inString = !inString;
continue;
}
if (!inString && fulltext.compare(i, 2, "//") == 0) {
i+=2;
while (fulltext[i] != '\n') i++;
lineNo++;
continue;
}
//start of multi line comment if check is true
if (!inString && fulltext.compare(i, 2, "/*") == 0) {
i += 2;
// till */ every character is comment
while (fulltext.compare(i, 2, "*/") != 0) {
if(fulltext[i]=='\n'){
lineNo++;
}
i++;
}
}
if (fulltext[i]== '{') {
return lineNo;
}
}
return lineNo;
}
/*
Finds the given line in the given source code text, and
extracts the comment (excluding the "//" prefix)
*/
static std::string getComment(const std::string &fulltext, int line)
{
if (line < 1) return "";
// Locate line
unsigned int start = 0;
for (; start<fulltext.length() ; start++) {
if (line <= 1) break;
if (fulltext[start] == '\n') line--;
}
int end = start + 1;
while (fulltext[end] != '\n') end++;
std::string comment = fulltext.substr(start, end - start);
// Locate comment
unsigned int startText = 0;
int noOfSemicolon = 0;
bool inString = false;
for (;startText < comment.length() - 1;startText++) {
if (inString && comment.compare(startText, 2, "\\\"") == 0) {
startText++;
continue;
}
if (comment[startText] == '"') inString = !inString;
if (!inString) {
if (comment.compare(startText, 2, "//") == 0) break;
if (comment[startText] == ';' && noOfSemicolon > 0) return "";
if (comment[startText] == ';') noOfSemicolon++;
}
}
if (startText + 2 > comment.length()) return "";
std::string result = comment.substr(startText + 2);
return result;
}
/*
Extracts a parameter description from comment on the given line.
Returns description, without any "//"
*/
static std::string getDescription(const std::string &fulltext, int line)
{
if (line < 1) return "";
unsigned int start = 0;
for (; start<fulltext.length() ; start++) {
if (line <= 1) break;
if (fulltext[start] == '\n') line--;
}
// not a valid description
if (fulltext.compare(start, 2, "//") != 0) return "";
// Jump over the two forward slashes
start = start+2;
//Jump over all the spaces
while (fulltext[start] == ' ' || fulltext[start] == '\t') start++;
std::string retString = "";
// go till the end of the line
while (fulltext[start] != '\n') {
// replace // with space
if (fulltext.compare(start, 2, "//") == 0) {
retString += " ";
start++;
} else {
retString += fulltext[start];
}
start++;
}
return retString;
}
/*
Create groups by parsing the multi line comment provided
*/
static GroupInfo createGroup(std::string comment,int lineNo)
{
//store info related to group
GroupInfo groupInfo;
std::string finalGroupName; //Final group name
std::string groupName; //group name
bool isGroupName = false;
for (unsigned int it = 0; it < comment.length();it++) {
//Start of Group Name
if (comment[it] == '[') {
isGroupName = true;
continue;
}
//End of Group Name
if (comment[it] == ']') {
isGroupName = false;
//Setting of group name
if (!finalGroupName.empty()) {
finalGroupName = finalGroupName + "-" + groupName;
} else {
finalGroupName = finalGroupName + groupName;
}
groupName.clear();
continue;
}
//collect characters if it belong to group name
if (isGroupName) {
groupName += comment[it];
}
}
groupInfo.commentString = finalGroupName;
groupInfo.lineNo = lineNo;
return groupInfo;
}
/*
This function collect all groups of parameters described in the
scad file.
*/
static GroupList collectGroups(const std::string &fulltext)
{
GroupList groupList; // container of all group names
int lineNo = 1; // tracks line number
bool inString = false; // check if its string or (line-) comment
// iterate through whole scad file
for (unsigned int i=0; i<fulltext.length(); i++) {
// increase line number
if (fulltext[i] == '\n') {
lineNo++;
continue;
}
// skip escaped quotes inside strings
if (inString && fulltext.compare(i, 2, "\\\"") == 0) {
i++;
continue;
}
//start or end of string negate the checkpoint
if (fulltext[i] == '"') {
inString = !inString;
continue;
}
if (!inString && fulltext.compare(i, 2, "//") == 0) {
i+=2;
while (fulltext[i] != '\n') i++;
lineNo++;
continue;
}
//start of multi line comment if check is true
if (!inString && fulltext.compare(i, 2, "/*") == 0) {
//store comment
std::string comment;
i += 2;
bool isGroup=true;
// till */ every character is comment
while (fulltext.compare(i, 2, "*/") != 0) {
if(fulltext[i]=='\n'){
lineNo++;
isGroup=false;
}
comment += fulltext[i];
i++;
}
if(isGroup)
groupList.push_back(createGroup(comment,lineNo));
}
}
return groupList;
}
/*!
Insert Parameters in AST of given scad file
form of annotations
*/
void CommentParser::collectParameters(const char *fulltext, FileModule *root_module)
{
// Get all groups of parameters
GroupList groupList = collectGroups(std::string(fulltext));
int parseTill=getLineToStop(fulltext);
// Extract parameters for all literal assignments
for (auto &assignment : root_module->scope.assignments) {
if (!assignment.expr.get()->isLiteral()) continue; // Only consider literals
// get location of assignment node
int firstLine = assignment.location().firstLine();
if(firstLine>=parseTill) continue;
// making list to add annotations
AnnotationList *annotationList = new AnnotationList();
// Extracting the parameter comment
std::string comment = getComment(std::string(fulltext), firstLine);
// getting the node for parameter annnotataion
shared_ptr<Expression> params = CommentParser::parser(comment.c_str());
if (!params) {
params = shared_ptr<Expression>(new Literal(ValuePtr(std::string(""))));
}
// adding parameter to the list
annotationList->push_back(Annotation("Parameter", params));
//extracting the description
std::string descr = getDescription(std::string(fulltext), firstLine - 1);
if (descr != "") {
//creating node for description
shared_ptr<Expression> expr(new Literal(ValuePtr(std::string(descr.c_str()))));
annotationList->push_back(Annotation("Description", expr));
}
// Look for the group to which the given assignment belong
int i=0;
for (;i<groupList.size() && groupList[i].lineNo<firstLine;i++);
i--;
if (i >= 0) {
//creating node for description
shared_ptr<Expression> expr(new Literal(ValuePtr(groupList[i].commentString)));
annotationList->push_back(Annotation("Group", expr));
}
assignment.addAnnotations(annotationList);
}
}

11
src/comment.h Normal file
View file

@ -0,0 +1,11 @@
#pragma once
#include "FileModule.h"
#include "Assignment.h"
namespace CommentParser {
shared_ptr<Expression> parser(const char *text);
void collectParameters(const char *fulltext, FileModule *root_module);
}

70
src/comment_lexer.l Normal file
View file

@ -0,0 +1,70 @@
%{
#include "Assignment.h"
#include "expression.h"
#include "value.h"
#include "comment_parser.h"
#include <boost/lexical_cast.hpp>
YY_BUFFER_STATE yy_scan_string ( const char *str ) ;
std::string stringcon;
%}
%x cond_string
D [0-9]
E [Ee][-+]?{D}+
H [0-9a-fA-F]
U [\x80-\xbf]
U2 [\xc2-\xdf]
U3 [\xe0-\xef]
U4 [\xf0-\xf4]
UNICODE {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U}
%%
[+-]?{D}+{E}? |
[+-]?{D}*\.{D}+{E}? |
[+-]?{D}+\.{D}*{E}? {
try {
yylval.num = boost::lexical_cast<double>(yytext);
return NUM;
} catch (boost::bad_lexical_cast) {}
}
"[" { return yytext[0];}
"]" { return yytext[0];}
"," { return yytext[0];}
":" { return yytext[0];}
[ \t]
\" { BEGIN(cond_string); stringcon.clear(); }
<cond_string>{
\\n { stringcon += '\n'; }
\\t { stringcon += '\t'; }
\\r { stringcon += '\r'; }
\\\\ { stringcon += '\\'; }
\\\" { stringcon += '"'; }
{UNICODE} { stringcon += yytext; }
[^\\\n\"] { stringcon += yytext; }
\" { BEGIN(INITIAL);
yylval.text = strdup(stringcon.c_str());
return WORD; }
<<EOF>> { BEGIN(INITIAL);
yylval.text = strdup(stringcon.c_str());
return WORD; }
}
[^(\[ \] \, \" \:)]* { yylval.text=strdup(yytext); return WORD;}
. { }
%%
int yywrap(void) {
return 1;
}

135
src/comment_parser.y Normal file
View file

@ -0,0 +1,135 @@
%{
#include <sstream>
#include <string.h>
#include "Assignment.h"
#include "expression.h"
#include "printutils.h"
#include "value.h"
#include "comment.h"
void yyerror(char *);
int yylex(void);
extern void yy_scan_string ( const char *str );
Expression *params;
%}
%union {
char *text;
char ch;
double num;
class Vector *vec;
class Expression *expr;
};
%token<num> NUM
%token<text> WORD
%type <text> word
%type <expr> expr
%type <expr> params
%type <vec> vector_expr
%type <vec> labled_vector
%%
params:
expr
{
$$ = $1;
params = $$;
}
;
expr:
NUM
{
$$ = new Literal(ValuePtr($1));
}
| word
{
$$ = new Literal(ValuePtr(std::string($1)));
free($1);
}
| '[' optional_commas ']'
{
$$ = new Literal(ValuePtr(Value::VectorType()));
}
| '[' vector_expr optional_commas ']'
{
$$ = $2;
}
| '[' expr ':' expr ']'
{
$$ = new Range($2, $4,Location::NONE);
}
| '[' expr ':' expr ':' expr ']'
{
$$ = new Range($2, $4, $6,Location::NONE);
}
| labled_vector { $$=$1;}
;
labled_vector:
expr ':' expr {
$$ = new Vector(Location::NONE);
$$->push_back($1);
$$->push_back($3);
}
;
optional_commas:
',' optional_commas
| /* empty */
;
vector_expr:
expr
{
$$ = new Vector(Location::NONE);
$$->push_back($1);
}
| vector_expr ',' optional_commas expr
{
$$ = $1;
$$->push_back($4);
}
;
word:
WORD
{
$$=$1;
}
| word NUM
{
std::ostringstream strs;
strs << $1 << " " << $2;
$$ = strdup(strs.str().c_str());
}
| NUM word
{
std::ostringstream strs;
strs << $1 << " " << $2;
$$ = strdup(strs.str().c_str());
}
| word WORD
{
std::ostringstream strs;
strs << $1 << " " << $2;
$$ = strdup(strs.str().c_str());
}
%%
void yyerror(char *msg) {
PRINTD("ERROR IN PARAMETER: Parser error in comments of file \n ");
params = NULL;
}
shared_ptr<Expression> CommentParser::parser(const char *text)
{
yy_scan_string(text);
int parserretval = yyparse();
if (parserretval != 0) return NULL;
return shared_ptr<Expression>(params);
}

View file

@ -78,6 +78,11 @@ namespace /* anonymous*/ {
}
bool Expression::isLiteral() const
{
return false;
}
UnaryOp::UnaryOp(UnaryOp::Op op, Expression *expr, const Location &loc) : Expression(loc), op(op), expr(expr)
{
}
@ -110,6 +115,13 @@ const char *UnaryOp::opString() const
}
}
bool UnaryOp::isLiteral() const {
if(this->expr->isLiteral())
return true;
return false;
}
void UnaryOp::print(std::ostream &stream) const
{
stream << opString() << *this->expr;
@ -303,10 +315,30 @@ void Range::print(std::ostream &stream) const
stream << "]";
}
bool Range::isLiteral() const {
if(!this->step){
if( begin->isLiteral() && end->isLiteral())
return true;
}else{
if( begin->isLiteral() && end->isLiteral() && step->isLiteral())
return true;
}
return false;
}
Vector::Vector(const Location &loc) : Expression(loc)
{
}
bool Vector::isLiteral() const {
for(const auto &e : this->children) {
if (!e->isLiteral()){
return false;
}
}
return true;
}
void Vector::push_back(Expression *expr)
{
this->children.push_back(shared_ptr<Expression>(expr));

View file

@ -13,7 +13,7 @@ class Expression : public ASTNode
public:
Expression(const Location &loc) : ASTNode(loc) {}
virtual ~Expression() {}
virtual bool isLiteral() const;
virtual ValuePtr evaluate(const class Context *context) const = 0;
virtual void print(std::ostream &stream) const = 0;
};
@ -27,7 +27,7 @@ public:
Not,
Negate
};
virtual bool isLiteral() const;
UnaryOp(Op op, Expression *expr, const Location &loc);
virtual ValuePtr evaluate(const class Context *context) const;
virtual void print(std::ostream &stream) const;
@ -99,6 +99,7 @@ public:
Literal(const ValuePtr &val, const Location &loc = Location::NONE);
ValuePtr evaluate(const class Context *) const;
virtual void print(std::ostream &stream) const;
virtual bool isLiteral() const { return true;}
private:
ValuePtr value;
};
@ -110,6 +111,7 @@ public:
Range(Expression *begin, Expression *step, Expression *end, const Location &loc);
ValuePtr evaluate(const class Context *context) const;
virtual void print(std::ostream &stream) const;
virtual bool isLiteral() const;
private:
shared_ptr<Expression> begin;
shared_ptr<Expression> step;
@ -123,6 +125,7 @@ public:
ValuePtr evaluate(const class Context *context) const;
virtual void print(std::ostream &stream) const;
void push_back(Expression *expr);
virtual bool isLiteral() const ;
private:
std::vector<shared_ptr<Expression>> children;
};

View file

@ -26,6 +26,8 @@ const Feature Feature::ExperimentalElseExpression("lc-else", "Enable <code>else<
const Feature Feature::ExperimentalForCExpression("lc-for-c", "Enable C-style <code>for</code> expression in list comprehensions.");
const Feature Feature::ExperimentalAmfImport("amf-import", "Enable AMF import.");
const Feature Feature::ExperimentalSvgImport("svg-import", "Enable SVG import.");
const Feature Feature::ExperimentalCustomizer("customizer", "Enable Customizer");
Feature::Feature(const std::string &name, const std::string &description)
: enabled(false), name(name), description(description)

View file

@ -21,6 +21,8 @@ public:
static const Feature ExperimentalForCExpression;
static const Feature ExperimentalAmfImport;
static const Feature ExperimentalSvgImport;
static const Feature ExperimentalCustomizer;
const std::string& get_name() const;
const std::string& get_description() const;

View file

@ -4,6 +4,7 @@
#include "ModuleInstantiation.h"
#include "expression.h"
#include "function.h"
#include "annotation.h"
LocalScope::LocalScope()
{
@ -25,16 +26,24 @@ void LocalScope::addChild(ModuleInstantiation *ch)
std::string LocalScope::dump(const std::string &indent) const
{
std::stringstream dump;
for(const auto &f : this->functions) {
for (const auto &f : this->functions) {
dump << f.second->dump(indent, f.first);
}
for(const auto &m : this->modules) {
for (const auto &m : this->modules) {
dump << m.second->dump(indent, m.first);
}
for(const auto &ass : this->assignments) {
for (const auto &ass : this->assignments) {
if (ass.hasAnnotations()) {
const Annotation *group = ass.annotation("Group");
if (group != NULL) dump << group->dump();
const Annotation *Description = ass.annotation("Description");
if (Description != NULL) dump << Description->dump();
const Annotation *parameter = ass.annotation("Parameter");
if (parameter != NULL) dump << parameter->dump();
}
dump << indent << ass.name << " = " << *ass.expr << ";\n";
}
for(const auto &inst : this->children) {
for (const auto &inst : this->children) {
dump << inst->dump(indent);
}
return dump.str();

View file

@ -24,6 +24,7 @@
*
*/
#include <iostream>
#include "comment.h"
#include "openscad.h"
#include "GeometryCache.h"
#include "ModuleCache.h"
@ -182,11 +183,14 @@ MainWindow::MainWindow(const QString &filename)
editorDockTitleWidget = new QWidget();
consoleDockTitleWidget = new QWidget();
parameterDockTitleWidget = new QWidget();
this->editorDock->setConfigKey("view/hideEditor");
this->editorDock->setAction(this->viewActionHideEditor);
this->consoleDock->setConfigKey("view/hideConsole");
this->consoleDock->setAction(this->viewActionHideConsole);
this->parameterDock->setConfigKey("view/hideCustomizer");
this->parameterDock->setAction(this->viewActionHideParameters);
this->versionLabel = NULL; // must be initialized before calling updateStatusBar()
updateStatusBar(NULL);
@ -283,7 +287,8 @@ MainWindow::MainWindow(const QString &filename)
waitAfterReloadTimer->setSingleShot(true);
waitAfterReloadTimer->setInterval(200);
connect(waitAfterReloadTimer, SIGNAL(timeout()), this, SLOT(waitAfterReload()));
connect(this->parameterWidget, SIGNAL(previewRequested()), this, SLOT(actionRenderPreview()));
connect(Preferences::inst(), SIGNAL(ExperimentalChanged()), this, SLOT(changeParameterWidget()));
connect(this->e_tval, SIGNAL(textChanged(QString)), this, SLOT(updatedAnimTval()));
connect(this->e_fps, SIGNAL(textChanged(QString)), this, SLOT(updatedAnimFps()));
connect(this->e_fsteps, SIGNAL(textChanged(QString)), this, SLOT(updatedAnimSteps()));
@ -417,7 +422,7 @@ MainWindow::MainWindow(const QString &filename)
connect(this->viewActionHideToolBars, SIGNAL(triggered()), this, SLOT(hideToolbars()));
connect(this->viewActionHideEditor, SIGNAL(triggered()), this, SLOT(hideEditor()));
connect(this->viewActionHideConsole, SIGNAL(triggered()), this, SLOT(hideConsole()));
connect(this->viewActionHideParameters, SIGNAL(triggered()), this, SLOT(hideParameters()));
// Help menu
connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout()));
connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage()));
@ -525,12 +530,19 @@ MainWindow::MainWindow(const QString &filename)
initActionIcon(editActionIndent, ":/images/Increase-Indent-32.png", ":/images/Increase-Indent-32-white.png");
initActionIcon(viewActionResetView, ":/images/Command-Reset-32.png", ":/images/Command-Reset-32-white.png");
initActionIcon(viewActionShowScaleProportional, ":/images/scalemarkers.png", ":/images/scalemarkers-white.png");
// fetch window states to be restored after restoreState() call
bool hideConsole = settings.value("view/hideConsole").toBool();
bool hideEditor = settings.value("view/hideEditor").toBool();
bool hideCustomizer = settings.value("view/hideCustomizer").toBool();
bool hideToolbar = settings.value("view/hideToolbar").toBool();
// make sure it looks nice..
QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray();
restoreState(windowState);
resize(settings.value("window/size", QSize(800, 600)).toSize());
move(settings.value("window/position", QPoint(0, 0)).toPoint());
updateWindowSettings(hideConsole, hideEditor, hideCustomizer, hideToolbar);
if (windowState.size() == 0) {
/*
@ -568,7 +580,7 @@ MainWindow::MainWindow(const QString &filename)
connect(this->editorDock, SIGNAL(topLevelChanged(bool)), this, SLOT(editorTopLevelChanged(bool)));
connect(this->consoleDock, SIGNAL(topLevelChanged(bool)), this, SLOT(consoleTopLevelChanged(bool)));
connect(this->parameterDock, SIGNAL(topLevelChanged(bool)), this, SLOT(parameterTopLevelChanged(bool)));
// display this window and check for OpenGL 2.0 (OpenCSG) support
viewModeThrownTogether();
show();
@ -615,7 +627,31 @@ void MainWindow::updateActionUndoState()
editActionUndo->setEnabled(editor->canUndo());
}
void MainWindow::loadViewSettings(){
/**
* Update window settings that get overwritten by the restoreState()
* Qt call. So the values are loaded before the call and restored here
* regardless of the (potential outdated) serialized state.
*/
void MainWindow::updateWindowSettings(bool console, bool editor, bool customizer, bool toolbar)
{
viewActionHideConsole->setChecked(console);
hideConsole();
viewActionHideEditor->setChecked(editor);
hideEditor();
viewActionHideToolBars->setChecked(toolbar);
hideToolbars();
if (Feature::ExperimentalCustomizer.is_enabled()) {
viewActionHideParameters->setChecked(customizer);
hideParameters();
} else {
viewActionHideParameters->setChecked(true);
hideParameters();
viewActionHideParameters->setVisible(false);
}
}
void MainWindow::loadViewSettings() {
QSettings settings;
if (settings.value("view/showEdges").toBool()) {
viewActionShowEdges->setChecked(true);
@ -638,12 +674,7 @@ void MainWindow::loadViewSettings(){
} else {
viewPerspective();
}
viewActionHideConsole->setChecked(settings.value("view/hideConsole").toBool());
hideConsole();
viewActionHideEditor->setChecked(settings.value("view/hideEditor").toBool());
hideEditor();
viewActionHideToolBars->setChecked(settings.value("view/hideToolbar").toBool());
hideToolbars();
updateMdiMode(settings.value("advanced/mdi").toBool());
updateUndockMode(settings.value("advanced/undockableWindows").toBool());
updateReorderMode(settings.value("advanced/reorderWindows").toBool());
@ -674,6 +705,7 @@ void MainWindow::updateUndockMode(bool undockMode)
if (undockMode) {
editorDock->setFeatures(editorDock->features() | QDockWidget::DockWidgetFloatable);
consoleDock->setFeatures(consoleDock->features() | QDockWidget::DockWidgetFloatable);
parameterDock->setFeatures(parameterDock->features() | QDockWidget::DockWidgetFloatable);
} else {
if (editorDock->isFloating()) {
editorDock->setFloating(false);
@ -683,6 +715,10 @@ void MainWindow::updateUndockMode(bool undockMode)
consoleDock->setFloating(false);
}
consoleDock->setFeatures(consoleDock->features() & ~QDockWidget::DockWidgetFloatable);
if (parameterDock->isFloating()) {
parameterDock->setFloating(false);
}
parameterDock->setFeatures(parameterDock->features() & ~QDockWidget::DockWidgetFloatable);
}
}
@ -691,6 +727,7 @@ void MainWindow::updateReorderMode(bool reorderMode)
MainWindow::reorderMode = reorderMode;
editorDock->setTitleBarWidget(reorderMode ? 0 : editorDockTitleWidget);
consoleDock->setTitleBarWidget(reorderMode ? 0 : consoleDockTitleWidget);
parameterDock->setTitleBarWidget(reorderMode ? 0 : parameterDockTitleWidget);
}
MainWindow::~MainWindow()
@ -780,12 +817,15 @@ void MainWindow::setFileName(const QString &filename)
QFileInfo fileinfo(filename);
this->fileName = fileinfo.absoluteFilePath();
setWindowFilePath(this->fileName);
this->parameterWidget->readFile(this->fileName);
QDir::setCurrent(fileinfo.dir().absolutePath());
this->top_ctx.setDocumentPath(fileinfo.dir().absolutePath().toLocal8Bit().constData());
}
editorTopLevelChanged(editorDock->isFloating());
consoleTopLevelChanged(consoleDock->isFloating());
parameterTopLevelChanged(parameterDock->isFloating());
}
void MainWindow::updateRecentFiles()
@ -1423,13 +1463,15 @@ void MainWindow::actionSaveAs()
// defaultSuffix property
QFileInfo info(new_filename);
if (info.exists()) {
if (QMessageBox::warning(this, windowTitle(),
if (QMessageBox::warning(this, windowTitle(),
QString(_("%1 already exists.\nDo you want to replace it?")).arg(info.fileName()),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) {
return;
}
}
}
this->parameterWidget->writeFile(new_filename);
setFileName(new_filename);
actionSave();
}
@ -1709,9 +1751,30 @@ void MainWindow::compileTopLevelDocument()
this->root_module = NULL;
auto fnameba = this->fileName.toLocal8Bit();
const char* fname =
this->fileName.isEmpty() ? "" : fnameba;
const char* fname = this->fileName.isEmpty() ? "" : fnameba;
this->root_module = parse(fulltext.c_str(), fs::path(fname), false);
if (Feature::ExperimentalCustomizer.is_enabled()) {
if (this->root_module!=NULL) {
//add parameters as annotation in AST
CommentParser::collectParameters(fulltext.c_str(),this->root_module);
}
this->parameterWidget->setParameters(this->root_module);
this->parameterWidget->applyParameters(this->root_module);
}
}
void MainWindow::changeParameterWidget()
{
if (Feature::ExperimentalCustomizer.is_enabled()) {
viewActionHideParameters->setVisible(true);
}
else {
viewActionHideParameters->setChecked(true);
hideParameters();
viewActionHideParameters->setVisible(false);
}
emit actionRenderPreview();
}
void MainWindow::checkAutoReload()
@ -1725,9 +1788,9 @@ void MainWindow::autoReloadSet(bool on)
{
QSettings settings;
settings.setValue("design/autoReload",designActionAutoReload->isChecked());
if (on) {
autoReloadTimer->start(200);
} else {
if (on) {
autoReloadTimer->start(200);
} else {
autoReloadTimer->stop();
}
}
@ -2445,6 +2508,11 @@ void MainWindow::on_consoleDock_visibilityChanged(bool)
consoleTopLevelChanged(consoleDock->isFloating());
}
void MainWindow::on_parameterDock_visibilityChanged(bool)
{
parameterTopLevelChanged(parameterDock->isFloating());
}
void MainWindow::editorTopLevelChanged(bool topLevel)
{
setDockWidgetTitle(editorDock, QString(_("Editor")), topLevel);
@ -2455,6 +2523,11 @@ void MainWindow::consoleTopLevelChanged(bool topLevel)
setDockWidgetTitle(consoleDock, QString(_("Console")), topLevel);
}
void MainWindow::parameterTopLevelChanged(bool topLevel)
{
setDockWidgetTitle(parameterDock, QString(_("Customizer")), topLevel);
}
void MainWindow::setDockWidgetTitle(QDockWidget *dockWidget, QString prefix, bool topLevel)
{
QString title(prefix);
@ -2505,6 +2578,15 @@ void MainWindow::hideConsole()
}
}
void MainWindow::hideParameters()
{
if (viewActionHideParameters->isChecked()) {
parameterDock->hide();
} else {
parameterDock->show();
}
}
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls())

View file

@ -25,6 +25,7 @@
*/
#include "openscad.h"
#include "comment.h"
#include "node.h"
#include "module.h"
#include "ModuleInstantiation.h"
@ -46,6 +47,7 @@
#include "OffscreenView.h"
#include "GeometryEvaluator.h"
#include"parameter/parameterset.h"
#include <string>
#include <vector>
#include <fstream>
@ -146,7 +148,8 @@ static void help(const char *progname, bool failure = false)
"%2%[ --colorscheme=[Cornfield|Sunset|Metallic|Starnight|BeforeDawn|Nature|DeepOcean] ] \\\n"
"%2%[ --csglimit=num ]"
#ifdef ENABLE_EXPERIMENTAL
" [ --enable=<feature> ]"
" [ --enable=<feature> ] \\\n"
"%2%[ -p <Parameter Filename>] [-P <Parameter Set>] "
#endif
"\\\n"
#ifdef DEBUG
@ -313,7 +316,7 @@ void set_render_color_scheme(const std::string color_scheme, const bool exit_if_
#include <QCoreApplication>
int cmdline(const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, int argc, char ** argv )
int cmdline(const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer,const std::string &parameterFile,const std::string &setName, int argc, char ** argv )
{
#ifdef OPENSCAD_QTGUI
QCoreApplication app(argc, argv);
@ -399,6 +402,17 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
PRINTB("Can't parse file '%s'!\n", filename.c_str());
return 1;
}
if (Feature::ExperimentalCustomizer.is_enabled()) {
// add parameter to AST
CommentParser::collectParameters(text.c_str(), root_module);
if (!parameterFile.empty() && !setName.empty()) {
ParameterSet param;
param.readParameterSet(parameterFile);
param.applyParameterSet(root_module, setName);
}
}
root_module->handleDependencies();
fs::path fpath = fs::absolute(fs::path(filename));
@ -807,6 +821,8 @@ int main(int argc, char **argv)
("debug", po::value<string>(), "special debug info")
("quiet,q", "quiet mode (don't print anything *except* errors)")
("o,o", po::value<string>(), "out-file")
("p,p", po::value<string>(), "parameter file")
("P,P", po::value<string>(), "parameter set")
("s,s", po::value<string>(), "stl-file")
("x,x", po::value<string>(), "dxf-file")
("d,d", po::value<string>(), "deps-file")
@ -899,6 +915,31 @@ int main(int argc, char **argv)
}
}
#endif
string parameterFile;
string parameterSet;
if (Feature::ExperimentalCustomizer.is_enabled()) {
if (vm.count("p")) {
if (!parameterFile.empty()) help(argv[0], true);
parameterFile = vm["p"].as<string>().c_str();
}
if (vm.count("P")) {
if (!parameterSet.empty()) help(argv[0], true);
parameterSet = vm["P"].as<string>().c_str();
}
}
else {
if (vm.count("p") || vm.count("P")) {
if (!parameterSet.empty()) help(argv[0], true);
PRINT("Customizer feature not activated\n");
help(argv[0], true);
}
}
vector<string> inputFiles;
if (vm.count("input-file")) {
inputFiles = vm["input-file"].as<vector<string>>();
@ -924,7 +965,7 @@ int main(int argc, char **argv)
if (arg_info || cmdlinemode) {
if (inputFiles.size() > 1) help(argv[0], true);
rc = cmdline(deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argc, argv);
rc = cmdline(deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, parameterFile, parameterSet, argc, argv);
}
else if (QtUseGUI()) {
rc = gui(inputFiles, original_path, argc, argv);

View file

@ -0,0 +1,300 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ParameterEntryWidget</class>
<widget class="QWidget" name="ParameterEntryWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>562</width>
<height>144</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item row="2" column="0">
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>4</number>
</property>
<widget class="QWidget" name="pageCheckBox">
<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="QCheckBox" name="checkBox">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageSlider">
<layout class="QGridLayout" name="gridLayout_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>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QSlider" name="slider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labelSliderValue">
<property name="text">
<string>Value</string>
</property>
<property name="margin">
<number>4</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageComboBox">
<layout class="QGridLayout" name="gridLayout_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>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QComboBox" name="comboBox"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageText">
<layout class="QGridLayout" name="gridLayout_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>
<property name="spacing">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="QLineEdit" name="lineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="frame">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageVector">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="doubleSpinBox2">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QDoubleSpinBox" name="doubleSpinBox1">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QDoubleSpinBox" name="doubleSpinBox3">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QDoubleSpinBox" name="doubleSpinBox4">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelDescription">
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<property name="text">
<string>Description</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelParameter">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Parameter</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>doubleSpinBox1</tabstop>
<tabstop>doubleSpinBox2</tabstop>
<tabstop>doubleSpinBox3</tabstop>
<tabstop>doubleSpinBox4</tabstop>
<tabstop>slider</tabstop>
<tabstop>checkBox</tabstop>
<tabstop>comboBox</tabstop>
<tabstop>lineEdit</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,353 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2014 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <QWidget>
#include "ParameterWidget.h"
#include "parameterspinbox.h"
#include "parametercombobox.h"
#include "parameterslider.h"
#include "parametercheckbox.h"
#include "parametertext.h"
#include "parametervector.h"
#include "modcontext.h"
#include "comment.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
namespace pt = boost::property_tree;
#include <QInputDialog>
#include <fstream>
ParameterWidget::ParameterWidget(QWidget *parent) : QWidget(parent)
{
setupUi(this);
descriptionShow = true;
autoPreviewTimer.setInterval(500);
autoPreviewTimer.setSingleShot(true);
connect(&autoPreviewTimer, SIGNAL(timeout()), this, SLOT(onPreviewTimerElapsed()));
connect(checkBoxAutoPreview, SIGNAL(toggled(bool)), this, SLOT(onValueChanged()));
connect(checkBoxDetailedDescription,SIGNAL(toggled(bool)), this,SLOT(onDescriptionShow()));
connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onSetChanged(int)));
connect(reset, SIGNAL(clicked()), this, SLOT(resetParameter()));
}
void ParameterWidget::resetParameter()
{
this->resetPara = true;
emit previewRequested();
}
ParameterWidget::~ParameterWidget()
{
}
void ParameterWidget::onSetDelete()
{
if (root.empty()) return;
std::string setName=comboBox->itemData(this->comboBox->currentIndex()).toString().toStdString();
root.get_child(ParameterSet::parameterSetsKey).erase(setName);
writeParameterSet(this->jsonFile);
this->comboBox->clear();
setComboBoxForSet();
}
void ParameterWidget::onSetAdd()
{
if (root.empty()) {
pt::ptree setRoot;
root.add_child(ParameterSet::parameterSetsKey, setRoot);
}
updateParameterSet(comboBox->itemData(this->comboBox->currentIndex()).toString().toStdString());
}
void ParameterWidget::readFile(QString scadFile)
{
this->jsonFile = scadFile.replace(".scad", ".json").toStdString();
bool readonly=readParameterSet(this->jsonFile);
if(readonly){
connect(this->addButton, SIGNAL(clicked()), this, SLOT(onSetAdd()));
connect(this->deleteButton, SIGNAL(clicked()), this, SLOT(onSetDelete()));
}
else{
this->addButton->setDisabled(true);
this->addButton->setToolTip("JSON file read only");
this->deleteButton->setDisabled(true);
this->deleteButton->setToolTip("JSON file read only");
}
this->comboBox->clear();
setComboBoxForSet();
}
void ParameterWidget::writeFile(QString scadFile)
{
writeParameterSet(scadFile.replace(".scad", ".json").toStdString());
}
void ParameterWidget::setComboBoxForSet()
{
this->comboBox->addItem("No Set Selected", QVariant(QString::fromStdString("")));
if (root.empty()) return;
for (const auto &name : getParameterNames()) {
const QString n = QString::fromStdString(name);
this->comboBox->addItem(n, QVariant(n));
}
}
void ParameterWidget::onSetChanged(int idx)
{
const std::string v = comboBox->itemData(idx).toString().toUtf8().constData();
applyParameterSet(v);
emit previewRequested();
}
void ParameterWidget::onDescriptionShow()
{
if (checkBoxDetailedDescription->isChecked()) {
descriptionShow = true;
} else {
descriptionShow = false;
}
emit previewRequested();
}
void ParameterWidget::onValueChanged()
{
autoPreviewTimer.stop();
if (checkBoxAutoPreview->isChecked()) {
autoPreviewTimer.start();
}
}
void ParameterWidget::onPreviewTimerElapsed()
{
emit previewRequested();
}
void ParameterWidget::begin()
{
QLayoutItem *child;
while ((child = this->scrollAreaWidgetContents->layout()->takeAt(0)) != 0) {
QWidget *w = child->widget();
this->scrollAreaWidgetContents->layout()->removeWidget(w);
delete w;
}
anyLayout = new QVBoxLayout();
}
void ParameterWidget::addEntry(ParameterVirtualWidget *entry)
{
QSizePolicy policy;
policy.setHorizontalPolicy(QSizePolicy::Expanding);
policy.setVerticalPolicy(QSizePolicy::Preferred);
policy.setHorizontalStretch(0);
policy.setVerticalStretch(0);
entry->setSizePolicy(policy);
anyLayout->addWidget(entry);
}
void ParameterWidget::end()
{
QSizePolicy policy;
policy.setHorizontalPolicy(QSizePolicy::Expanding);
policy.setVerticalPolicy(QSizePolicy::Preferred);
policy.setHorizontalStretch(0);
policy.setVerticalStretch(1);
QLabel *label = new QLabel("");
label->setSizePolicy(policy);
this->scrollAreaWidgetContents->layout()->addWidget(label);
}
void ParameterWidget::connectWidget()
{
anyfocused = false;
// clear previous entries in groupMap and entries
clear();
std::vector<std::string> global;
if (groupMap.find("Global") != groupMap.end()) {
global = groupMap["Global"].parameterVector;
groupMap["Global"].parameterVector.clear();
}
for (group_map::iterator it = groupMap.begin(); it != groupMap.end(); ) {
std::vector<std::string> gr;
gr = it->second.parameterVector;
if (gr.empty() || it->first == "Hidden") {
it = groupMap.erase(it);
}
else {
it->second.parameterVector.insert(it->second.parameterVector.end(), global.begin(), global.end());
it++;
}
}
begin();
for (group_map::iterator it = groupMap.begin(); it != groupMap.end(); it++) {
std::vector<std::string> gr;
gr = it->second.parameterVector;
for(unsigned int i=0;i < gr.size();i++) {
AddParameterWidget(gr[i]);
}
GroupWidget *groupWidget = new GroupWidget(it->second.show, QString::fromStdString(it->first));
groupWidget->setContentLayout(*anyLayout);
this->scrollAreaWidgetContents->layout()->addWidget(groupWidget);
anyLayout = new QVBoxLayout();
}
end();
if (anyfocused != 0){
entryToFocus->setParameterFocus();
}
}
void ParameterWidget::clear(){
for (entry_map_t::iterator it = entries.begin(); it != entries.end();) {
if (!(*it).second->set) {
it = entries.erase(it);
} else {
it++;
}
}
for (group_map::iterator it = groupMap.begin(); it != groupMap.end(); it++) {
it->second.parameterVector.clear();
}
for (entry_map_t::iterator it = entries.begin(); it != entries.end(); it++) {
if (groupMap.find(it->second->groupName) == groupMap.end()) {
groupInst enter;
enter.parameterVector.push_back(it->first);
enter.show = false;
groupMap[it->second->groupName] = enter;
}
else {
groupMap[it->second->groupName].parameterVector.push_back(it->first);
}
}
}
void ParameterWidget::AddParameterWidget(std::string parameterName)
{
ParameterVirtualWidget *entry ;
switch(entries[parameterName]->target) {
case ParameterObject::COMBOBOX:{
entry = new ParameterComboBox(entries[parameterName], descriptionShow);
break;
}
case ParameterObject::SLIDER:{
entry = new ParameterSlider(entries[parameterName], descriptionShow);
break;
}
case ParameterObject::CHECKBOX:{
entry = new ParameterCheckBox(entries[parameterName], descriptionShow);
break;
}
case ParameterObject::TEXT:{
entry = new ParameterText(entries[parameterName], descriptionShow);
break;
}
case ParameterObject::NUMBER:{
entry = new ParameterSpinBox(entries[parameterName], descriptionShow);
break;
}
case ParameterObject::VECTOR:{
entry = new ParameterVector(entries[parameterName], descriptionShow);
break;
}
case ParameterObject::UNDEFINED:{
break;
}
}
if (entries[parameterName]->target != ParameterObject::UNDEFINED) {
connect(entry, SIGNAL(changed()), this, SLOT(onValueChanged()));
addEntry(entry);
if (entries[parameterName]->focus){
entryToFocus = entry;
anyfocused = true;
}
}
}
void ParameterWidget::applyParameterSet(std::string setName)
{
boost::optional<pt::ptree &> set = getParameterSet(setName);
if (!set.is_initialized()) {
return;
}
for (pt::ptree::value_type &v : set.get()) {
entry_map_t::iterator entry = entries.find(v.first);
if (entry != entries.end()) {
if (entry->second->dvt == Value::STRING) {
entry->second->value=ValuePtr(v.second.data());
} else if (entry->second->dvt == Value::BOOL) {
entry->second->value = ValuePtr(v.second.get_value<bool>());
} else {
shared_ptr<Expression> params = CommentParser::parser(v.second.data().c_str());
if (!params) continue;
ModuleContext ctx;
ValuePtr newValue = params->evaluate(&ctx);
if (entry->second->dvt == newValue->type()) {
entry->second->value = newValue;
}
}
}
}
}
void ParameterWidget::updateParameterSet(std::string setName)
{
if (setName == "") {
QInputDialog *setDialog = new QInputDialog();
bool ok = true;
const QString result = setDialog->getText(this,
"Create new set of parameter", "Enter name of the parameter set",
QLineEdit::Normal, "", &ok);
if (ok) {
setName = result.trimmed().toStdString();
}
}
if (!setName.empty()) {
pt::ptree iroot;
for (entry_map_t::iterator it = entries.begin(); it != entries.end(); it++) {
iroot.put(it->first,it->second->value->toString());
}
addParameterSet(setName, iroot);
const QString s(QString::fromStdString(setName));
if (this->comboBox->findText(s) == -1) {
this->comboBox->addItem(s, QVariant(s));
this->comboBox->setCurrentIndex(this->comboBox->findText(s));
}
writeParameterSet(this->jsonFile);
}
}

View file

@ -0,0 +1,77 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2014 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#pragma once
#include <QTimer>
#include "parameterextractor.h"
#include "ui_ParameterWidget.h"
#include "groupwidget.h"
#include "parameterset.h"
class ParameterWidget : public QWidget, public Ui::ParameterWidget, public ParameterExtractor, public ParameterSet
{
Q_OBJECT
private:
typedef std::map<std::string,groupInst > group_map;
group_map groupMap;
QTimer autoPreviewTimer;
bool descriptionShow;
QVBoxLayout * anyLayout;
std::string jsonFile;
bool anyfocused;
ParameterVirtualWidget *entryToFocus;
public:
ParameterWidget(QWidget *parent = 0);
virtual ~ParameterWidget();
void readFile(QString scadFile);
void writeFile(QString scadFile);
protected slots:
void onValueChanged();
void onPreviewTimerElapsed();
void onDescriptionShow();
void onSetChanged(int idx);
void onSetAdd();
void onSetDelete();
void resetParameter();
signals:
void previewRequested();
protected:
void connectWidget();
void begin();
void addEntry(class ParameterVirtualWidget *entry);
void end();
void clear();
void AddParameterWidget(std::string parameterName);
void setComboBoxForSet();
void applyParameterSet(std::string setName);
void updateParameterSet(std::string setName);
};

View file

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ParameterWidget</class>
<widget class="QWidget" name="ParameterWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>486</width>
<height>590</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="7" column="0">
<widget class="QComboBox" name="comboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="addButton">
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item row="11" column="0" colspan="4">
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>472</width>
<height>496</height>
</rect>
</property>
<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>
</layout>
</widget>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Preset:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBoxAutoPreview">
<property name="text">
<string>Automatic Preview</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QPushButton" name="deleteButton">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBoxDetailedDescription">
<property name="text">
<string>Show Details</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="reset">
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,77 @@
#include "groupwidget.h"
#include <QPropertyAnimation>
GroupWidget::GroupWidget(bool &show, const QString & title, const int animationDuration, QWidget *parent) : QWidget(parent), animationDuration(animationDuration)
{
toggleButton.setStyleSheet("QToolButton { border: none; }");
toggleButton.setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
toggleButton.setText(title);
toggleButton.setCheckable(true);
headerLine.setFrameShape(QFrame::HLine);
headerLine.setFrameShadow(QFrame::Sunken);
headerLine.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
contentArea.setStyleSheet("QScrollArea { background-color: white; border: none; }");
contentArea.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
// start out collapsed
contentArea.setMaximumHeight(0);
contentArea.setMinimumHeight(0);
// let the entire widget grow and shrink with its content
toggleAnimation.addAnimation(new QPropertyAnimation(this, "minimumHeight"));
toggleAnimation.addAnimation(new QPropertyAnimation(this, "maximumHeight"));
toggleAnimation.addAnimation(new QPropertyAnimation(&contentArea, "maximumHeight"));
this->show = &show;
toggleButton.setChecked(show);
// don't waste space
mainLayout.setVerticalSpacing(0);
mainLayout.setContentsMargins(0, 0, 0, 0);
int row = 0;
mainLayout.addWidget(&toggleButton, row, 0, 1, 1, Qt::AlignLeft);
mainLayout.addWidget(&headerLine, row++, 2, 1, 1);
mainLayout.addWidget(&contentArea, row, 0, 1, 3);
setLayout(&mainLayout);
QObject::connect(&toggleButton, SIGNAL(toggled(bool)),this, SLOT(onclicked(bool)));
}
void GroupWidget::onclicked(const bool checked)
{
toggleButton.setArrowType(toggleButton.isChecked() ? Qt::DownArrow : Qt::RightArrow);
toggleAnimation.setDirection(toggleButton.isChecked() ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
toggleAnimation.start();
if (toggleButton.isChecked()) {
*(this->show) = true;
} else {
*(this->show) = false;
}
this->animationDuration = 300;
}
void GroupWidget::setContentLayout(QLayout & contentLayout)
{
delete contentArea.layout();
contentArea.setLayout(&contentLayout);
const int collapsedHeight = sizeHint().height() - contentArea.maximumHeight();
int contentHeight = contentLayout.sizeHint().height();
for (int i = 0; i < toggleAnimation.animationCount() - 1; ++i) {
QPropertyAnimation * GroupWidgetAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(i));
GroupWidgetAnimation->setDuration(animationDuration);
GroupWidgetAnimation->setStartValue(collapsedHeight);
GroupWidgetAnimation->setEndValue(collapsedHeight + contentHeight);
}
QPropertyAnimation * contentAnimation = static_cast<QPropertyAnimation *>(toggleAnimation.animationAt(toggleAnimation.animationCount() - 1));
contentAnimation->setDuration(animationDuration);
contentAnimation->setStartValue(0);
contentAnimation->setEndValue(contentHeight);
if (*(this->show)) {
toggleButton.setArrowType(Qt::DownArrow);
toggleAnimation.start();
} else {
toggleButton.setArrowType(Qt::RightArrow);
}
}

View file

@ -0,0 +1,33 @@
#pragma once
#include <QFrame>
#include <QGridLayout>
#include <QParallelAnimationGroup>
#include <QScrollArea>
#include <QToolButton>
#include <QWidget>
#include <vector>
struct groupInst {
std::vector<std::string> parameterVector;
bool show;
};
class GroupWidget : public QWidget {
Q_OBJECT
private:
QGridLayout mainLayout;
QToolButton toggleButton;
QFrame headerLine;
QParallelAnimationGroup toggleAnimation;
QScrollArea contentArea;
int animationDuration;
bool *show;
public:
groupInst groupinst;
explicit GroupWidget(bool &show,const QString & title = "", const int animationDuration = 0, QWidget *parent = 0);
void setContentLayout(QLayout & contentLayout);
private slots:
void onclicked(bool);
};

View file

@ -0,0 +1,33 @@
#include "parametercheckbox.h"
ParameterCheckBox::ParameterCheckBox(ParameterObject *parameterobject, bool showDescription)
{
object = parameterobject;
setName(QString::fromStdString(object->name));
setValue();
connect(checkBox, SIGNAL(clicked()), this, SLOT(onChanged()));
if (showDescription == true) {
setDescription(object->description);
}
else {
checkBox->setToolTip(object->description);
}
}
void ParameterCheckBox::onChanged()
{
object->focus = true;
object->value = ValuePtr(checkBox->isChecked());
emit changed();
}
void ParameterCheckBox::setParameterFocus()
{
this->checkBox->setFocus();
object->focus = false;
}
void ParameterCheckBox::setValue() {
this->stackedWidget->setCurrentWidget(this->pageCheckBox);
this->checkBox->setChecked(object->value->toBool());
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "parametervirtualwidget.h"
class ParameterCheckBox : public ParameterVirtualWidget
{
Q_OBJECT
public:
ParameterCheckBox(ParameterObject *parameterobject,bool);
void setValue();
void setParameterFocus();
protected slots:
void onChanged();
};

View file

@ -0,0 +1,57 @@
#include "parametercombobox.h"
ParameterComboBox::ParameterComboBox(ParameterObject *parameterobject, bool showDescription)
{
object = parameterobject;
setName(QString::fromStdString(object->name));
setValue();
connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onChanged(int)));
if (showDescription == true) {
setDescription(object->description);
}
else{
comboBox->setToolTip(object->description);
}
}
void ParameterComboBox::onChanged(int idx)
{
if (object->dvt == Value::STRING) {
const std::string v = comboBox->itemData(idx).toString().toStdString();
object->value = ValuePtr(v);
} else {
const double v = comboBox->itemData(idx).toDouble();
object->value = ValuePtr(v);
}
object->focus = true;
emit changed();
}
void ParameterComboBox::setParameterFocus()
{
this->comboBox->setFocus();
object->focus = false;
}
void ParameterComboBox::setValue()
{
this->stackedWidget->setCurrentWidget(this->pageComboBox);
comboBox->clear();
const Value::VectorType& vec = object->values->toVector();
for (Value::VectorType::const_iterator it = vec.begin(); it != vec.end(); it++) {
if ((*it)->toVector().size() > 1) {
comboBox->addItem(QString::fromStdString((*it)->toVector()[1]->toString()),
QVariant(QString::fromStdString((*it)->toVector()[0]->toString())));
}
else {
comboBox->addItem(QString::fromStdString((*it)->toString()),
QVariant(QString::fromStdString((*it)->toString())));
}
}
QString defaultText = QString::fromStdString(object->value->toString());
int idx = comboBox->findData(QVariant(defaultText));
if (idx >= 0) {
comboBox->setCurrentIndex(idx);
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "parametervirtualwidget.h"
class ParameterComboBox : public ParameterVirtualWidget
{
Q_OBJECT
public:
ParameterComboBox(ParameterObject *parameterobject,bool showDescription);
void setValue();
void setParameterFocus();
public slots:
void onChanged(int idx);
};

View file

@ -0,0 +1,63 @@
#include "parameterextractor.h"
#include "modcontext.h"
ParameterExtractor::ParameterExtractor()
{
resetPara = false;
}
ParameterExtractor::~ParameterExtractor()
{
}
void ParameterExtractor::applyParameters(FileModule *fileModule)
{
if (!fileModule) return;
for (auto &assignment : fileModule->scope.assignments) {
auto entry = entries.find(assignment.name);
if (entry != entries.end()) {
entry->second->applyParameter(assignment);
entry->second->set = false;
}
}
}
void ParameterExtractor::setParameters(const FileModule* module)
{
if (!module) return;
ModuleContext ctx;
for (auto &assignment : module->scope.assignments) {
const Annotation *param = assignment.annotation("Parameter");
if (!param) continue;
const ValuePtr defaultValue = assignment.expr->evaluate(&ctx);
if (defaultValue->type() == Value::UNDEFINED) continue;
ParameterObject *entryObject = new ParameterObject();
entryObject->setAssignment(&ctx, &assignment, defaultValue);
//check whether object exist or not previously
if (entries.find(assignment.name) == entries.end() || resetPara) {
//if object doen't exist
//or we have reset Parameters then add new entry
entries[assignment.name] = entryObject;
} else {
//if entry object is already exist we check if its modified
//or not
if (*entryObject == *entries[assignment.name]) {
//if entry is not modified then we don't add new entry
entryObject = entries[assignment.name];
} else {
//if entry is modified then we add new entry
entries[assignment.name] = entryObject;
}
}
entryObject->set = true;
}
connectWidget();
this->resetPara = false;
}

View file

@ -0,0 +1,24 @@
#pragma once
#include "FileModule.h"
#include "parametervirtualwidget.h"
class ParameterExtractor
{
protected:
typedef std::map<std::string, class ParameterObject *> entry_map_t;
entry_map_t entries;
public:
ParameterExtractor();
virtual ~ParameterExtractor();
void setParameters(const FileModule* module);
void applyParameters(FileModule *fileModule);
protected:
virtual void begin() = 0;
virtual void addEntry(ParameterVirtualWidget *entry) = 0;
virtual void end() = 0;
virtual void connectWidget() = 0;
bool resetPara;
};

View file

@ -0,0 +1,88 @@
#include "parameterobject.h"
#include "module.h"
#include "modcontext.h"
#include "annotation.h"
ParameterObject::ParameterObject() : focus(false)
{
}
void ParameterObject::applyParameter(Assignment &assignment)
{
ModuleContext ctx;
const ValuePtr defaultValue = assignment.expr->evaluate(&ctx);
if (defaultValue->type() == dvt) {
assignment.expr = shared_ptr<Expression>(new Literal(value));
}
}
int ParameterObject::setValue(const class ValuePtr defaultValue, const class ValuePtr values)
{
this->values = values;
this->value = defaultValue;
this->defaultValue = defaultValue;
this->vt = values->type();
this->dvt = defaultValue->type();
if (dvt == Value::BOOL) {
target = CHECKBOX;
} else if ((dvt == Value::VECTOR) && (defaultValue->toVector().size() <= 4)) {
checkVectorWidget();
} else if ((vt == Value::VECTOR) && ((dvt == Value::NUMBER) || (dvt == Value::STRING))) {
target = COMBOBOX;
} else if ((vt == Value::RANGE) && (dvt == Value::NUMBER)) {
target = SLIDER;
} else if (dvt == Value::NUMBER) {
target = NUMBER;
} else {
target = TEXT;
}
return target;
}
void ParameterObject::setAssignment(Context *ctx, const Assignment *assignment, const ValuePtr defaultValue)
{
name = assignment->name;
const Annotation *param = assignment->annotation("Parameter");
const ValuePtr values = param->evaluate(ctx);
setValue(defaultValue, values);
const Annotation *desc = assignment->annotation("Description");
if (desc) {
const ValuePtr v = desc->evaluate(ctx);
if (v->type() == Value::STRING) {
description=QString::fromStdString(v->toString());
}
}
const Annotation *group = assignment->annotation("Group");
if (group) {
const ValuePtr v = group->evaluate(ctx);
if (v->type() == Value::STRING) {
groupName=v->toString();
}
} else {
groupName="Parameters";
}
}
bool ParameterObject::operator == (const ParameterObject &second)
{
return (this->defaultValue == second.defaultValue && this->values==second.values &&
this->description == second.description && this->groupName == second.groupName);
}
void ParameterObject::checkVectorWidget()
{
Value::VectorType vec = defaultValue->toVector();
for (unsigned int i = 0;i < vec.size();i++) {
if (vec[i]->type() != Value::NUMBER) {
target = TEXT;
return;
}
}
target = VECTOR;
}

View file

@ -0,0 +1,37 @@
#pragma once
#include "value.h"
#include "Assignment.h"
#include "expression.h"
#include <QString>
class ParameterObject
{
public:
typedef enum { UNDEFINED, COMBOBOX, SLIDER, CHECKBOX, TEXT, NUMBER, VECTOR } parameter_type_t;
ValuePtr value;
ValuePtr values;
ValuePtr defaultValue;
Value::ValueType dvt;
parameter_type_t target;
QString description;
std::string name;
bool set;
std::string groupName;
bool focus;
private:
Value::ValueType vt;
void checkVectorWidget();
public:
ParameterObject();
void setAssignment(Context *context, const Assignment *assignment, const ValuePtr defaultValue);
void applyParameter(Assignment &assignment);
bool operator==(const ParameterObject &second);
protected:
int setValue(const ValuePtr defaultValue, const ValuePtr values);
};

View file

@ -0,0 +1,117 @@
#include "parameterset.h"
#include "comment.h"
#include "modcontext.h"
#include "expression.h"
#include "printutils.h"
#include <fstream>
#include <boost/property_tree/json_parser.hpp>
std::string ParameterSet::parameterSetsKey("parameterSets");
std::string ParameterSet::fileFormatVersionKey("fileFormatVersion");
std::string ParameterSet::fileFormatVersionValue("1");
boost::optional<pt::ptree &> ParameterSet::parameterSets()
{
return root.get_child_optional(ParameterSet::parameterSetsKey);
}
std::vector<std::string> ParameterSet::getParameterNames()
{
std::vector<std::string> names;
boost::optional<pt::ptree &> sets = parameterSets();
if (sets.is_initialized()) {
for (const auto &v : sets.get()) {
names.push_back(v.first);
}
}
return names;
}
boost::optional<pt::ptree &> ParameterSet::getParameterSet(const std::string &setName)
{
boost::optional<pt::ptree &> sets = root.get_child_optional(ParameterSet::parameterSetsKey);
if (!sets.is_initialized()) {
return sets;
}
boost::optional<pt::ptree &> set = sets.get().get_child_optional(setName);
return set;
}
void ParameterSet::addParameterSet(const std::string setName, const pt::ptree & set)
{
boost::optional<pt::ptree &> sets = parameterSets();
if (sets.is_initialized()) {
sets.get().erase(setName);
}
root.add_child(ParameterSet::parameterSetsKey + "." + setName, set);
}
/*!
Returns true if the file is writable
*/
bool ParameterSet::readParameterSet(const std::string &filename)
{
try {
pt::read_json(filename, this->root);
//check whether file is read-only
std::fstream file;
file.open(filename, std::ios::app);
if (file.is_open()) {
file.close();
return true;
}
}
catch (const pt::json_parser_error &e) {
PRINTB("ERROR: Cannot open Parameter Set '%s': %s", filename % e.what());
}
return false;
}
void ParameterSet::writeParameterSet(const std::string &filename)
{
// Always force default version for now
root.put<std::string>(fileFormatVersionKey, fileFormatVersionValue);
try {
pt::write_json(filename, this->root);
}
catch (const pt::json_parser_error &e) {
PRINTB("ERROR: Cannot write Parameter Set '%s': %s", filename % e.what());
}
}
void ParameterSet::applyParameterSet(FileModule *fileModule, const std::string &setName)
{
if (fileModule == NULL || this->root.empty()) return;
try {
ModuleContext ctx;
std::string path = parameterSetsKey + "." + setName;
for (auto &assignment : fileModule->scope.assignments) {
for (auto &v : root.get_child(path)) {
if (v.first == assignment.name) {
const ValuePtr defaultValue = assignment.expr->evaluate(&ctx);
if (defaultValue->type() == Value::STRING) {
assignment.expr = shared_ptr<Expression>(new Literal(ValuePtr(v.second.data())));
}
else if (defaultValue->type() == Value::BOOL) {
assignment.expr = shared_ptr<Expression>(new Literal(ValuePtr(v.second.get_value<bool>())));
} else {
shared_ptr<Expression> params = CommentParser::parser(v.second.data().c_str());
if (!params) continue;
ModuleContext ctx;
if (defaultValue->type() == params->evaluate(&ctx)->type()) {
assignment.expr = params;
}
}
}
}
}
}
catch (std::exception const& e) {
PRINTB("ERROR: Cannot apply parameter Set: %s", e.what());
}
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <vector>
#include <boost/property_tree/ptree.hpp>
namespace pt = boost::property_tree;
class ParameterSet
{
public:
static std::string parameterSetsKey;
static std::string fileFormatVersionKey;
static std::string fileFormatVersionValue;
protected:
pt::ptree root;
private:
boost::optional<pt::ptree &> parameterSets();
public:
ParameterSet() {}
~ParameterSet() {}
std::vector<std::string> getParameterNames();
boost::optional<pt::ptree &> getParameterSet(const std::string &setName);
void addParameterSet(const std::string setName, const pt::ptree & set);
bool readParameterSet(const std::string &filename);
void writeParameterSet(const std::string &filename);
void applyParameterSet(class FileModule *fileModule, const std::string &setName);
};

View file

@ -0,0 +1,63 @@
#include "parameterslider.h"
ParameterSlider::ParameterSlider(ParameterObject *parameterobject, bool showDescription)
{
this->pressed = true;
object = parameterobject;
setName(QString::fromStdString(object->name));
setValue();
connect(slider, SIGNAL(sliderPressed()), this, SLOT(onPressed()));
connect(slider, SIGNAL(sliderReleased()), this, SLOT(onReleased()));
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onChanged(int)));
if (showDescription == true) {
setDescription(object->description);
}
else {
slider->setToolTip(object->description);
}
}
void ParameterSlider::onChanged(int)
{
double v = slider->value()*step;
this->labelSliderValue->setText(QString::number(v, 'f', decimalPrecision));
if (this->pressed) {
object->focus = true;
object->value = ValuePtr(v);
emit changed();
}
}
void ParameterSlider::setParameterFocus()
{
slider->setFocus();
object->focus = false;
}
void ParameterSlider::onPressed()
{
this->pressed = false;
}
void ParameterSlider::onReleased(){
this->pressed = true;
onChanged(0);
}
void ParameterSlider::setValue()
{
if (object->values->toRange().step_value() > 0) {
setPrecision(object->values->toRange().step_value());
step = object->values->toRange().step_value();
} else {
decimalPrecision = 1;
step = 1;
}
int min = object->values->toRange().begin_value()/step;
int max=object->values->toRange().end_value()/step;
int current=object->value->toDouble()/step;
this->stackedWidget->setCurrentWidget(this->pageSlider);
this->slider->setRange(min,max);
this->slider->setValue(current);
this->labelSliderValue->setText(QString::number(current*step, 'f',decimalPrecision));
}

View file

@ -0,0 +1,20 @@
#pragma once
#include "parametervirtualwidget.h"
class ParameterSlider : public ParameterVirtualWidget
{
Q_OBJECT
public:
ParameterSlider(ParameterObject *parameterobject, bool showDescription);
void setValue();
void setParameterFocus();
private:
double step;
bool pressed;
protected slots:
void onChanged(int);
void onReleased();
void onPressed();
};

View file

@ -0,0 +1,48 @@
#include "parameterspinbox.h"
ParameterSpinBox::ParameterSpinBox(ParameterObject *parameterobject, bool showDescription)
{
object = parameterobject;
setName(QString::fromStdString(object->name));
setValue();
connect(doubleSpinBox1, SIGNAL(valueChanged(double)), this, SLOT(onChanged(double)));
if (showDescription == true) {
setDescription(object->description);
}
else {
doubleSpinBox1->setToolTip(object->description);
}
}
void ParameterSpinBox::onChanged(double)
{
object->focus = true;
object->value = ValuePtr(doubleSpinBox1->value());
emit changed();
}
void ParameterSpinBox::setParameterFocus()
{
this->doubleSpinBox1->setFocus();
object->focus = false;
}
void ParameterSpinBox::setValue()
{
if (object->values->toDouble() > 0) {
setPrecision(object->values->toDouble());
this->doubleSpinBox1->setSingleStep(object->values->toDouble());
}
else {
setPrecision(object->defaultValue->toDouble());
this->doubleSpinBox1->setSingleStep(1/pow(10,decimalPrecision));
}
this->doubleSpinBox1->setDecimals(decimalPrecision);
this->stackedWidget->setCurrentWidget(this->pageVector);
this->doubleSpinBox1->setRange(object->value->toDouble()-1000, object->value->toDouble()+1000);
this->doubleSpinBox1->setValue(object->value->toDouble());
this->doubleSpinBox2->hide();
this->doubleSpinBox3->hide();
this->doubleSpinBox4->hide();
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "parametervirtualwidget.h"
class ParameterSpinBox :public ParameterVirtualWidget
{
Q_OBJECT
public:
ParameterSpinBox(ParameterObject *parameterobject, bool showDescription);
void setValue();
void setParameterFocus();
protected slots:
void onChanged(double);
};

View file

@ -0,0 +1,50 @@
#include "parametertext.h"
#include "modcontext.h"
#include "comment.h"
ParameterText::ParameterText(ParameterObject *parameterobject, bool showDescription)
{
object = parameterobject;
setName(QString::fromStdString(object->name));
setValue();
connect(lineEdit, SIGNAL(textChanged(QString)), this, SLOT(onChanged(QString)));
if (showDescription == true){
setDescription(object->description);
}
else{
lineEdit->setToolTip(object->description);
}
}
void ParameterText::onChanged(QString)
{
if (object->dvt == Value::STRING) {
object->value = ValuePtr(lineEdit->text().toStdString());
}
else {
ModuleContext ctx;
shared_ptr<Expression> params = CommentParser::parser(lineEdit->text().toStdString().c_str());
if (!params) return;
ValuePtr newValue = params->evaluate(&ctx);
if (object->dvt == newValue->type()) {
object->value = newValue;
}
}
object->focus = true;
emit changed();
}
void ParameterText::setParameterFocus()
{
this->lineEdit->setFocus();
object->focus = false;
}
void ParameterText::setValue()
{
this->stackedWidget->setCurrentWidget(this->pageText);
this->lineEdit->setText(QString::fromStdString(object->value->toString()));
if (object->values->toDouble() > 0) {
this->lineEdit->setMaxLength(object->values->toDouble());
}
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "parametervirtualwidget.h"
class ParameterText : public ParameterVirtualWidget
{
Q_OBJECT
public:
ParameterText(ParameterObject *parameterobject,bool showDescription);
void setValue();
void setParameterFocus();
protected slots:
void onChanged(QString);
};

View file

@ -0,0 +1,89 @@
#include "parametervector.h"
ParameterVector::ParameterVector(ParameterObject *parameterobject, bool showDescription)
{
object = parameterobject;
setName(QString::fromStdString(object->name));
setValue();
connect(doubleSpinBox1,SIGNAL(valueChanged(double)),this,SLOT(onChanged(double)));
connect(doubleSpinBox2,SIGNAL(valueChanged(double)),this,SLOT(onChanged(double)));
connect(doubleSpinBox3,SIGNAL(valueChanged(double)),this,SLOT(onChanged(double)));
connect(doubleSpinBox4,SIGNAL(valueChanged(double)),this,SLOT(onChanged(double)));
if (showDescription == true) {
setDescription(object->description);
}
else {
frame->setToolTip(object->description);
}
}
void ParameterVector::onChanged(double)
{
object->focus = true;
if (object->target == 5) {
object->value = ValuePtr(doubleSpinBox1->value());
} else {
Value::VectorType vt;
vt.push_back(this->doubleSpinBox1->value());
if (!this->doubleSpinBox2->isReadOnly()) {
vt.push_back(this->doubleSpinBox2->value());
}
if (!this->doubleSpinBox3->isReadOnly()) {
vt.push_back(this->doubleSpinBox3->value());
}
if (!this->doubleSpinBox4->isReadOnly()) {
vt.push_back(this->doubleSpinBox4->value());
}
object->value = ValuePtr(vt);
}
emit changed();
}
void ParameterVector::setParameterFocus()
{
this->doubleSpinBox1->setFocus();
object->focus = false;
}
void ParameterVector::setValue()
{
this->stackedWidget->setCurrentWidget(this->pageVector);
Value::VectorType vec = object->value->toVector();
if (vec.size() < 4) {
this->doubleSpinBox4->hide();
this->doubleSpinBox4->setReadOnly(true);
}
if (vec.size() < 3) {
this->doubleSpinBox3->hide();
this->doubleSpinBox3->setReadOnly(true);
}
if (vec.size() < 2) {
this->doubleSpinBox2->hide();
this->doubleSpinBox2->setReadOnly(true);
}
setPrecision(vec.at(0)->toDouble());
this->doubleSpinBox1->setDecimals(decimalPrecision);
this->doubleSpinBox1->setRange(vec.at(0)->toDouble()-1000,vec.at(0)->toDouble()+1000);
this->doubleSpinBox1->setValue(vec.at(0)->toDouble());
if (vec.size() > 1) {
setPrecision(vec.at(1)->toDouble());
this->doubleSpinBox2->setDecimals(decimalPrecision);
this->doubleSpinBox2->setRange(vec.at(1)->toDouble()-1000,vec.at(1)->toDouble()+1000);
this->doubleSpinBox2->setValue(vec.at(1)->toDouble());
this->doubleSpinBox2->setReadOnly(false);
}
if (vec.size() > 2) {
setPrecision(vec.at(2)->toDouble());
this->doubleSpinBox3->setDecimals(decimalPrecision);
this->doubleSpinBox3->setRange(vec.at(2)->toDouble()-1000,vec.at(2)->toDouble()+1000);
this->doubleSpinBox3->setValue(vec.at(2)->toDouble());
this->doubleSpinBox3->setReadOnly(false);
}
if (vec.size() > 3) {
setPrecision(vec.at(3)->toDouble());
this->doubleSpinBox4->setDecimals(decimalPrecision);
this->doubleSpinBox4->setRange(vec.at(3)->toDouble()-1000,vec.at(3)->toDouble()+1000);
this->doubleSpinBox4->setValue(vec.at(3)->toDouble());
this->doubleSpinBox4->setReadOnly(false);
}
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "parametervirtualwidget.h"
class ParameterVector : public ParameterVirtualWidget
{
Q_OBJECT
public:
ParameterVector(ParameterObject *parameterobject, bool showDescription);
void setValue();
void setParameterFocus();
protected slots:
void onChanged(double);
};

View file

@ -0,0 +1,37 @@
#include "parametervirtualwidget.h"
ParameterVirtualWidget::ParameterVirtualWidget(QWidget *parent) : QWidget(parent)
{
setupUi(this);
}
ParameterVirtualWidget::~ParameterVirtualWidget(){
}
void ParameterVirtualWidget::setName(QString name) {
this->labelDescription->hide();
name.replace(QRegExp("([_]+)"), " ");
this->labelParameter->setText(name);
}
void ParameterVirtualWidget::setPrecision(double number){
decimalPrecision = 0;
long double diff, rn; //rn stands for real number
unsigned long long intNumber, multi = 1;
number = abs(number);
while(1) {
rn = (number * multi);
intNumber = rn; //the fractional part will be truncated here
diff = rn - intNumber;
if (diff <= 0.0 || decimalPrecision > 6) {
break;
}
multi = multi * 10;
decimalPrecision++;
}
}

View file

@ -0,0 +1,34 @@
#pragma once
#include "value.h"
#include "qtgettext.h"
#include "ui_ParameterEntryWidget.h"
#include "parameterobject.h"
class ParameterVirtualWidget : public QWidget, public Ui::ParameterEntryWidget
{
Q_OBJECT
protected:
ParameterObject *object;
public:
ParameterVirtualWidget(QWidget *parent = 0);
virtual ~ParameterVirtualWidget();
virtual void setParameterFocus() = 0;
signals:
void changed();
protected:
int decimalPrecision;
virtual void setPrecision(double number);
virtual void setValue() = 0;
void setName(QString name);
void setDescription(const QString& description) {
if(!description.isEmpty()){
this->labelDescription->show();
this->labelDescription->setText(description);
}
}
};

View file

@ -0,0 +1,73 @@
a = true;//parameter
//description
b = false;//parameter
//description
c = undef;//parameter
//description
d = a;//parameter
//description
e = $fn;//parameter
//description
f1 = [1,,];//parameter
//description
f2 = [1,2,3];//parameter
//description
g = f2.x + f2.y + f2.z;//parameter
//description
h1 = [2:5];//parameter
//description
h2 = [1:2:10];//parameter
//description
i = h2.begin - h2.step - h2.end;//parameter
//description
j = "test";//parameter
//description
k = 1.23e-2;//parameter
//description
l = a * b;//parameter
//description
m = a / b;//parameter
//description
n = a % b;//parameter
//description
o = c < d;//parameter
//description
p = c <= d;//parameter
//description
q = c == d;//parameter
//description
r = c != d;//parameter
//description
s = c >= d;//parameter
//description
t = c > d;//parameter
//description
u = e && g;//parameter
//description
v = e || g;//parameter
//description
w = +i;//parameter
//description
x = -i;//parameter
//description
y = !i;//parameter
//description
z = (j);//parameter
//description
aa = k ? l : m;//parameter
//description
bb = n[o];//parameter
//description
cc = let(a=1) a;//parameter
//description
dd = [for (a=[0,1]) let(b=a) if (true) b];//parameter
//description
ee = ["abc", for (a=[0,1]) let(b=a) if (true) b, true, for(c=[1:3]) c, 3];//parameter
//description
ff = [for (a=[0,1]) if (a == 0) "A" else ( "B" )];//parameter
//description
gg = [each [ "a", 0, false ]];//parameter
//description
hh = [for (a = [0 : 3]) if (a < 2) ( if (a < 1) ["+", a] ) else ["-", a] ];//parameter
//description
ii = [for (a=0,b=1;a < 5;a=a+1,b=b+2) [a,b*b] ];

View file

@ -0,0 +1,65 @@
a = abs();//parameter
//description
b = sign();//parameter
//description
c = rands();//parameter
//description
d = min();//parameter
//description
e = max();//parameter
//description
f = sin();//parameter
//description
g = cos();//parameter
//description
h = asin();//parameter
//description
i = acos();//parameter
//description
j = tan();//parameter
//description
k = atan();//parameter
//description
l = atan2();//parameter
//description
m = round();//parameter
//description
n = ceil();//parameter
//description
o = floor();//parameter
//description
p = pow();//parameter
//description
q = sqrt();//parameter
//description
r = exp();//parameter
//description
ra = len();//parameter
//description
s = log();//parameter
//description
t = ln();//parameter
//description
u = str();//parameter
//description
ua = chr();//parameter
//description
ub = concat();//parameter
//description
v = lookup();//parameter
//description
va = search();//parameter
//description
y = version();//parameter
//description
z = version_num();//parameter
//description
za = norm();//parameter
//description
zb = cross();//parameter
//description
zc = parent_module();//parameter
//description
w = dxf_dim();//parameter
//description
x = dxf_cross();

View file

@ -0,0 +1,77 @@
minkowski();//parameter
//description
hull();//parameter
//description
resize();//parameter
//description
child();//parameter
//description
echo();//parameter
//description
assign();//parameter
//description
for();//parameter
//description
intersection_for();//parameter
//description
if(false) { cube(); } else { sphere(); }//parameter
//description
union();//parameter
//description
difference();//parameter
//description
intersection();//parameter
//description
dxf_linear_extrude();//parameter
//description
linear_extrude();//parameter
//description
dxf_rotate_extrude();//parameter
//description
rotate_extrude();//parameter
//description
import();//parameter
//description
import_stl();//parameter
//description
import_off();//parameter
//description
import_dxf();//parameter
//description
group();//parameter
//description
cube();//parameter
//description
sphere();//parameter
//description
cylinder();//parameter
//description
polyhedron();//parameter
//description
square();//parameter
//description
circle();//parameter
//description
polygon();//parameter
//description
projection();//parameter
//description
render();//parameter
//description
surface();//parameter
//description
scale();//parameter
//description
rotate();//parameter
//description
mirror();//parameter
//description
translate();//parameter
//description
multmatrix();//parameter
//description
color();//parameter
//description
offset();//parameter
//description
text();

View file

@ -0,0 +1,48 @@
//alone Description at Top
//normal description
x=50;
// normal starting width spaces description
x2=45;
// normal starting tab spaces description
x3=3;
// normal comment starting with space before //
x4=3;
// normal comment starting with tab before //
x5=3;
// double description
x5=3;
//
x6=12;
x7=12;
// comment
x8=12;
// description sandwiched between two assignments
x9=23;
x8=12;
// comment sandwiched between two assignments
x19=23;
x10=23;
x11=23;
x12=23;
// normal comment starting with tab before //
x13=3;
// double description
x13=7;
// double description // normal comment starting with tab before //
x14=3;

49
testdata/scad/customizer/group.scad vendored Normal file
View file

@ -0,0 +1,49 @@
// combo box for nunber
Numbers=2; // [0, 1, 2, 3]
// combo box for string
Strings="foo"; // [foo, bar, baz]
//labeled combo box for numbers
Labeled_values=10; // [10:L, 20:M, 30:L]
//labeled combo box for string
Labeled_value="S"; // [S:Small, M:Medium, L:Large]
/*[ Global ]*/
// slider widget for number
slider =34; // [10:100]
//step slider for number
stepSlider=2; //[0:5:100]
/* [Hidden] */
//description
Variable = true; //comment
/*[Global] */
// spinbox with step size 23
Spinbox = 5; //23
/* [Textbox] */
//Text box for vector with more than 4 elements
Vector=[12,34,44,43,23,23];//comment
// Text box for string
String="hello"; //comment
/* [Special vector] */
//Text box for vector with less than or equal to 4 elements
Vector2=[12,34,45,23]; //any thing
// Norma; text
String2="hello"; //comment with "
/* [group after " in previous comment ] */
//Text box for vector with less than or equal to 4 elements
Vector3=[12,34,45,23]; //any thing
echo(String);

62
testdata/scad/customizer/parameter.scad vendored Normal file
View file

@ -0,0 +1,62 @@
x=1;
x1=1; //12
x2=1; //12
x3=1; // 12
x4=1; // 12
x5=1; //[1:12]
x6=1; //[1:2:12]
x7=1; //[1:12
x8=1; //[1 12]
x9=1; //[1:12] //[12:34]
x10=1; //
x11=1; //
x12=1; //[12]
x13=10; // [10:Small, 20:Medium, 30:Large]
x13a=10; // [10:Small, 20: 34 Medium, 30:Large 12]
x14=10; //[10:100, 20:101, 30:102]
x15=10; //parameter
x16=10; //[0, 1, 2, 3]
x17="text"; // parameter
x18="text"; //[foo, bar, baz]
x19="text"; //[0:text, 1:foo, 2:bar, 3:hello]
x20="text"; //[foo:10, bar:10, baz:30]
x21="text"; //[foo:yes, bar:no, baz:mgiht]
x22=[12,34]; //[23,4]
x23=[12,34]; //[23,4,23,4,45]
x24=[12,34,2,3,41,23]; //[23,4,2,3,4,6]
x25=12; x26="text"; //[1:34]
x27=12; //end parameter
x28=-12;
x29=!1;
x30=["new","secon"];
x31=["new","second"]; //[new,second]
x32=["new","second"]; //["new",second]

View file

@ -0,0 +1,41 @@
{
"parameterSets":
{
"firstSet":
{
"Labeled_value": " \/*New *\/ ",
"Labeled_values": "100",
"Numbers": "1",
"Spinbox": "35",
"String": "hello",
"Strings": "foo",
"Variable": "false",
"Vector": "[2, 34, 45, 12, 3, 56]",
"Vector2": "[12,4, 45, 23]",
"slider": "38",
"stepSlider": "12",
"stringVector":"[hello, new, 12]"
},
"wrongSetValues":
{
"Labeled_value": "S new",
"Labeled_values": "wrong type",
"Numbers": "2",
"Spinbox": "5",
"String": "1234",
"Strings": "fo",
"Variable": "true",
"Vector": "12, 34, 44, 43, 2, 23",
"Vector2": "[12, 34, 45, 23]",
"slider": "34",
"stepSlider": "2"
},
"thirdSet":
{
"Labeled_value":"S new",
"non existing":"value",
"nonparameter" : "second",
"stringVector":"[ \" hello\",\" new \"]"
}
}
}

View file

@ -0,0 +1,46 @@
/* [Drop down box:] */
// combo box for nunber
Numbers=2; // [0, 1, 2, 3]
// combo box for string
Strings="foo";
//labeled combo box for numbers
Labeled_values=10; // [10:L, 20:M, 30:L]
//labeled combo box for string
Labeled_value="S"; // [S:Small, M:Medium, L:Large]
/*[ Slider ]*/
// slider widget for number
slider =34; // [10:100]
//step slider for number
stepSlider=2; //[0:5:100]
/* [Checkbox] */
//description
Variable = true; //comment
/*[Spinbox] */
// spinbox with step size 23
Spinbox = 5; //23
/* [Textbox] */
//Text box for vector with more than 4 elements
Vector=[12,34,44,43,23,23];//comment
// Text box for string
String="hello"; //comment
/* [Special vector] */
//Text box for vector with less than or equal to 4 elements
Vector2=[12,34,45,23]; //any thing
nonparameter="new";
stringVector=["1","2"];
echo(String);

View file

@ -747,7 +747,9 @@ set(CORE_SOURCES
../src/libsvg/svgpage.cc
../src/libsvg/transformation.cc
../src/libsvg/util.cc
../src/clipper-utils.cc
../src/clipper-utils.cc
../src/assignment.cc
../src/annotation.cc
../src/polyclipping/clipper.cpp
../src/${PLATFORMUTILS_SOURCE}
${FLEX_OpenSCADlexer_OUTPUTS}
@ -1664,6 +1666,23 @@ add_failing_test(offfailedtest EXE ${PYTHON_EXECUTABLE} SCRIPT ${CMAKE_SOURCE_DI
# Add experimental tests
#
#
# Customizer tests
#
add_cmdline_test(customizertest EXE ${OPENSCAD_BINPATH} ARGS --enable=customizer -o SUFFIX ast FILES
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/description.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/parameter.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/allmodulescomment.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/allfunctionscomment.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/allexpressionscomment.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/group.scad
)
add_cmdline_test(customizertest-first EXE ${OPENSCAD_BINPATH} ARGS --enable=customizer -p ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.json -P firstSet -o SUFFIX ast FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.scad)
add_cmdline_test(customizertest-wrong EXE ${OPENSCAD_BINPATH} ARGS --enable=customizer -p ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.json -P wrongSetValues -o SUFFIX ast FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.scad)
add_cmdline_test(customizertest-incomplete EXE ${OPENSCAD_BINPATH} ARGS --enable=customizer -p ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.json -P thirdSet -o SUFFIX ast FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.scad)
add_cmdline_test(customizertest-imgset EXE ${OPENSCAD_BINPATH} ARGS --enable=customizer -p ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.json -P imagine -o SUFFIX ast FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/customizer/setofparameter.scad)
# Tests using the actual OpenSCAD binary
# non-ASCII filenames

View file

@ -0,0 +1,52 @@
//Group("Drop down box:")
//Description("combo box for nunber")
//Parameter([0, 1, 2, 3])
Numbers = 1;
//Group("Drop down box:")
//Description("combo box for string")
//Parameter("")
Strings = "foo";
//Group("Drop down box:")
//Description("labeled combo box for numbers")
//Parameter([[10, "L"], [20, "M"], [30, "L"]])
Labeled_values = 100;
//Group("Drop down box:")
//Description("labeled combo box for string")
//Parameter([["S", "Small"], ["M", "Medium"], ["L", "Large"]])
Labeled_value = " /*New */ ";
//Group(" Slider ")
//Description("slider widget for number")
//Parameter([10 : 100])
slider = 38;
//Group(" Slider ")
//Description("step slider for number")
//Parameter([0 : 5 : 100])
stepSlider = 12;
//Group("Checkbox")
//Description("description")
//Parameter("comment")
Variable = false;
//Group("Spinbox")
//Description("spinbox with step size 23")
//Parameter(23)
Spinbox = 35;
//Group("Textbox")
//Description("Text box for vector with more than 4 elements")
//Parameter("comment")
Vector = [2, 34, 45, 12, 3, 56];
//Group("Textbox")
//Description("Text box for string")
//Parameter("comment")
String = "hello";
//Group("Special vector")
//Description("Text box for vector with less than or equal to 4 elements")
//Parameter("any thing")
Vector2 = [12, 4, 45, 23];
//Group("Special vector")
//Parameter("")
nonparameter = "new";
//Group("Special vector")
//Parameter("")
stringVector = ["hello", "new", 12];
echo(String);

View file

@ -0,0 +1,52 @@
//Group("Drop down box:")
//Description("combo box for nunber")
//Parameter([0, 1, 2, 3])
Numbers = 2;
//Group("Drop down box:")
//Description("combo box for string")
//Parameter("")
Strings = "foo";
//Group("Drop down box:")
//Description("labeled combo box for numbers")
//Parameter([[10, "L"], [20, "M"], [30, "L"]])
Labeled_values = 10;
//Group("Drop down box:")
//Description("labeled combo box for string")
//Parameter([["S", "Small"], ["M", "Medium"], ["L", "Large"]])
Labeled_value = "S";
//Group(" Slider ")
//Description("slider widget for number")
//Parameter([10 : 100])
slider = 34;
//Group(" Slider ")
//Description("step slider for number")
//Parameter([0 : 5 : 100])
stepSlider = 2;
//Group("Checkbox")
//Description("description")
//Parameter("comment")
Variable = true;
//Group("Spinbox")
//Description("spinbox with step size 23")
//Parameter(23)
Spinbox = 5;
//Group("Textbox")
//Description("Text box for vector with more than 4 elements")
//Parameter("comment")
Vector = [12, 34, 44, 43, 23, 23];
//Group("Textbox")
//Description("Text box for string")
//Parameter("comment")
String = "hello";
//Group("Special vector")
//Description("Text box for vector with less than or equal to 4 elements")
//Parameter("any thing")
Vector2 = [12, 34, 45, 23];
//Group("Special vector")
//Parameter("")
nonparameter = "new";
//Group("Special vector")
//Parameter("")
stringVector = ["1", "2"];
echo(String);

View file

@ -0,0 +1,52 @@
//Group("Drop down box:")
//Description("combo box for nunber")
//Parameter([0, 1, 2, 3])
Numbers = 2;
//Group("Drop down box:")
//Description("combo box for string")
//Parameter("")
Strings = "foo";
//Group("Drop down box:")
//Description("labeled combo box for numbers")
//Parameter([[10, "L"], [20, "M"], [30, "L"]])
Labeled_values = 10;
//Group("Drop down box:")
//Description("labeled combo box for string")
//Parameter([["S", "Small"], ["M", "Medium"], ["L", "Large"]])
Labeled_value = "S new";
//Group(" Slider ")
//Description("slider widget for number")
//Parameter([10 : 100])
slider = 34;
//Group(" Slider ")
//Description("step slider for number")
//Parameter([0 : 5 : 100])
stepSlider = 2;
//Group("Checkbox")
//Description("description")
//Parameter("comment")
Variable = true;
//Group("Spinbox")
//Description("spinbox with step size 23")
//Parameter(23)
Spinbox = 5;
//Group("Textbox")
//Description("Text box for vector with more than 4 elements")
//Parameter("comment")
Vector = [12, 34, 44, 43, 23, 23];
//Group("Textbox")
//Description("Text box for string")
//Parameter("comment")
String = "hello";
//Group("Special vector")
//Description("Text box for vector with less than or equal to 4 elements")
//Parameter("any thing")
Vector2 = [12, 34, 45, 23];
//Group("Special vector")
//Parameter("")
nonparameter = "second";
//Group("Special vector")
//Parameter("")
stringVector = [" hello", " new "];
echo(String);

View file

@ -0,0 +1,52 @@
//Group("Drop down box:")
//Description("combo box for nunber")
//Parameter([0, 1, 2, 3])
Numbers = 2;
//Group("Drop down box:")
//Description("combo box for string")
//Parameter("")
Strings = "fo";
//Group("Drop down box:")
//Description("labeled combo box for numbers")
//Parameter([[10, "L"], [20, "M"], [30, "L"]])
Labeled_values = 10;
//Group("Drop down box:")
//Description("labeled combo box for string")
//Parameter([["S", "Small"], ["M", "Medium"], ["L", "Large"]])
Labeled_value = "S new";
//Group(" Slider ")
//Description("slider widget for number")
//Parameter([10 : 100])
slider = 34;
//Group(" Slider ")
//Description("step slider for number")
//Parameter([0 : 5 : 100])
stepSlider = 2;
//Group("Checkbox")
//Description("description")
//Parameter("comment")
Variable = true;
//Group("Spinbox")
//Description("spinbox with step size 23")
//Parameter(23)
Spinbox = 5;
//Group("Textbox")
//Description("Text box for vector with more than 4 elements")
//Parameter("comment")
Vector = [12, 34, 44, 43, 23, 23];
//Group("Textbox")
//Description("Text box for string")
//Parameter("comment")
String = "1234";
//Group("Special vector")
//Description("Text box for vector with less than or equal to 4 elements")
//Parameter("any thing")
Vector2 = [12, 34, 45, 23];
//Group("Special vector")
//Parameter("")
nonparameter = "new";
//Group("Special vector")
//Parameter("")
stringVector = ["1", "2"];
echo(String);

View file

@ -0,0 +1,55 @@
//Parameter("parameter")
a = true;
//Description("description")
//Parameter("parameter")
b = false;
//Description("description")
//Parameter("parameter")
c = undef;
d = a;
e = $fn;
//Description("description")
//Parameter("parameter")
f1 = [1];
//Description("description")
//Parameter("parameter")
f2 = [1, 2, 3];
g = ((f2.x + f2.y) + f2.z);
//Description("description")
//Parameter("parameter")
h1 = [2 : 5];
//Description("description")
//Parameter("parameter")
h2 = [1 : 2 : 10];
i = ((h2.begin - h2.step) - h2.end);
//Description("description")
//Parameter("parameter")
j = "test";
//Description("description")
//Parameter("parameter")
k = 0.0123;
l = (a * b);
m = (a / b);
n = (a % b);
o = (c < d);
p = (c <= d);
q = (c == d);
r = (c != d);
s = (c >= d);
t = (c > d);
u = (e && g);
v = (e || g);
w = i;
x = -i;
y = !i;
z = j;
aa = (k ? l : m);
bb = n[o];
cc = let(a = 1) a;
dd = [for(a = [0, 1]) (let(b = a) (if(true) (b)))];
ee = ["abc", for(a = [0, 1]) (let(b = a) (if(true) (b))), true, for(c = [1 : 3]) (c), 3];
ff = [for(a = [0, 1]) (if((a == 0)) ("A") else ("B"))];
gg = [each (["a", 0, false])];
hh = [for(a = [0 : 3]) (if((a < 2)) (if((a < 1)) (["+", a])) else (["-", a]))];
ii = [for(a = 0, b = 1;(a < 5);a = (a + 1), b = (b + 2)) [a, (b * b)]];

View file

@ -0,0 +1,34 @@
a = abs();
b = sign();
c = rands();
d = min();
e = max();
f = sin();
g = cos();
h = asin();
i = acos();
j = tan();
k = atan();
l = atan2();
m = round();
n = ceil();
o = floor();
p = pow();
q = sqrt();
r = exp();
ra = len();
s = log();
t = ln();
u = str();
ua = chr();
ub = concat();
v = lookup();
va = search();
y = version();
z = version_num();
za = norm();
zb = cross();
zc = parent_module();
w = dxf_dim();
x = dxf_cross();

View file

@ -0,0 +1,41 @@
minkowski();
hull();
resize();
child();
echo();
assign();
for();
intersection_for();
if(false) cube();
else sphere();
union();
difference();
intersection();
dxf_linear_extrude();
linear_extrude();
dxf_rotate_extrude();
rotate_extrude();
import();
import_stl();
import_off();
import_dxf();
group();
cube();
sphere();
cylinder();
polyhedron();
square();
circle();
polygon();
projection();
render();
surface();
scale();
rotate();
mirror();
translate();
multmatrix();
color();
offset();
text();

View file

@ -0,0 +1,38 @@
//Description("normal description")
//Parameter("")
x = 50;
//Description("normal starting width spaces description")
//Parameter("")
x2 = 45;
//Description("normal starting tab spaces description")
//Parameter("")
x3 = 3;
//Parameter("")
x4 = 3;
//Description("double description ")
//Parameter("")
x5 = 3;
//Parameter("")
x6 = 12;
//Parameter("")
x7 = 12;
//Parameter("")
x8 = 12;
//Description("description sandwiched between two assignments")
//Parameter("")
x9 = 23;
//Parameter("")
x19 = 23;
//Parameter("")
x10 = 23;
//Parameter("")
x11 = 23;
//Parameter("")
x12 = 23;
//Description("double description ")
//Parameter("")
x13 = 7;
//Description("double description normal comment starting with tab before ")
//Parameter("")
x14 = 3;

View file

@ -0,0 +1,50 @@
//Description("combo box for nunber")
//Parameter([0, 1, 2, 3])
Numbers = 2;
//Description("combo box for string")
//Parameter(["foo", "bar", "baz"])
Strings = "foo";
//Description("labeled combo box for numbers")
//Parameter([[10, "L"], [20, "M"], [30, "L"]])
Labeled_values = 10;
//Description("labeled combo box for string")
//Parameter([["S", "Small"], ["M", "Medium"], ["L", "Large"]])
Labeled_value = "S";
//Group(" Global ")
//Description("slider widget for number")
//Parameter([10 : 100])
slider = 34;
//Group(" Global ")
//Description("step slider for number")
//Parameter([0 : 5 : 100])
stepSlider = 2;
//Group("Hidden")
//Description("description")
//Parameter("comment")
Variable = true;
//Group("Global")
//Description("spinbox with step size 23")
//Parameter(23)
Spinbox = 5;
//Group("Textbox")
//Description("Text box for vector with more than 4 elements")
//Parameter("comment")
Vector = [12, 34, 44, 43, 23, 23];
//Group("Textbox")
//Description("Text box for string")
//Parameter("comment")
String = "hello";
//Group("Special vector")
//Description("Text box for vector with less than or equal to 4 elements")
//Parameter("any thing")
Vector2 = [12, 34, 45, 23];
//Group("Special vector")
//Description("Norma; text")
//Parameter("comment with ")
String2 = "hello";
//Group("group after \" in previous comment ")
//Description("Text box for vector with less than or equal to 4 elements")
//Parameter("any thing")
Vector3 = [12, 34, 45, 23];
echo(String);

View file

@ -0,0 +1,69 @@
//Parameter("")
x = 1;
//Parameter(12)
x1 = 1;
//Parameter(12)
x2 = 1;
//Parameter(12)
x3 = 1;
//Parameter(12)
x4 = 1;
//Parameter([1 : 12])
x5 = 1;
//Parameter([1 : 2 : 12])
x6 = 1;
//Parameter("")
x7 = 1;
//Parameter("")
x8 = 1;
//Parameter("")
x9 = 1;
//Parameter("")
x10 = 1;
//Parameter("")
x11 = 1;
//Parameter([12])
x12 = 1;
//Parameter([[10, "Small"], [20, "Medium"], [30, "Large"]])
x13 = 10;
//Parameter([[10, "Small"], [20, "34 Medium"], [30, "Large 12"]])
x13a = 10;
//Parameter([[10, 100], [20, 101], [30, 102]])
x14 = 10;
//Parameter("parameter")
x15 = 10;
//Parameter([0, 1, 2, 3])
x16 = 10;
//Parameter("parameter")
x17 = "text";
//Parameter(["foo", "bar", "baz"])
x18 = "text";
//Parameter([[0, "text"], [1, "foo"], [2, "bar"], [3, "hello"]])
x19 = "text";
//Parameter([["foo", 10], ["bar", 10], ["baz", 30]])
x20 = "text";
//Parameter([["foo", "yes"], ["bar", "no"], ["baz", "mgiht"]])
x21 = "text";
//Parameter([23, 4])
x22 = [12, 34];
//Parameter([23, 4, 23, 4, 45])
x23 = [12, 34];
//Parameter([23, 4, 2, 3, 4, 6])
x24 = [12, 34, 2, 3, 41, 23];
//Parameter("")
x25 = 12;
//Parameter("")
x26 = "text";
//Parameter("end parameter")
x27 = 12;
//Parameter("")
x28 = -12;
//Parameter("")
x29 = !1;
//Parameter("")
x30 = ["new", "secon"];
//Parameter(["new", "second"])
x31 = ["new", "second"];
//Parameter(["new", "second"])
x32 = ["new", "second"];

View file

@ -0,0 +1,214 @@
cylinder($fn = 0, $fa = 12, $fs = 2, h = 50, r1 = 2, r2 = 1, center = false);
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 46.5], [0, 0, 0, 1]]) {
group() {
difference() {
cylinder($fn = 360, $fa = 12, $fs = 2, h = 7, r1 = 4, r2 = 4, center = false);
cylinder($fn = 360, $fa = 12, $fs = 2, h = 8, r1 = 2, r2 = 2, center = false);
}
}
}
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 46.5], [0, 0, 0, 1]]) {
group() {
difference() {
union() {
group() {
group() {
multmatrix([[1, 0, 0, 25], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 7, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, 15.5872], [0, 1, 0, -19.5458], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 7, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -5.56302], [0, 1, 0, -24.3732], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 7, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -22.5242], [0, 1, 0, -10.8471], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 7, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -22.5242], [0, 1, 0, 10.8471], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 7, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -5.56302], [0, 1, 0, 24.3732], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 7, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, 15.5872], [0, 1, 0, 19.5458], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 7, r1 = 4, r2 = 4, center = false);
}
}
}
}
group() {
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[0.62349, -0.781831, 0, 0], [0.781831, 0.62349, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.222521, -0.974928, 0, 0], [0.974928, -0.222521, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.900969, -0.433884, 0, 0], [0.433884, -0.900969, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.900969, 0.433884, 0, 0], [-0.433884, -0.900969, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.222521, 0.974928, 0, 0], [-0.974928, -0.222521, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[0.62349, 0.781831, 0, 0], [-0.781831, 0.62349, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
}
linear_extrude(height = 4, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 0.5, $fs = 0.5) {
difference() {
circle($fn = 0, $fa = 0.5, $fs = 0.5, r = 25);
circle($fn = 0, $fa = 0.5, $fs = 0.5, r = 23);
}
}
}
group() {
group() {
multmatrix([[1, 0, 0, 25], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 8, r1 = 3, r2 = 3, center = false);
}
}
multmatrix([[1, 0, 0, 15.5872], [0, 1, 0, -19.5458], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 8, r1 = 3, r2 = 3, center = false);
}
}
multmatrix([[1, 0, 0, -5.56302], [0, 1, 0, -24.3732], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 8, r1 = 3, r2 = 3, center = false);
}
}
multmatrix([[1, 0, 0, -22.5242], [0, 1, 0, -10.8471], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 8, r1 = 3, r2 = 3, center = false);
}
}
multmatrix([[1, 0, 0, -22.5242], [0, 1, 0, 10.8471], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 8, r1 = 3, r2 = 3, center = false);
}
}
multmatrix([[1, 0, 0, -5.56302], [0, 1, 0, 24.3732], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 8, r1 = 3, r2 = 3, center = false);
}
}
multmatrix([[1, 0, 0, 15.5872], [0, 1, 0, 19.5458], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 0.5, $fs = 0.5, h = 8, r1 = 3, r2 = 3, center = false);
}
}
}
}
}
}
group() {
group() {
multmatrix([[1, 0, 0, 25], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, 15.5872], [0, 1, 0, -19.5458], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -5.56302], [0, 1, 0, -24.3732], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -22.5242], [0, 1, 0, -10.8471], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -22.5242], [0, 1, 0, 10.8471], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, -5.56302], [0, 1, 0, 24.3732], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 4, r2 = 4, center = false);
}
}
multmatrix([[1, 0, 0, 15.5872], [0, 1, 0, 19.5458], [0, 0, 1, 0], [0, 0, 0, 1]]) {
group() {
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 4, r2 = 4, center = false);
}
}
}
}
}
group() {
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[0.62349, -0.781831, 0, 0], [0.781831, 0.62349, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.222521, -0.974928, 0, 0], [0.974928, -0.222521, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.900969, -0.433884, 0, 0], [0.433884, -0.900969, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.900969, 0.433884, 0, 0], [-0.433884, -0.900969, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[-0.222521, 0.974928, 0, 0], [-0.974928, -0.222521, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
multmatrix([[0.62349, 0.781831, 0, 0], [-0.781831, 0.62349, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, -2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
cube(size = [25, 3, 3], center = false);
}
}
}

View file

@ -0,0 +1,16 @@
multmatrix([[1, 0, 0, 0], [0, 0.5, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
difference() {
cylinder($fn = 10, $fa = 12, $fs = 2, h = 4, r1 = 80, r2 = 80, center = true);
multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 2], [0, 0, 0, 1]]) {
cylinder($fn = 10, $fa = 12, $fs = 2, h = 3, r1 = 70, r2 = 70, center = true);
}
}
}
linear_extrude(height = 2, center = false, convexity = 1, scale = [1, 1], $fn = 10, $fa = 12, $fs = 2) {
multmatrix([[1, 0, 0, 0], [0, 1, 0, 4], [0, 0, 1, 0], [0, 0, 0, 1]]) {
text(text = "Welcome to...", size = 10, spacing = 1, font = "", direction = "ltr", language = "en", script = "Latn", halign = "center", valign = "baseline", $fn = 10, $fa = 12, $fs = 2);
}
multmatrix([[1, 0, 0, 0], [0, 1, 0, -16], [0, 0, 1, 0], [0, 0, 0, 1]]) {
text(text = "Parametric Designs", size = 10, spacing = 1, font = "", direction = "ltr", language = "en", script = "Latn", halign = "center", valign = "baseline", $fn = 10, $fa = 12, $fs = 2);
}
}

View file

@ -35,3 +35,4 @@ ff = [for(a = [0, 1]) (if((a == 0)) ("A") else ("B"))];
gg = [each (["a", 0, false])];
hh = [for(a = [0 : 3]) (if((a < 2)) (if((a < 1)) (["+", a])) else (["-", a]))];
ii = [for(a = 0, b = 1;(a < 5);a = (a + 1), b = (b + 2)) [a, (b * b)]];

View file

@ -81,7 +81,7 @@
</CommandLineArgument>
<CommandLineArgument
argument = "testdata/scad/misc/allmodules.scad"
isEnabled = "YES">
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "non-manifold2.scad -o non-manifold2.stl --debug=GeometryUtils"