using { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /Verse.org/Simulation/Tags } using { /Verse.org/Assets } using { /UnrealEngine.com/Temporary/Diagnostics } # CHANGE THE CAR'S COLOURS — Part 2 of "Scene Graph: Car Primitive". # # Players love a colour swap. The honest truth about Verse + materials in build # 41.00: there is NO public per-parameter API. `material.SetColorProperty` / # `SetFloatProperty` exist but are Epic-internal, and there is no # `SetVectorParameter` / `material_parameter_collection` / `dynamic_material` # anywhere in the public surface. What a creator CAN do is swap the WHOLE # material on a placed prop with one public call: # # creative_prop.SetMaterial(Material : material, ?Index : int) # # So the recipe is: author a few material assets (a red paint, a blue paint, a # gold paint), expose them as `@editable ?material` slots, and cycle through them # on a button press. Same car body, instant new paint job. # # Note the `?material` (optional) type: the `material` class is Epic-internal and # cannot be constructed with `material{}`, so a concrete device can't give it a # plain default. Declaring the slot as `?material = false` is the idiom — the # editor fills it in, and Verse unwraps it with `Paint?`. car_body_tag := class(tag) {} car_paint_button_tag := class(tag) {} car_material_colors_device := class(creative_device): # Three paint-job materials. Drop a Material asset into each slot in the # Details panel (any material works — these are whole-material swaps, not # colour tweaks). @editable PaintA : ?material = false @editable PaintB : ?material = false @editable PaintC : ?material = false # Which paint is showing now (0,1,2 -> A,B,C). `var` so we can advance it. var PaintIndex : int = 0 OnBegin() : void = for (Obj : FindCreativeObjectsWithTag(car_paint_button_tag)): if (Button := button_device[Obj]): Button.InteractedWithEvent.Subscribe(OnPaintPressed) Print("CarColors: paint button wired.") OnPaintPressed(Agent : agent) : void = # Advance to the next paint, wrapping 2 -> 0. Mod can fail (decides), so # compute it in its own failure context, then assign. if (Next := Mod[PaintIndex + 1, 3]): set PaintIndex = Next # Pick the matching paint slot and repaint, only if that slot is # filled. Each branch unwraps its own optional (Paint?) in the if. if (PaintIndex = 0, Paint := PaintA?): ApplyPaint(Paint) else if (PaintIndex = 1, Paint := PaintB?): ApplyPaint(Paint) else if (Paint := PaintC?): ApplyPaint(Paint) # Repaint every tagged car body by swapping its whole material slot 0. ApplyPaint(Paint : material) : void = for (Obj : FindCreativeObjectsWithTag(car_body_tag)): if (Body := creative_prop[Obj]): Body.SetMaterial(Paint, ?Index := 0) Print("CarColors: repainted the car.")