The future of plugins and extensions with Hype

As I am writing extensions for Hype am really wishing for Live-Previews and JS running in the Hype GUI. I guess it’s also a matter of security that this still isn’t possible. In one of my recent newsletters I came across this interesting Blog-Post from Figma and their Plugin-Approaches. Maybe an interesting read for Tumult (@jonathan, @Daniel).

3 Likes

I saw that too; it is a clever solution. Security is a factor, but isn’t a reason for not having plugins in Hype. In fact, the scene editor will run javascript now if you include it in the head html (or as part of a .js file set to be included in the head).

1 Like

I’ll give it a test… live preview is one thing although it might often slightly differ from the actual display function to not annoy while editing.

Yeah, the reality is that there are definitely times when one would want and wouldn’t want effects to be previewed live. Right now it is both a feature and bug (depending on the effect) that these occur in the scene editor. I can see that a plugin should be able to be notified when it is okay or not okay to render.

Also it might have it’s preview code be removed on exports.

Yup, any plugin system would need to be able to identify and export differently based on the editor vs. export environment.

Here is a quick example but I am not getting all green Div's in the GUI?
ActiveScriptInHeadTest.hype.zip (12,7 KB)

:+1:

BTW I loved the times when we could enable the JSContexts. It would fire up the safari inspect allowing to peak into the WebKit stage used in the Hype GUI.
https://forums.tumult.com/t/when-launching-the-beta-js-screen-appears-jscontext-window/11477?u=maxzieb

Interesting, this is a bug.

For the scene editor, we run the head html through a tidy process to ensure that mangled head html code won't interfere with editing. (Of course valid head html still can in many other ways!). The tidy method we use isn't smart enough to know about the <script> tag, and so is converting the for loop from:

