Scene Graph - Editor behavior that easily becomes the source of bugs

Summary

The editor behavior of components is somewhat incorrect compared to what you would normally get statically flagged at compile time in code.

Some of it was mentioned in the following report but none of it was actually addressed: [Major] Many `@editable` values cannot be set any more (Scene Graph)

Please select what you are reporting on:

Unreal Editor for Fortnite

What Type of Bug are you experiencing?

UI/Tools

Steps to Reproduce

Here’s the code to reproduce the behaviors.

vz_test_non_concrete_editables_component := class<final><final_super>(component) {
  @editable
  ENonConcrete: vz_non_concrete_class

  @editable
  ESetNonConcrete: vz_non_concrete_class = vz_non_concrete_class { Number := 42 }

  @editable
  EOptionalNonConcrete: ?vz_non_concrete_class

  @editable
  ESetOptionalNonConcrete: ?vz_non_concrete_class = false

  @editable
  ENonConcreteArray: []vz_non_concrete_class
}

vz_non_concrete_class := class {
  @editable
  Number: int
}

Expected Result

  • NonConcrete field should say Set to Value
  • EOptionalNonConcrete field’s drop down options should present None as an option
  • ESetOptionalNonConcrete should be set to None
  • All fields that have no default value in code should have NO default value assigned by the editor, regardless of the type being concrete (source of bugs). Therefore the Number field should say Set to Value instead of 0.
  • Index [...] element of ENonConcreteArray should not default to the base class.
  • When a value is not set, it should say Set to Value instead of None. None should be reserved for representing false of an optional type of if potentially an enum with an explicit None case.

Observed Result

  • ENonConcrete field says None, but it really should be saying Set to Value
  • EOptionalNonConcrete field correctly says Set to Value but the drop down menu does not provide the None as an option. The type is ?vz_non_concrete_class so false aka None should be an option
  • ESetOptionalNonConcrete incorrectly says Set to Value, but it really should say None as the value is explicitly set in code to false
  • ENonConcreteArray automatically assumes we want to use the vz_non_concrete_class class as its new element even if there could be more subclasses. Additionally if we set the the type to the class, all concrete fields are automatically initialized with a default value, this is a source of bugs. In code initialization process is explicit for a good reason and types without a value, even if they are concrete cannot be omitted from the explicit user written initialization process. The editor circumvents this by giving types that are concrete a sort of “convenience”, but in reality this will lead to wrongly / unintentionally set values when using the editor workflow.

Platform(s)

PC / UEFN

cc @Vath

1 Like

(Fowarded from an outside-forum conversation)

Basically, comparing “current” to “expected” editable behaviors:

  1. some_property (non concrete reference to property):
    —> Currently is “None”, which is misleading and confusing comparing to other scenarios;
    —> The expected should be “Set to Value”, since the concrete value needs to be set and can’t be left unset;

  2. ?some_property (non concrete optional reference to property):
    —> Currently is “Set to Value”, wich is fine and coherent to understand (This is Ok);
    —> Currently after setting the value to something, the optional can’t be set back to “Blank/None/false”;
    —> The expected should be after setting to value, displaying “None” (blank/false optional) in a dropdown, together with other possible value selector options;

  3. ?some_property = false (concrete optional reference initialized as blank/false):
    —> Currently is “Set to Value”, which is confusing and not coherent comparing to other scenarios;
    —> The expected should be None, meaning that the value is set, but the editable is blank/false;

  4. []some_class (non concrete array of some class type):
    —> Currently when adding a element to the array, the element is defaulted to the base class type (some_class) on this example, which is confusing and prone to errors on the user configuration;
    —> The expected should display the new array element as “Set to Value”, and then the user hand-picking a base class to derivate from it on. (such as ex. child_class);

  5. class_with_properties (non concrete reference to a non concrete class):
    —> Currently when setting it to a value, it will auto-fill all the class properties with “default” values that doesn’t exist (such as MyInt : int gets defaulted to 0 or MyString : string to ""). This is not supposed to happen and prone to cause errors when working with editables, due to it auto-setting wrong values that may cause diferent functionality on the component logic;
    —> The expected should be all class fields being unitialized, displaying as “Set to Value”, without pre-filling it at all;

some_class := class{}
child_class := class(some_class){}

class_with_properties := class {
    @editable
    MyInt : int
    @editable
    MyString : string
    @editable
    MyFloat : float
    @editable
    MyLogic : logic
    @editable
    MyColor : color
}

my_class := class {
    @editable # `some_property` example
    MyValue0 : int

    @editable # `?some_property` example
    MyValue1 : ?int

    @editable # `?some_property = false` example
    MyValue2 : ?int = false

    @editable # `[]some_class` example
    MyValue3 : []some_class

    @editable # `class_with_properties` example
    MyValue4 : class_with_properties
}
Property1: some_type          # Should never prefill with a default value when the type is `concrete`, should always display `set to value`
Property2: ?some_type         # Should display `set to value` -> dropdown should present a list of options where `None` is the top most option
Property3: ?some_type = false # Should display `None` -> dropdown should present a list of options where `None` is the top most option
Property4: []some_type        # Should display `set to value` -> initial interaction should make it EMPTY -> any new elements should provide a list of `some_type` subtype options, any `some_type` properties should never prefill with value just like `Property1` unless they already have a default value in code

Regarding a potential collision with an enum that has a None case of its own.

some_enum := enum {
  None
  Something
}

Just display a dropdown menu which has a clear hairline to partition the two sets of possible values. This should apply to any ?some_type and ?some_type = false values.

None            <- represents `false` value 
--------------- <- hairline
None            <- `some_enum.None`
Something       <- `some_enum.Something`

In case of ?some_class:

None
---------------
some_class
some_other_subclasses

In case of ?int

None
---------------
int             <- display the type

When int is picked present an empty textbox, DO NOT prefill with 0 as a default value, keep the value still uninitialized, but the editor already would know that the user wants to set an actual integer here. Keep presenting the red :warning: symbol until the value is actually properly set by the user.

FORT-901741 has been added to our ‘To Do’ list. Someone’s been assigned this task.