Skip to content

Commit

Permalink
making geometry objects more similar, writing down some of the plan
Browse files Browse the repository at this point in the history
  • Loading branch information
robin-swift committed Jun 17, 2024
1 parent bd589cf commit 24acad4
Show file tree
Hide file tree
Showing 26 changed files with 1,163 additions and 1,171 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ qt_add_executable(embroidermodder2
${SRC}/imagewidget.cpp
${SRC}/layer-commands.cpp
${SRC}/layer-manager.cpp
${SRC}/geometry.cpp
${SRC}/main.cpp
${SRC}/mainwindow.cpp
${SRC}/mainwindow-actions.cpp
Expand Down
84 changes: 84 additions & 0 deletions docs/refman/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Simplifying codebase

## Removing Embedded Javascript

A large proportion of the code is present to facilitate the Javascript (ECMAScript) interpreter
that allows Embroidermodder to be extensible. This feature is one of the least important to
the average user and our command line program `embroider` is the appropriate way for users
to automate their work. It also is a feature that makes the source far harder to manage and
much larger.

This is a very complex change, a lot of the planned user interaction was highly dependant on
how Javascript works. For example, using a number that is set to `NaN` to establish that a
step in the user interaction is incomplete. Also Javascript is dynamically typed, so there is
a lot of management of strings, ints and real numbers that doesn't work the same in C/C++.

### Managing modal interactions

When the user adds an ellipse, for example, 3 clicks are required to establish the ellipse
and 1 more click to optionally set its rotation. Each of these are associated with an
enum that is incremented when each click callback is used.

### Combining Contexts

To make the `command_data` table simpler, rather than have context-sensitive commands
have 5 callbacks and context-insensitive commands have 1, we make the callback capable of
detecting the context it has been called in.

## Combining Geometry Management

Libembroidery and Embroidermodder 2 were slightly at odds with how they dealt with geometry:
every libembroidery type having a sister class in EM2. For example EmbArc relates to ArcObject.
This was necessary to allow the EM2 geometry to inherit the `QGraphicsPathItem`
class.

However, since so much of the geometry algorithms and structs are within
libembroidery making these classes less object-oriented. This would mean we don't have to
load all of the geometry in the pattern into `QGraphicsPathItem` copies to render and manipulate
and then dump them all back into the pattern to save.

## Rules surrounding C, C++ and Qt features and functions

The main rule here is to reduce the amount of code necessary to achieve what we want,
seperate code from data to allow alterations to happen entirely in data and reduce the amount of
dependancy that creates on libraries.

1. Don't use a Qt function when a C++ will do: it makes us work to Qt's intended style and makes code harder to read for non-Qt favouring developers. (Don't use `qMax`, `qCos` etc.)
2. Don't use a C++ function when a C one will do, it makes the interfacing between C and C++ parts of the source more complicated. (Don't use the `std::` copies.)
3. Don't use polymorphism, it slows down compliation, produces long and hard to interpret compiler messages.
4. Use switch/case whenever the if/else chain is based on an enum (or defines that act as an enum).
5. Use C linkage for any function not in a class that only uses C types.
6. Don't create a class for data that isn't dynamically allocated, for functions that don't use the private data.
7. Avoid using set/get for class data when the data can be public.
8. Reduce the amount of dynamically allocated memory, every allocation creates an oppertunity for invalid memory.

## Compilation Speed

Ideally the compilation of the entire project, including libembroidery should be so fast that
the development cycle doesn't have to account for it. At the time of writing, the following
commands create this output:

```
$ make clean
$ time `make &> build.log`
real 9m14.716s
user 8m39.204s
sys 0m28.895s
$ make clean
$ time `make &> build.log`
real 4m30.748s
user 15m5.793s
sys 1m3.419s
```

Note that we are not including the `cmake` time since that is only done once
as setup. If you made an alteration in `src/core.h` and wanted to test it, it would
take you a 4m 30s turnaround. Waiting this long makes the development cycle pretty slow,
if we could cut this in half then that would help.

# Bugs

* `icon24` is being interpreted as `rgb`
* "Oh Yeah!" button causes crash
32 changes: 16 additions & 16 deletions src/commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,7 @@ platform_command(ScriptEnv *context)
}

