From 74748acaafcc2be386f12bf490be677c30751337 Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 1 Jul 2024 16:07:25 -0700 Subject: [PATCH] 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! --- app/assets/stylesheets/items/_show.sass | 4 ++-- app/controllers/items_controller.rb | 14 ++++------- app/helpers/items_helper.rb | 2 +- app/models/item.rb | 1 + app/models/outfit.rb | 31 ++++++++++++++----------- app/views/items/show.html.haml | 7 ++---- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/app/assets/stylesheets/items/_show.sass b/app/assets/stylesheets/items/_show.sass index a546885d..26f5dafb 100644 --- a/app/assets/stylesheets/items/_show.sass +++ b/app/assets/stylesheets/items/_show.sass @@ -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 diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index ff6999a8..ff723610 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -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 diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index 7a4021b7..c77a9bb2 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -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 diff --git a/app/models/item.rb b/app/models/item.rb index 5739e082..3a3c6b37 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -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 diff --git a/app/models/outfit.rb b/app/models/outfit.rb index 15b43e75..5a293d83 100644 --- a/app/models/outfit.rb +++ b/app/models/outfit.rb @@ -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? diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 3fce6e3c..6db54aeb 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -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|