felixhayashi / TW5-TiddlyMap

Map drawing and topic visualization for your wiki
http://tiddlymap.org
BSD 2-Clause "Simplified" License
863 stars 132 forks source link

Edge weights; Timeline & parameter views #270

Open micahscopes opened 7 years ago

micahscopes commented 7 years ago

Hi, I'm the lone developer on a game team. We're making an adventure game (a dating sim). I've stubbornly decided that I want to use TW5 because its so unique and well-made, and also because this mapping tool is so awesome and wonderful.

So I'd like to propose a new feature and develop it. What I'm asking from you is some feedback and tips on how best to integrate this feature with the existing tiddlymap code.

The very generic big picture: I'd like to give edges weights/parameters that could be used in open ended, dynamic ways by widgets and tw5 plugins. Then I'd like to utilize some more of those nice vis.js features (have you seen these!?) to create views/editors for these weights/parameters. Ideally, these views would be just as flexible as the existing map views.

A concrete example: say I have a bunch of tiddlers that represent text that I want to be transcluded into a view tiddler, in a specific order with specific timing. Right now I could use a custom edge type to represent this. Here we have a tiddler called A with edges of type flow:reveal to three tiddlers, B,C and D:

flow-reveal-a bcd

As it stands, we could write a flow-reveal widget that looks at the a widget's flow:* edges, then transcludes and reveals all the related tiddlers connected via by flow:reveal edges.

If we had <$flow-reveal root='A'/>, it'd goto A, then transclude B, C and D into A, all at the same time.

Instead of a widget, we could even write a plugin that just automatically did flow:* stuff. And tiddlymapper wouldn't need to know anything whatsoever about how it worked, or that it even existed!

Now... imagine that you could switch from the force layout to this:

flow-chart-abcd ๐Ÿ˜ฎ ๐Ÿ˜ฒ

(In case you're curious, I just modified this vis.js example)

The tmap.edges property of tiddler A would now be:

{
  "770dbc90-ad90-4e3c-b8dd-049ac36b44d5":
    { "to":"6f4fc4ea-a340-49fa-abe2-dfb9b0b62a6b",
      "type":"flow:reveal",
      "start": 1000, "end": 4000
    },
  "1565adfa-4740-40e8-81e6-5621af72d955":
    { "to":"5f126c65-c677-448b-a031-e7961aa7e044",
      "type":"flow:reveal",
      "start": 2000, "end": 3500
    },
  "3ae335ec-ba78-4a1b-96fb-31e5b6bf0e20":
    { "to":"a6808c50-ea17-4b1a-8cb1-eb05754da659",
      "type":"flow:reveal",
      "start": 5000, "end": 20000
    }
}

Now we can tell our flow-reveal thing to take into account start and end weights of each edge, so that it could do the revealing at just the right timing! Can you imagine the possibilities?!

Here's a bigger example: reveal link

In this case the flow:reveal subgraph has two disjoint clusters. However, since the view's edge selection includes tw-body:link edges, the overall graph is connected.

Similarly, for the timeline layout of this view, I've imagined automatically generating timeline groups from the two disjoint clusters in the flow:reveal subgraph.

See here: multiple-flows

How would this play out? Our flow-reveal thingy would transclude B into A, C & D into B, and E & F into D, revealing them according to the start and end parameters of the flow:reveal edges. Then it would stop.

But there is a plain wikitext link from D to G. Clicking it would go to G. Again, our flow-reveal thing would transclude and reveal I & H into G.

These examples are very specific, but I'm imagining something as flexible and generic as the existing mapping tool! Potentially, it might even be cool to integrate some other vis.js views to edit more edge parameters.

For example, what if you wanted to have a edge type called flow:random-jump, which held a delay parameter and a probability parameter. Well then maybe it'd make since to have a timeline-like view with delay on the x-axis and probability on the y-axis. A flow-random-jump widget might look at the tiddlers connected to the current tiddler by this flow:random-jump edge type and then pick one according to normalized probability weights. Then, it'd look at the delay for the edge it picked, wait and jump to that tiddler if nothing happened in the meantime.

By the way, it could also be nice to have an edge-parameter editing widget in the existing tiddlymapper map view. That's something I could probably do right now without much help. Maybe the edges could have little drop-down widgets that let you type in a parameter or select it with a slider/menu.

For example, what if you wanted to give some edge type an enabled weight that could take boolean values? Or what if you wanted to have some edge types called sound:play that took volume, fadeIn, duration and fadeOut parameters.

Okay, I think I've said enough for now. I'm looking forward to hearing your feedback ๐Ÿ˜ƒ

Just so you know what I'd like to use this feature for in our game: Transcluding dialog and imagery, flowing between scenes, music and sound. Those are just off the top of my head.

micahscopes commented 7 years ago

Just to summarize the core components of this feature:

  1. Allow edges to have parameters (a.k.a. 'weights'). The parameters could be specified via edge types, or just added freely on a per-edge basis. They could be stored in source tiddler's tmap.edge JSON property, along-side the edge id and target id.

  2. Give the option to edit these parameters directly in tiddlymapper views.

  3. Tiddlymapper views would have customizable modes (think "layouts"?) for viewing and editing specific edge parameters of edges visible in the current view. This could be conceived of as having alternatives to the force layout. Picture the ability to switch from the force layout to a timeline or graph layout that is coupled to specified edge parameters. The important thing is that dragging nodes around in these parameter layouts would edit the edge parameters.

felixhayashi commented 7 years ago

Hi @micahscopes

many thanks for laying out your thoughts in detail. The idea to offer ways to add metadata/weights/parameters to edges that goes beyond mere linking- and styling-data is a great idea. For nodes, which are tiddlers themselves, this feature already exists (the fields of the tiddler can be used to store extra node data), but for edges this feature is missing indeed.

As you suggested it would make sense to give the user both a chance to add meta-data on an "edge-type" level (which affects all edges of that type) as well as on an "edge-instance" level which could be stored, as you already pointed out, in the tmap.edges field json and only affects the specific edge.

Picture the ability to switch from the force layout to a timeline or graph layout that is coupled to specified edge parameters. The important thing is that dragging nodes around in these parameter layouts would edit the edge parameters.

That sounds great. This also plays well with the general idea of switching between text mode (TiddlyWIki) and map-layouts (TiddlyMap). So maybe in the future you can modify Timelines (or other kind of charts) by modifying graphs and vice versa ;)