init_command();
// setPromptPrefix(qsTr("Platform") + " = " + _main->platformString());
// appendPromptHistory();
// prompt_output(translate("Platform") + " = " + _main->platformString());
end_command();
return script_null;
}
Expand Down Expand Up @@ -758,34 +757,30 @@ settings_dialog_command(ScriptEnv *context)
return script_null;
}

/* NOTE: main() is run every time the command is started.
* Use it to reset variables so they are ready to go.
*/
/* SYSWINDOWS */
ScriptValue
syswindows_command(ScriptEnv * context)
{
init_command();
clear_selection();
/*
setPromptPrefix(qsTr("Enter an option [Cascade/Tile]: "));
*/
prompt_output(translate("Enter an option [Cascade/Tile]: "));

// Do nothing for click, context

#if 0
if (str == "C" || str == "CASCADE") {
//TODO: Probably should add additional qsTr calls here.
//TODO: Probably should add additional translate calls here.
_main->windowCascade();
end_command();
}
else if (str == "T" || str == "TILE") {
//TODO: Probably should add additional qsTr calls here.
//TODO: Probably should add additional translate calls here.
_main->windowTile();
end_command();
}
else {
alert(qsTr("Invalid option keyword."));
setPromptPrefix(qsTr("Enter an option [Cascade/Tile]: "));
alert(translate("Invalid option keyword."));
prompt_output(translate("Enter an option [Cascade/Tile]: "));
}
#endif
return script_null;
Expand Down Expand Up @@ -886,9 +881,7 @@ todo_command(ScriptEnv *context)
return script_null;
}

/* NOTE: main() is run every time the command is started.
* Use it to reset variables so they are ready to go.
*/
/* UNDO */
ScriptValue
undo_command(ScriptEnv * context)
{
Expand Down Expand Up @@ -1205,7 +1198,14 @@ add_arc_command(ScriptEnv* context)
if (!argument_checks(context, "mouseX", "rrrrrr")) {
return script_false;
}
_main->nativeAddArc(REAL(0), REAL(1), REAL(2), REAL(3), REAL(4), REAL(5), OBJ_RUBBER_OFF);
EmbArc arc;
arc.start.x = REAL(0);
arc.start.y = REAL(1);
arc.mid.x = REAL(2);
arc.mid.y = REAL(3);
arc.end.x = REAL(4);
arc.end.y = REAL(5);
_main->nativeAddArc(arc, OBJ_RUBBER_OFF);
return script_null;
}

Expand Down
8 changes: 7 additions & 1 deletion src/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ OBJ_TYPE_RECTANGLE = 100025,
OBJ_TYPE_SLOT = 100026,
OBJ_TYPE_SPLINE = 100027,
OBJ_TYPE_TEXTMULTI = 100028,
OBJ_TYPE_TEXTSINGLE = 100029
OBJ_TYPE_TEXTSINGLE = 100029,
OBJ_TYPE_UNKNOWN = 100029
};

//OBJ_NAME_VALUES
Expand Down Expand Up @@ -476,6 +477,11 @@ void prompt_output(const char *);
int argument_checks(ScriptEnv *context, char *function, const char *args);
char *translate(char *msg);

int parse_floats(char *line, float result[], int n);
int parse_vector(char *line, EmbVector *v);
bool validRGB(float r, float g, float b);
void reportDistance(EmbVector a, EmbVector b);

/* MainWindow calls */
void init_command(void);
void clear_selection(void);
Expand Down
Loading

0 comments on commit 24acad4

Please sign in to comment.