Refactor more of item outfit preview into the Outfit class

This is a cute thing that I think sets us up for other stuff down the
line: move more of the outfit appearance logic into the `Outfit` class!
Now, we set up the item page with a temporary instance of `Outfit`,
then ask for its `visible_layers`.

Still missing restricted-zones logic and such, that's next!
This commit is contained in:
Emi Matchu 2024-07-01 16:07:25 -07:00
parent 054c809052
commit 74748acaaf
6 changed files with 29 additions and 30 deletions

View file

@ -38,7 +38,7 @@ body.items-show
height: 16px
width: 16px
outfit-viewer
.outfit-viewer
position: relative
display: block
width: 300px
@ -49,7 +49,7 @@ body.items-show
margin: 0 auto .75em
outfit-layer
.outfit-layer
display: block
position: absolute
inset: 0

View file

@ -84,14 +84,10 @@ class ItemsController < ApplicationController
end
@selected_preview_pet_type = load_selected_preview_pet_type
@preview_pet_type = load_preview_pet_type
@item_layers = @item.appearance_for(
@preview_pet_type, swf_asset_includes: [:zone]
).swf_assets
@pet_layers = @preview_pet_type.canonical_pet_state.swf_assets.
includes(:zone)
@preview_outfit = Outfit.new(
pet_state: load_preview_pet_type.canonical_pet_state,
worn_items: [@item],
)
@preview_error = validate_preview
end
@ -227,7 +223,7 @@ class ItemsController < ApplicationController
def validate_preview
if @selected_preview_pet_type.new_record?
:pet_type_does_not_exist
elsif @item_layers.empty?
elsif @preview_outfit.item_appearances.values.any?(&:empty?)
:no_item_data
end
end

View file

@ -250,7 +250,7 @@ module ItemsHelper
end
def outfit_viewer_layer(swf_asset)
content_tag "outfit-layer", style: "z-index: #{swf_asset.zone.depth}" do
content_tag :div, class: "outfit-layer" do
image_tag swf_asset.image_url, alt: ""
end
end

View file

@ -557,6 +557,7 @@ class Item < ApplicationRecord
# bit more suited to it!
Appearance = Struct.new(:body, :swf_assets) do
include ActiveModel::Serializers::JSON
delegate :present?, :empty?, to: :swf_assets
def attributes
{body: body, swf_assets: swf_assets}
end

View file

@ -25,7 +25,12 @@ class Outfit < ApplicationRecord
before_validation :ensure_unique_name, if: :user_id?
attr_reader :biology
delegate :color, to: :pet_state
delegate :pose, to: :pet_state
delegate :pet_type, to: :pet_state
delegate :color, to: :pet_type
delegate :color_id, to: :pet_type
delegate :species, to: :pet_type
delegate :species_id, to: :pet_type
scope :wardrobe_order, -> { order('starred DESC', :name) }
@ -107,18 +112,6 @@ class Outfit < ApplicationRecord
)
end
def color_id
pet_state.pet_type.color_id
end
def species_id
pet_state.pet_type.species_id
end
def pose
pet_state.pose
end
def biology=(biology)
@biology = biology.slice(:species_id, :color_id, :pose, :pet_state_id)
@ -166,6 +159,18 @@ class Outfit < ApplicationRecord
self.item_outfit_relationships = new_relationships
end
def item_appearances(...)
Item.appearances_for(worn_item_ids, pet_type, ...)
end
def visible_layers
pet_layers = pet_state.swf_assets.includes(:zone)
item_layers = item_appearances(swf_asset_includes: [:zone]).values.
map(&:swf_assets).flatten
(pet_layers + item_layers).sort_by(&:depth)
end
def ensure_unique_name
# If no name was provided, start with "Untitled outfit".
self.name = "Untitled outfit" if name.blank?

View file

@ -14,11 +14,8 @@
sorry!
= turbo_frame_tag "item-preview" do
%outfit-viewer
%outfit-pet-appearance
= outfit_viewer_layers @pet_layers
%outfit-item-appearance
= outfit_viewer_layers @item_layers
.outfit-viewer
= outfit_viewer_layers @preview_outfit.visible_layers
= form_for item_path(@item), method: :get, class: "species-color-picker",
data: {"is-valid": @preview_error.nil?} do |f|