Exit Full View

Vectorial / brainDump.txt

Brain Dump
==========

Some random thoughts while thinking about this project...



Filetype vial (vialz for the zip variant)

Customisable handle sizes (and styles).

Two zoom&pan settings, which can be toggled between, so that it is easy to switch between a high zoom level for editing,
    and then zoom back out to see the results.
    From the zoomed out state, we can drag a bounding box to zoom in on an area (replacing the old zoom-in settings).

How does blur work in OpenGL?
    Doesn't the shader only draw pixels within the area bounded by the triangle?
    So do we need to offset the shape when we create the mesh when the blur changes?
    But then how do we

Every shape has a unique identifier (String),
    but for speed, internally we actually store all shapes in ONE array, and the id is really the index.
    We then have a lookup table which converts the string ids to indices.
    Do this for every type of object, such as named colors.
    When we rename an item, we need to change every expression which uses that object.

Borders can be INSIDE, OUTSIDE or straddle the edges of the solid. (Maybe 0..1, or ever a greater range!)
    Note, if the border is inside and rounded, then the fill ALSO needs to be rounded.

All the usual stuff :
    Paths, groups, transformations, layers ...

Standard gradient fills, pattern fills, texture fills...
    However, consider using the full power of OpenGL, which allows us to map textures using uvs.
    Each point of the path has a uv, which you can change, either manually, or via "standard" mappings, such as "radial"

Cloned objects
    But how flexible can we be with them?
        For example, can we change more than the clone's transform and color?
        e.g. Can we change a single vertex
        e.g. Can we change a single "property" of a smart shape?

Document coordinates
    Let's not force Y=0 at the top, let it be the bottom if we want!
    Just give Document a transform which is identity for Y=0 == TOP, but a matrix based on height otherwise.

Offset Path
    Uses the path data of another path, but is offset by a given amount

Repeated shapes
    Similar to clone.

A document has more than just a single "view".
    Pages
    Textures
    Palettes
    Patterns
    Shaders
    Constants - e.g. for gridSize, boxRadius ...

Render using OpenGL.

Export all

Exporting a shape does NOT include anything that happens to overlap it.

Linked resources (textures) use relative paths when applicable (never go UP a directory).

Updating the model
==================

Calculated points require updates to happen whenever a shape which it is dependent on changes.
    This includes transformations of the depends-on shape parents.

How should we do this? Take Point as an example.

    Maybe Keep track of all points which are used by any given point.
    e.g.
        interface Shape( parent : Parent, shapeName : String, pointsData : List<PointData> )

        interface PointData( pointName : String, point : Point, usedBy : PointDependency )
        class SimplePointData : PointData
        class ExpressionPointData : PointData
        class PointDependency( shape : Shape, pointIndex : Int )

        pointName is "p0", "p1", "p2" for triangles. "center" for a circle etc.

        pointIndex will be the index into shape's PointData list.

    So, the expression Shapes[MyTriangle.p0] + (2,0) adds a PointDependency to MyTriangle's p0 PointItem.

    NOTE
        PointDependency will actually be a generic class Dependency<Point>
        As we will have lots of these, such as Dependency<Length>, Dependency<Angle>, Dependency<Color> etc.

    BUT
        We want to have values in other places too (not just Shape). For example, our document/page has a background color,
        a size etc, and we may want to refer to these too.

    So
        interface Item ( itemName : String, byName : Map<String,Any> )
        interface HasPoints( pointsData : List<PointData> ) : Item // Note, shapeName must be renamed to "itemName"
        interface Shape : HasPoints

    And now we can have Items such as Document, DocumentGrid ...
    byName is a map of all the data, keyed by its name. This forces all named items to have a unique name.


Parent
======

    interface Parent( transform : Matrix32, inverseTransform : Matrix32 ) : Item

Handles & Mouse
===============

Handles are always drawn last. We do NOT get into nasty "context" stuff, and instead draw them via localToWorld( thePoint ).
However, as we need to inspect the world points often, we should cache the world values.
    i.e. PointData will have a worldPoint as well as a local Point.
    For SimplePointData, the worldPoint should be cached and made dirty whenever a parent changes, or the local point changes.
    For ExpressionPointData we can update these whenever a
    For both of them, when they are invalidated (isDirty = true), also invalidate all usedBy.

Many Handle subclasses, which know how to change the data.
    e.g. BezierControl1, BezierControl2, BezierStart, BezierEnd, EllipseWidth, EllipseHeight ...
    BezierControl1 has the previous PathSection, or null if this is the first section in the path.
        NOTE. BezierControl1&2 should respect the tangent of the prev/next line unless the vertex is sharp.
        ALSO, if symmetric, and the other handle is locked/expression, then we cannot drag it without either unlinking, or making it asymmetric.

