Orthographic View Builder

I am currently working on a tool to make building orthographic views sillier to this one by @nader.chinichian

I am soliciting some community feedback on a few questions I have to get some ideas.

If the original builder of the coordinate container happens to see this, I have mad respect for you because this thing is difficult! This is essentially a coordinate container with one extra feature, and boy is it not the most straight forward. lol

Screen Recording 2022-11-17 at 11.13.05 PM 5

Here is a link to a clearer video, because I had to tank the frame rate or its file size is too large.

Some comments:

  1. I plan on making some sort of "drag and drop" to add new views.
  2. The table is currently fully editable
  3. You toggle if something is affected by the perspective transforms with the blue checkbox.
  4. This will export as a json file that can be read by a view canvas that I will also package with this utility. So there will be an editor, and a viewer.
  5. I originally built this with pixels, then I changed it to percentages, at this point I am not sure which is better.
  6. In a perfect world I would make this a direct component in a module, but I can't do that until I convince IA to send me the code for the coordinate container so I don't have to recreate the wheel first. lol

My questions:

  1. What should I do when the view scales? Should I add a mode similar to the coordinate container where you can choose pixels or percentages so it will either scale or not?
  2. If the user wanted pixels, should I try to keep the content centered? I have no idea how to even do that since I can't grab the width of the view, just the page.
  3. Would anyone use this other than @nader.chinichian and my engineers??

I look forward to thoughts and opinions.

It looks pretty cool, but I'm not sure I would ever have a use-case. I'm interested in what yours is?

If you use python code for dragging it will be useless over internet as mouse movement events run on server side for every pixels and send back new position to the client. This is one of most important reason I always ask IA to support java script in perspective.

Really it started out because I had a client asking for some views like that, similar to this one:

I had an engineer I was teaching how to do it, and it just started to feel really tedious. It's a lot of bindings, handmade building, and it takes a while to get everything set up. So it was mostly a curiosity to see if I could streamline the design. I think that sexy UI like that is important and would continue to help Ignition stand out above the rest if it's even easier to implement. So I was trying to make it easier to implement.

This is purely just a design-time problem. The end-output is the two formatted view canvas instances properties, that you can toggle between as you select different components. Message handlers on the embedded wrapper view and the view canvas itself will automate the positioning. So everything happens without user interaction, and no python scripting involved.

I agree that python is a slow use-case for drag and drop, but if its only design-time then as long as you are working with a relatively local server its not a huge deal.

4 Likes

An update, for those curious:

I started prioritizing the "focus" feature that existed in @nader.chinichian original view.

Kapture 2022-12-01 at 12.37.27
(Ignore the choppiness, its the gif)

None of the embedded views on this page are aware they are wrapped inside the tool, so it doesn't require modifying existing views.

I do provide a perspective parameter to each one though, incase someone wanted to change visible content based off the current state.

The view builds everything out with one parameter called viewStates which is an array of the configured instances you want to visualize.

Here is the example shown above:

Example Parameters
[
  {
    "labels": [
      {
        "positions": {
          "flat": {
            "height": "10%",
            "left": "45%",
            "top": "10%",
            "width": "15%",
            "zIndex": 1
          },
          "perspective": {
            "height": "10%",
            "left": "20%",
            "top": "20%",
            "width": "15%",
            "zIndex": 1
          }
        },
        "text": "Top Example"
      },
      {
        "positions": {
          "flat": {
            "height": "10%",
            "left": "45%",
            "top": "80%",
            "width": "15%",
            "zIndex": 1
          },
          "perspective": {
            "height": "10%",
            "left": "35%",
            "top": "45%",
            "width": "15%",
            "zIndex": 1
          }
        },
        "viewParams": {
          "text": "Example View Label"
        },
        "viewPath": "TestLabel"
      }
    ],
    "name": "Floor Layout",
    "outline": "blue",
    "perspective": true,
    "positions": {
      "flat": {
        "height": "60%",
        "left": "17.2413793103%",
        "top": "19.9546485261%",
        "width": "60%",
        "zIndex": 0
      },
      "perspective": {
        "height": "30%",
        "left": "19.4252873563%",
        "top": "17.4603174603%",
        "width": "30%",
        "zIndex": 0
      }
    },
    "viewParams": {},
    "viewPath": "ExampleLayout"
  },
  {
    "labels": [
      {
        "positions": {
          "flat": {
            "height": "10%",
            "left": "45%",
            "top": "10%",
            "width": "15%",
            "zIndex": 1
          },
          "perspective": {
            "height": "10%",
            "left": "60%",
            "top": "60%",
            "width": "15%",
            "zIndex": 1
          }
        },
        "text": "Bottom Example"
      }
    ],
    "name": "Floor Layout",
    "outline": "red",
    "perspective": true,
    "positions": {
      "flat": {
        "height": "60%",
        "left": "17.2413793103%",
        "top": "19.9546485261%",
        "width": "60%",
        "zIndex": 0
      },
      "perspective": {
        "height": "30%",
        "left": "59.4252873563%",
        "top": "60%",
        "width": "30%",
        "zIndex": 0
      }
    },
    "viewParams": {},
    "viewPath": "ExampleLayout"
  }
]

Each instance takes the following parameters:

Instance Properties

Param Example Value Description
name "Floor Layout" So its easier to see which item you are looking at. The name isn't shown anywhere at this time
outline "blue" The outline color to add to the nested view group if enableOutlines is true on the parent. This is for development mostly
perspective true Whether or not to show this instance in the isomorphic state
positions { "flat": { "height": "60%", "left": "10%", "top": "20%", "width": "60%", "zIndex": 0 }, "perspective": { "height": "30%", "left": "20%", "top": "20%", "width": "30%", "zIndex": 0 } } The positions to use for the nested view group. The flat and perspective keys are used to determine which position to use based on the current state.
viewPath "MyFolder/MyView" The path to the main view to use for the nested view group.
viewParams { "text": "Example View Label" } The parameters to pass to the nested view groups main view.
labels [ { "positions": { "flat": { "height": "10%", "left": "45%", "top": "10%", "width": "15%", "zIndex": 1 }, "perspective": { "height": "10%", "left": "20%", "top": "20%", "width": "15%", "zIndex": 1 } }, "text": "Top Example" } ] An array of labels to add to the nested view group. Each label take will automatically trigger the focus for the view group when clicked.

Label Properties

Param Example Value Description
text "Top Example" The text to display on the label, this does not work if viewPath is not None
style { "fontSize": "20px", "color": "red" } An override to the labels default styling, this does not work if viewPath is set to None
positions { "flat": { "height": "10%", "left": "45%", "top": "10%", "width": "15%", "zIndex": 1 }, "perspective": { "height": "10%", "left": "20%", "top": "20%", "width": "15%", "zIndex": 1 } } The positions to use for the label. The flat and perspective keys are used to determine which position to use based on the current state.
viewPath "MyFolder/MyView" The path to a possible embedded view to use for the label.
viewParams { "text": "Example View Label" } The parameters to pass to the label view.

I will put this on the exchange and Github when I am done, just have not done so yet.

The next things I want to implement:

  1. The stacking feature that exists in @nader.chinichian original view
  2. A version of this that allows positioning with my original click-to-drag method, currently I did these ones by manually typing the positions
  3. Control over the desired aspect ratio, currently everything is locked into a 16:9 aspect ratio

I am open to ideas and feedback!

13 Likes