Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor legacy avalon and pype to AYON #14

Merged
merged 7 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions client/ayon_harmony/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@ Server/client now uses stricter protocol to handle communication. This is necess
| A | H | 0x00 | 0x00 | 0x00 | 0x00 | ...

```
First two bytes are *magic* bytes stands for **A**valon **H**armony. Next four bytes hold length of the message `...` encoded as 32bit unsigned integer. This way we know how many bytes to read from the socket and if we need more or we need to parse multiple messages.
First two bytes are *magic* bytes stands for **A**yon **H**armony. Next four bytes hold length of the message `...` encoded as 32bit unsigned integer. This way we know how many bytes to read from the socket and if we need more or we need to parse multiple messages.


## Usage

The integration creates an `Openpype` menu entry where all related tools are located.
The integration creates an `AYON` menu entry where all related tools are located.

**NOTE: Menu creation can be temperamental. The best way is to launch Harmony and do nothing else until Harmony is fully launched.**

### Work files

Because Harmony projects are directories, this integration uses `.zip` as work file extension. Internally the project directories are stored under `[User]/.avalon/harmony`. Whenever the user saves the `.xstage` file, the integration zips up the project directory and moves it to the Avalon project path. Zipping and moving happens in the background.
Because Harmony projects are directories, this integration uses `.zip` as work file extension. Internally the project directories are stored under `[User]/.ayon/harmony`. Whenever the user saves the `.xstage` file, the integration zips up the project directory and moves it to the AYON project path. Zipping and moving happens in the background.

### Show Workfiles on launch

Expand Down Expand Up @@ -94,20 +94,20 @@ print(harmony.send({"function": func, "args": ["Hello", "Python"]})["result"])

When naming your functions be aware that they are executed in global scope. They can potentially clash with Harmony own function and object names.
For example `func` is already existing Harmony object. When you call your function `func` it will overwrite in global scope the one from Harmony, causing
erratic behavior of Harmony. Openpype is prefixing those function names with [UUID4](https://docs.python.org/3/library/uuid.html) making chance of such clash minimal.
erratic behavior of Harmony. AYON is prefixing those function names with [UUID4](https://docs.python.org/3/library/uuid.html) making chance of such clash minimal.
See above examples how that works. This will result in function named `38dfcef0_a6d7_4064_8069_51fe99ab276e_hello()`.
You can find list of Harmony object and function in Harmony documentation.

### Higher level (recommended)

Instead of sending functions directly to Harmony, it is more efficient and safe to just add your code to `js/PypeHarmony.js` or utilize `{"script": "..."}` method.
Instead of sending functions directly to Harmony, it is more efficient and safe to just add your code to `js/AyonHarmony.js` or utilize `{"script": "..."}` method.

#### Extending PypeHarmony.js
#### Extending AyonHarmony.js

Add your function to `PypeHarmony.js`. For example:
Add your function to `AyonHarmony.js`. For example:

```javascript
PypeHarmony.myAwesomeFunction = function() {
AyonHarmony.myAwesomeFunction = function() {
someCoolStuff();
};
```
Expand All @@ -116,7 +116,7 @@ Then you can call that javascript code from your Python like:
```Python
import ayon_harmony.api as harmony

harmony.send({"function": "PypeHarmony.myAwesomeFunction"});
harmony.send({"function": "AyonHarmony.myAwesomeFunction"});

```

Expand Down Expand Up @@ -185,7 +185,7 @@ harmony.save_scene()
<details>
<summary>Click to expand for details on scene save.</summary>

Because Openpype tools does not deal well with folders for a single entity like a Harmony scene, this integration has implemented to use zip files to encapsulate the Harmony scene folders. Saving scene in Harmony via menu or CTRL+S will not result in producing zip file, only saving it from Workfiles will. This is because
Because AYON tools do not deal well with folders for a single entity like a Harmony scene, this integration has implemented to use zip files to encapsulate the Harmony scene folders. Saving scene in Harmony via menu or CTRL+S will not result in producing zip file, only saving it from Workfiles will. This is because
zipping process can take some time in which we cannot block user from saving again. If xstage file is changed during zipping process it will produce corrupted zip
archive.
</details>
Expand All @@ -196,7 +196,6 @@ These plugins were made with the [polly config](https://github.com/mindbender-st
#### Creator Plugin
```python
import ayon_harmony.api as harmony
from uuid import uuid4


class CreateComposite(harmony.Creator):
Expand Down Expand Up @@ -580,7 +579,7 @@ replace_files = """function %s_replace_files(args)

class ImageSequenceLoader(load.LoaderPlugin):
"""Load images
Stores the imported asset in a container named after the asset.
Stores the imported product in a container named after the product.
"""
product_types = {
"shot",
Expand Down
61 changes: 30 additions & 31 deletions client/ayon_harmony/api/TB_sceneOpened.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* global QTcpSocket, QByteArray, QDataStream, QTimer, QTextCodec, QIODevice, QApplication, include */
/* global QTcpSocket, QByteArray, QDataStream, QTimer, QTextCodec, QIODevice, QApplication, include */
/*
Avalon Harmony Integration - Client
AYON Harmony Integration - Client
-----------------------------------

This script implements client communication with Avalon server to bridge
This script implements client communication with AYON server to bridge
gap between Python and QtScript.

*/
Expand Down Expand Up @@ -274,7 +274,7 @@ function Client() {
self.socket.readyRead.connect(self.onReadyRead);
var app = QCoreApplication.instance();

app.avalonClient.send(
app.ayonClient.send(
{
'module': 'ayon_core.lib',
'method': 'emit_event',
Expand Down Expand Up @@ -342,7 +342,7 @@ function Client() {
}

/**
* Entry point, creating Avalon Client.
* Entry point, creating AYON Client.
*/
function start() {
var self = this;
Expand All @@ -354,9 +354,9 @@ function start() {
// Attach the client to the QApplication to preserve.
var app = QCoreApplication.instance();

if (app.avalonClient == null) {
app.avalonClient = new Client();
app.avalonClient.socket.connectToHost(host, port);
if (app.ayonClient == null) {
app.ayonClient = new Client();
app.ayonClient.socket.connectToHost(host, port);
}
var mainWindow = null;
var widgets = QApplication.topLevelWidgets();
Expand All @@ -367,26 +367,25 @@ function start() {
}
var menuBar = mainWindow.menuBar();
var actions = menuBar.actions();
app.avalonMenu = null;
app.ayonMenu = null;

for (var i = 0 ; i < actions.length; i++) {
label = System.getenv('AYON_MENU_LABEL');
if (actions[i].text == label) {
app.avalonMenu = true;
app.ayonMenu = true;
}
}

var menu = null;
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
menu = menuBar.addMenu(System.getenv('AYON_MENU_LABEL'));
}
// menu = menuBar.addMenu('Avalon');

/**
* Show creator
*/
self.onCreator = function() {
app.avalonClient.send({
app.ayonClient.send({
'module': 'ayon_harmony.api.lib',
'method': 'show',
'args': ['creator']
Expand All @@ -401,13 +400,13 @@ function start() {
* Show Workfiles
*/
self.onWorkfiles = function() {
app.avalonClient.send({
app.ayonClient.send({
'module': 'ayon_harmony.api.lib',
'method': 'show',
'args': ['workfiles']
}, false);
};
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
action = menu.addAction('Workfiles...');
action.triggered.connect(self.onWorkfiles);
}
Expand All @@ -416,14 +415,14 @@ function start() {
* Show Loader
*/
self.onLoad = function() {
app.avalonClient.send({
app.ayonClient.send({
'module': 'ayon_harmony.api.lib',
'method': 'show',
'args': ['loader']
}, false);
};
// add Loader item to menu
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
action = menu.addAction('Load...');
action.triggered.connect(self.onLoad);
}
Expand All @@ -432,14 +431,14 @@ function start() {
* Show Publisher
*/
self.onPublish = function() {
app.avalonClient.send({
app.ayonClient.send({
'module': 'ayon_harmony.api.lib',
'method': 'show',
'args': ['publish']
}, false);
};
// add Publisher item to menu
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
action = menu.addAction('Publish...');
action.triggered.connect(self.onPublish);
}
Expand All @@ -448,14 +447,14 @@ function start() {
* Show Scene Manager
*/
self.onManage = function() {
app.avalonClient.send({
app.ayonClient.send({
'module': 'ayon_harmony.api.lib',
'method': 'show',
'args': ['sceneinventory']
}, false);
};
// add Scene Manager item to menu
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
action = menu.addAction('Manage...');
action.triggered.connect(self.onManage);
}
Expand All @@ -464,14 +463,14 @@ function start() {
* Show Subset Manager
*/
self.onSubsetManage = function() {
app.avalonClient.send({
app.ayonClient.send({
'module': 'ayon_harmony.api.lib',
'method': 'show',
'args': ['subsetmanager']
}, false);
};
// add Subset Manager item to menu
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
action = menu.addAction('Subset Manager...');
action.triggered.connect(self.onSubsetManage);
}
Expand All @@ -480,7 +479,7 @@ function start() {
* Set scene settings from DB to the scene
*/
self.onSetSceneSettings = function() {
app.avalonClient.send(
app.ayonClient.send(
{
"module": "ayon_harmony.api",
"method": "ensure_scene_settings",
Expand All @@ -490,7 +489,7 @@ function start() {
);
};
// add Set Scene Settings
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
action = menu.addAction('Set Scene Settings...');
action.triggered.connect(self.onSetSceneSettings);
}
Expand All @@ -499,14 +498,14 @@ function start() {
* Show Experimental dialog
*/
self.onExperimentalTools = function() {
app.avalonClient.send({
app.ayonClient.send({
'module': 'ayon_harmony.api.lib',
'method': 'show',
'args': ['experimental_tools']
}, false);
};
// add Subset Manager item to menu
if (app.avalonMenu == null) {
if (app.ayonMenu == null) {
action = menu.addAction('Experimental Tools...');
action.triggered.connect(self.onExperimentalTools);
}
Expand All @@ -519,10 +518,10 @@ function start() {
app.onFileChanged = function(path)
{
var app = QCoreApplication.instance();
if (app.avalonOnFileChanged){
app.avalonClient.send(
if (app.ayonOnFileChanged){
app.ayonClient.send(
{
'module': 'avalon.harmony.lib',
'module': 'ayon.harmony.lib',
'method': 'on_file_changed',
'args': [path]
},
Expand All @@ -538,7 +537,7 @@ function start() {
scene_path = scene.currentProjectPath() +"/" + scene.currentVersionName() + ".xstage";
app.watcher.addPath(scenePath);
app.watcher.fileChanged.connect(app.onFileChanged);
app.avalonOnFileChanged = true;
app.ayonOnFileChanged = true;
*/
app.onFileChanged = function(path) {
// empty stub
Expand All @@ -548,7 +547,7 @@ function start() {

function ensureSceneSettings() {
var app = QCoreApplication.instance();
app.avalonClient.send(
app.ayonClient.send(
{
"module": "ayon_harmony.api",
"method": "ensure_scene_settings",
Expand Down
4 changes: 2 additions & 2 deletions client/ayon_harmony/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
application_launch,
export_template,
on_pyblish_instance_toggled,
inject_avalon_js,
inject_ayon_js,
)

from .lib import (
Expand Down Expand Up @@ -61,7 +61,7 @@
"application_launch",
"export_template",
"on_pyblish_instance_toggled",
"inject_avalon_js",
"inject_ayon_js",

# lib
"launch",
Expand Down
Loading
Loading