for (i = 0; i < divs.length; ++i) {

to:

for (i = 0; i &lt; divs.length; ++i) {

This is invalid javascript, and therefore failing.

I thought this could still be done? Regardless, this is how I investigated:

defaults write com.tumult.Hype4 WebKitDeveloperExtras -bool YES
3 Likes

HURRAY! It's back… :heart:

This works :slight_smile: until it get's fixed… avoiding the symbol "<".

<script>
	setInterval(function(){
		var divs = document.querySelectorAll('div');
		for (i = 0; i != divs.length-1; ++i) {
			console.log (divs[i]);
			divs[i].style.setProperty('background-color', 'green', 'important');
		}
	},100);
	
</script>	

Bingo!

3 Likes

I am not sure what your plans are for the long run, but for the immediate future I’d appreciate some Hype tags like IE had back in the days (and a fixed parser!). This might just be really great…

<!--[if HYPE]>
This is rendered in the Hype GUI but will be stripped in the exports
<![endif]-->

Other solutions? Ideas? Having extended Symbol Bundles package all this would even be better (including them having a portion running on HypeDocumentLoad).

That may be the best way to do it… I was also looking into media queries with environment variables for CSS-specific cases but it doesn’t look like those are yet supported. For plugins specifically though I think it is fine if things are well defined – these are more of a case for standard CSS/JS that may interfere with a user’s experience but it is ultimately wanted.

1 Like

So I had a good nights sleep on the topic and what do you think about structuring the plugins around callbacks / events like the current event system (Hype‘s Observer Pattern).

So many of the same events would be triggered on an dedicated listener array specific to the IDE (like HypeSceneLoad and many more new and IDE specific etc.). The hypeDocument would contain a reference to a GUI specific API (in the long run with some modifiers maybe even registering custom GUI elements in the side panels or adding stuff to the stage that Hype then „knows“ about) and Element would contain essentially the target and Event as usual.

<!--[if HYPE]>
<script>

/* callbacks */
function onSceneSelected (hypeDocument, element, event) {...}
function onTimelineSelected (hypeDocument, element, event) {...}

/* Setup Hype IDE listeners */
if("HYPE_IDE_eventListeners" in window === false) { window.HYPE_IDE_eventListeners = Array();}
window.HYPE_IDE_eventListeners.push({"type":"HypeSceneLoad", "callback": onSceneSelected});
window.HYPE_IDE_eventListeners.push({"type":"HypeTimelineSelected", "callback": onTimelineSelected});

</script>
<![endif]-->

Hope this makes sense! Exciting.

By the way. The conditional tags could potentially also solve 3rd party issues by removing these bits when rendering the head HTML to the IDE WebKit-Instance. Note the negation with the not (!) exclamation !HYPE.

<!--[if !HYPE]>
<script src="https://someserver.tld/1.2.3/weirdLibrary.min.js"></script>
<![endif]-->

First attempt at a "full" IDE plugin…

2 Likes

Nice, I like this idea; makes sense.

It might be the case that plugins can be loaded/unloaded so there may need to be a bit more bookkeeping or formalization on the functions (say a plugin makes functions with a specific name it wants a callback to).

2 Likes

Not sure what your exactly thinking about? Maybe make an example with dummy code.

On my part I was thinking about any function we could call in the Hype IDE is accesible through an IDE-API much like the one already provided (hypeDocument.COMMAND). We can retrieve it on a document or scene level with an IDE init event callback. And then triggers stuff view with it (like adding Timelines, Elements, Keyframes) in the IDE.

In the other direction Hype emits event callbacks and notifies JS and we can react to things like (attribute changes, elements added, scene switched, timeline switched, keyframes added and fire our code and occasionally modify values or halt default execution with the return of the callback).

Just my limited perspective as I don't know anything about the setup your running, but I appreciated the ways things are done in the exported portion and how extensible this makes Hype already.

Much appreciated that this is on the table at all!

2 Likes

A structure like:


class MyPlugin {
   function sceneWillChange() {
     // ...
   }

   function sceneDidChange() {
     // ...
   }

   function playheadDidChange(time, timeline) {
     // ...
   }

   function loadInspectorItem(parentContainer) {
       //...
   }

   function elementNeedsReload(elm) {
       // ...
   }

Since everything is contained under a specific object, it can more easily be loaded/unloaded.

1 Like

Keeping in mind that a plugin consists of an portion that should be in the export and a portion that takes care of the preview in the editor… I was still under the impression we are talking about the "extended symbol" approach. So loading and unloading comes down to removing or adding that symbol in the library?

OR

are we now talking about a full fledged new entity called "plugin"? If we get a more powerful and dedicated plugin interface then I totally get it. Then the class would also define functions that return specific portions of code (or snippets of HTML, JS and CSS) it wants to run/include in the case of exports or previews in the IDE.

If plugins isn't just the extended symbol it might even take over some / all of the export logic callbacks currently in Python (and grandfather them). It could be potentially even better then the Python approach as it does allow state to carry over from call to call and is more accessible to all people familiar with JS. Meaning the class instance could potentially hold state across the entire export process.


If plugins is distinct from extended symbols the possibility to run code on DocumentLoad from a symbol level would still be very much appreciated.


Custom parameters / interface in the IDE for either Plugins or extended symbols is already achievable with the little used approach from the exporter scripts …

def document_arguments():
	return ["clickTag"];

def extra_actions():
	return [
		{"label" : "Ad Exit", "function" : "alert", "arguments":[{"label":"Alert", "type": "String"}]},
		{"label" : "Expand", "function" : "console.log", "arguments":[{"label":"1stMessage", "type": "Expression"}, {"label":"2ndMessage", "type": "String"}]}
	]

... so basically we would need that as an interface in the class or/and as some setting in extended symbols. Depending on the final approach.

I thought we were talking about a plugin system, not a symbol that has some associated IDE scripting abilities :slight_smile:.

But yes, there is overlap in some of the requirements of what a next-gen symbol, plugin, and export script require! One doesn't preclude the other for future plans.