While not related to what you are planning to do, maybe this TW plugin could also be of interest to you: http://kixam.github.io/TW5-visjsTimeline/

Give the option to edit these parameters directly in tiddlymapper views.

The question of designing the GUI is a critical aspect here. I would suggest to start with adding an extra tab in the edge-type manager (which is opened when double clicking edges; the "overview", "styling", "general" etc. are shown) that is named "metadata" (or something similar), where the user can add parameters via a key-value input field list. Once the user hits "save" those fields are stored in the edge-type.

As for storing metadata per edge-instance: One option would be to extend the right-click popup/tooltip feature, which currently exists only for nodes, to be also used for edges. The right-click on an edge could open a tooltip menu with a menu entry named "add metadata" that leads to a dialog that allows the user to add key-value parametrisation (very similar to the "edit node" dialog which opens when double clicking on a node). The key-value form editor could be the same one as in the edge-type manager, however, the result is stored in the tmap.edges json. โ€“ By the way: One thing to consider is that only tmap.edges can have parametrization, edges inferred from tags, lists or fields do not have a json container to hold that extra data.

What I'm asking from you is some feedback and tips on how best to integrate this feature with the existing tiddlymap code.

Hope the feedback above helps a bit. If you have specific questions about the TiddlyMap code, please ask :) I may not respond right away but I'll try my best.

Best wishes Felix

micahscopes commented 7 years ago

Felix, Thank you so much for your helpful response! I was very excited that you understood what I wrote.

I like the "metadata" name. It seems like a name that's very friendly to folks more interested in mind mapping and concept mapping kinds of things. I think I'll start there.

As for the changes in network-map views affecting changes in timeline/chart views, I already have some ideas.

The most promising one to me at the moment is to allow, in chart views, not only an absolute plotting mode but also a relative mode that plots parameters additively as you descend parent-child relationships. In absolute mode, a parameter would just be plotted as you might expect given its value, but in relative mode, each edge parameter would be plotted relative to its "parent edge" parameter. Dragging a node would edit the edge parameter relative to its parent edge parameter, like a vector. If a loop exists, maybe it could be drawn until the edge of the screen, but in a non-editable way. Or a more simple solution: only draw edges once.

That's the main one I'll focus on at first for the timeline editor. It'd let you plot successive "delay" parameters linearly and edit them as though they were on the same timeline. The timeline will of course be defined by the descent of visible graph edges. I still need to answer the question of "descending from where?"... in the case of loops, where is the root? I'm confident I'll be able to figure something out that makes sense.

I haven't thought as much about deriving network relationship changes from edge metadata plots, but I'm sure there are lots of interesting possibilities!

One thing to think about will be managing all the possibilities! Guess it makes sense to wait and cross that bridge when it's time :)

Thanks for the heads up on that timeline plugin, by the way. I hadn't seen that.

Micah

felixhayashi commented 7 years ago

Hi @micahscopes,

The timeline will of course be defined by the descent of visible graph edges. I still need to answer the question of "descending from where?"... in the case of loops, where is the root? I'm confident I'll be able to figure something out that makes sense.

You could try to dissallow users creating cyclic connections but this will be difficult, I guess. Another option would be to shift the decision to the user, i.e. let the user define the timeline offset somehow. Or maybe you should treat this issue as an edge case for now, which you can solve in later stages of the development.

Felix

micahscopes commented 6 years ago

I'm digging into this now and working to understand the project organization. Do you ever go on the #tiddlywiki channel on freenode? Maybe we could arrange a time when I could pick your brain?

samuelwiechmann commented 6 years ago

I am also interested in the feature described by @micahscopes ๐Ÿ‘

Allow edges to have parameters (a.k.a. 'weights'). The parameters could be specified via edge types, or just added freely on a per-edge basis.

It would already help to be able to set the physics-properties per edge-type. This would allow to create connections in a free-floating graph without influencing the structure. But I have no idea how to do that or if it is even possible with vis.js.

Even better though would be to also have the ability to set the springConstant-parameter on a per-edge basis. I imagine the springConstant increasing with every approoving click by a user for example.