Handles have different effects based upon Ctrl, Shift, Alt
    Give a summary in the status bar.
    With ("More..." added when there are more alternatives, or the text doesn't fit on).
    When not dragging, always show "More...", and when clicked, explain that double clicking Shift will bring up extra info.
    Could use arrow keys to choose extra features from this info???

Partial Point Expressions
=========================

My design hasn't accounted for points which are only partially constrained.
For example, we want to constrain a point to a construction line, but leave the position along that line free.
Dragging its handle should let us move the point anywhere along that line.

So Expressions can have many types.

 * Calculated i.e. no free variables.
 * AlongLine (either with a "t" value, or as a fixed distance from an end point)
 * AlongPath (with a t value)
 * AlongArc (either with a "t" value, or as a distance from one of the arc's end points)
 * Horizontal/Vertical Guide : x or y are free. Note, for angled lines, use AlongLine (above).
 * User Defined Partial Constraint :
     An arbitrary expression and a free variable with a given range, and the GUI lets us change this free variable
     using a slider or similar.

Construction lines then become the basis upon which we create one of the above.
    e.g. If we draw a construction line segment, then we end up with an "AlongLine" constraint.
Note Horizontal and Vertical guides are just another type of construction line ;-)

Can we have two points that are glued, but free to move anywhere.
    e.g. Glue the corners of two rectangles together, and moving EITHER of the rectangles also moves the other one.
    We could then glue a whole grid of them together!

If any Geometry of a shape isn't free

Temporary Construction Lines
============================

If we want to create a point as an expressions in the GUI,
draw a construction line, and then snap a handle to it.
The construction line can then be removed.
NOTE, we may actually still have the construction line object (as part of the expression), but
it is removed as an Item in the document.

Other Cached Data
=================

We may need to cache bounding boxes for each Shape, and maybe even a "neighbourhood" structure to help speed up selection.
Snappable points would certainly benefit from a Neighbourhood.
NOTE, the neighbourhood can be recalculated on mouse up.

Undo/Redo
=========

Do NOT make any changes to the model directly. Instead, batch{ foo() }
    Where foo() is a method of HistoryBatch, which creates an Alteration, and applies it.
    If the new Alteration can be merged with the previous one, then great, merge them!
    Otherwise, add the Alteration to the HistoryBatch.
Each Ctrl+Z, Ctrl+Shift+Z shows details of the Alteration.

Keyboard Shortcuts
==================

Shortcuts can have a context
    e.g. Delete keys can be used to delete the current vertex as well as delete the current Shape.

While dragging we can TEMPORARILY turn snapping on/off.
    e.g. If we assume there's no snapping, we could turn on grid snapping using #

Snapping vs Gluing
==================

When we move a Handle, and it snaps to a geometry, it does NOT glue it.
Hit G to glue it i.e. the point changes from a SimplePointData to ExpressionPointData.

NOTE, there are many glue options when snapping to lines/splines.
    Ratio, Nearest, Furthest

Cyclic Dependencies
===================

Whenever we make a change, draw will be called, which calls "ensureClean".
    If this throws a CyclicDependency exception, then we can show a dialog, and allow one item to be cut.
    Maybe ensureClean is called twice. The first throws an exception with the item that failed.
    We then try to calculate that item AGAIN, but this time keeping track of all items being calculated.
    We will then have enough information to show a dialog which lets the user cut one of the expressions.

Expression Language
===================

Points

[1,0] is a vector in the default units for the document.
[float, float]

[1pt, 3px] a vector using explicit units.
Note, the conversion between pt, px, em and real lengths, such as mm, cm is done by the Document.
Values are always stored in the document's default units.
If we change the default, we need to add units to all expressions which omit them.

Lengths

4px 2em 5mm etc

Numbers

4 4.0

Always treated as floats.

Colors :

#ccc
#c1c1c1
#cccf // With transparency
RED // Include all the named web colors.
Pallet.highlight // A color defined in this document's palette.
Document.Pallet.highlight // Same as the above.

To reference a shape, we can use its unique name : Shape.myTriangle
We can also refer to our parent : parent
Also refer to a sibling using a "local" name (so that we can choose names which aren't unique) : parent.myBox

Note, a Path is a list of PathSections, such as Line, Bezier, EllipticalArc ...
How should we reference them?
    We *could* use an index, and then we'd need to fix expressions when a point is added/removed.

    Shape.mySquiggle.Sections[1].p0

The Application's names, (such as Document, Pallet, Grid, Page...) all start with a capital.
All names (such as myRect) start with a lower case.
Use camelCase, not underscores.

Objects are given a default name, such as rect1
Renaming an object should NEVER break anything, and it should be impossible to duplicate a name.

File Format
===========

JSON.
However, if we embed other objects, then use a different extension, and put the JSON, and other resources into a zip.

Also export as SVG
    Can we keep *all* of the data within an extra XML namespace?

Extra Features
==============

It would be nice if Paths could be combined and then un-combined again.
    e.g. Take two overlapping squares.
    Combine them to make a funky shape, but KEEP the two squares.
    We can then manipulate the two squares, and the result is the combination of the two.
    We can *choose* to make this permanent (to form a simple Path again), but we don't have to.
Also, allow combining of Shapes, not only Paths.

When using a Color from a palette, we should be able to change its opacity, and the result is
an Expression, which refers the swatch, but with a different alpha value.

When we look at the Paint info for a shape, it should highlight the swatch if it is from the document's Palette.
    Ditto if the Paint color is *related* to a swatch.